aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanisław Zagórowski <hasohasacz@gmail.com>2024-01-11 16:23:45 +0100
committerStanisław Zagórowski <hasohasacz@gmail.com>2024-01-11 16:23:45 +0100
commitf45abfdf2150d8136e3da48e1daba5473030c0be (patch)
treea2dde05dd3577564bbdce51b847819d7ee12cc43
parent377a5a136d53bd91736a1dfbd418235d3b6b7462 (diff)
reorganize and prettify
-rw-r--r--Cargo.lock72
-rw-r--r--Cargo.toml3
-rw-r--r--src/luax/mod.rs67
-rw-r--r--src/main.rs166
-rw-r--r--src/server.rs11
5 files changed, 236 insertions, 83 deletions
diff --git a/Cargo.lock b/Cargo.lock
index cc7f64a..f5df680 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -93,6 +93,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
+name = "bitflags"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+
+[[package]]
name = "bstr"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -202,6 +208,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
+name = "errno"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
name = "eyre"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -212,6 +228,12 @@ dependencies = [
]
[[package]]
+name = "fastrand"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+
+[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -417,6 +439,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
[[package]]
+name = "linux-raw-sys"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
+
+[[package]]
name = "memchr"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -519,6 +547,15 @@ dependencies = [
]
[[package]]
+name = "redox_syscall"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
+[[package]]
name = "reluax"
version = "0.1.0"
dependencies = [
@@ -528,6 +565,7 @@ dependencies = [
"hyper",
"hyper-util",
"rlua",
+ "tempfile",
"tokio",
"utf8-read",
]
@@ -538,18 +576,18 @@ version = "0.19.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d33e5ba15c3d43178f283ed5863d4531e292fc0e56fb773f3bea45f18e3a42a"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"bstr",
"libc",
"num-traits",
- "rlua-lua54-sys",
+ "rlua-lua51-sys",
]
[[package]]
-name = "rlua-lua54-sys"
+name = "rlua-lua51-sys"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7aafabafe1895cb4a2be81a56d7ff3d46bf4b5d2f9cfdbea2ed404cdabe96474"
+checksum = "5c8f4636b03fa54b5c154415f1d9333cec7a7e3bd6bc64c092a2196e488cfd52"
dependencies = [
"cc",
"libc",
@@ -563,6 +601,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
+name = "rustix"
+version = "0.38.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
+dependencies = [
+ "bitflags 2.4.1",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -608,6 +659,19 @@ dependencies = [
]
[[package]]
+name = "tempfile"
+version = "3.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "redox_syscall",
+ "rustix",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
name = "thread_local"
version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 46ee34d..d99526c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,6 +11,7 @@ color-eyre = "0.6.2"
http-body-util = "0.1.0"
hyper = { version = "1.1.0", features = ["http1", "http2", "server"] }
hyper-util = { version = "0.1.2", features = ["http1", "http2", "server", "tokio"] }
-rlua = "0.19.7"
+rlua = { version = "0.19.7", default-features = false, features = ["system-luajit"] }
+tempfile = "3.9.0"
tokio = { version = "1.35.1", features = ["macros", "rt-multi-thread"] }
utf8-read = "0.4.0"
diff --git a/src/luax/mod.rs b/src/luax/mod.rs
index df9f57d..2e6fe27 100644
--- a/src/luax/mod.rs
+++ b/src/luax/mod.rs
@@ -1,4 +1,4 @@
-use crate::Result;
+use crate::{error::LuaXError, Result};
mod lexer;
mod preprocessor;
@@ -6,6 +6,63 @@ mod preprocessor;
mod tests;
mod tokens;
+pub fn table_to_html<W: std::io::Write>(table: rlua::Table, f: &mut W) -> Result<()> {
+ let type_name: Option<String> = table.get("tag").unwrap();
+
+ if type_name.is_none() {
+ return Err(LuaXError::MissingField("tag".to_string()).into());
+ }
+
+ let type_name = type_name.unwrap();
+
+ write!(f, "<{}", type_name)?;
+ let mut children = None;
+ let mut attrs = None;
+ for pair in table.pairs::<String, rlua::Value>() {
+ let (key, value) = pair?;
+ if key == "tag" {
+ continue;
+ }
+ if key == "children" {
+ children = Some(value);
+ continue;
+ }
+ if key == "attrs" {
+ attrs = Some(value);
+ continue;
+ }
+ }
+ if let Some(attrs) = attrs {
+ if let rlua::Value::Table(attrs) = attrs {
+ for pair in attrs.pairs::<String, rlua::String>() {
+ let (key, value) = pair?;
+ write!(f, " {}=\"{}\"", key, value.to_str()?)?;
+ }
+ } else {
+ return Err(LuaXError::NonTableAttrs.into());
+ }
+ }
+ write!(f, ">")?;
+
+ if let Some(children) = children {
+ if let rlua::Value::Table(children) = children {
+ for child in children.sequence_values::<rlua::Value>() {
+ match child? {
+ rlua::Value::Table(child) => table_to_html(child, f)?,
+ rlua::Value::String(s) => write!(f, "{}", s.to_str()?)?,
+ _ => return Err(LuaXError::NonTableChildren.into()),
+ }
+ }
+ } else {
+ return Err(LuaXError::NonTableChildren.into());
+ }
+ }
+
+ write!(f, "</{}>", type_name)?;
+
+ Ok(())
+}
+
pub fn preprocess(s: &str) -> Result<String> {
let mut buf = Vec::new();
let preprocessor = preprocessor::Preprocessor::new(s, &mut buf)?;
@@ -17,12 +74,13 @@ pub fn preprocess(s: &str) -> Result<String> {
Ok(s)
}
-pub fn preprocess_dir(path: &std::path::Path) -> Result<()> {
+pub fn preprocess_dir(path: &std::path::Path) -> Result<usize> {
+ let mut preprocessed = 0;
for entry in std::fs::read_dir(path)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
- preprocess_dir(&path)?;
+ preprocessed += preprocess_dir(&path)?;
} else {
if path.extension().unwrap_or_default() != "luax" {
continue;
@@ -33,8 +91,9 @@ pub fn preprocess_dir(path: &std::path::Path) -> Result<()> {
let out_path = path.with_extension("lua");
std::fs::write(out_path, s)?;
+ preprocessed += 1;
}
}
- Ok(())
+ Ok(preprocessed)
}
diff --git a/src/main.rs b/src/main.rs
index 466ffbc..f4d06ce 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,76 +1,20 @@
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use clap::Parser;
-use color_eyre::Result;
-use error::{LuaXError, ReluaxError};
+use color_eyre::{owo_colors::OwoColorize, Result};
mod error;
mod luax;
mod server;
-fn table_to_html<W: std::io::Write>(table: rlua::Table, f: &mut W) -> Result<()> {
- let type_name: Option<String> = table.get("tag").unwrap();
-
- if type_name.is_none() {
- return Err(ReluaxError::LuaX(LuaXError::MissingField("tag".to_string())).into());
- }
-
- let type_name = type_name.unwrap();
-
- write!(f, "<{}", type_name)?;
- let mut children = None;
- let mut attrs = None;
- for pair in table.pairs::<String, rlua::Value>() {
- let (key, value) = pair?;
- if key == "tag" {
- continue;
- }
- if key == "children" {
- children = Some(value);
- continue;
- }
- if key == "attrs" {
- attrs = Some(value);
- continue;
- }
- }
- if let Some(attrs) = attrs {
- if let rlua::Value::Table(attrs) = attrs {
- for pair in attrs.pairs::<String, rlua::String>() {
- let (key, value) = pair?;
- write!(f, " {}=\"{}\"", key, value.to_str()?)?;
- }
- } else {
- return Err(ReluaxError::LuaX(LuaXError::NonTableAttrs).into());
- }
- }
- write!(f, ">")?;
-
- if let Some(children) = children {
- if let rlua::Value::Table(children) = children {
- for child in children.sequence_values::<rlua::Value>() {
- match child? {
- rlua::Value::Table(child) => table_to_html(child, f)?,
- rlua::Value::String(s) => write!(f, "{}", s.to_str()?)?,
- _ => return Err(ReluaxError::LuaX(LuaXError::NonTableChildren).into()),
- }
- }
- } else {
- return Err(ReluaxError::LuaX(LuaXError::NonTableChildren).into());
- }
- }
-
- write!(f, "</{}>", type_name)?;
-
- Ok(())
-}
-
#[derive(Debug, Clone, clap::Parser)]
struct Args {
#[clap(short = 'C', long = "current-dir", default_value = ".")]
current_dir: std::path::PathBuf,
#[clap(short = 'p', long = "port", default_value = "4310")]
port: u16,
+ #[clap(short = 'l', long = "local", default_value = "false")]
+ local: bool,
}
#[tokio::main]
@@ -78,22 +22,86 @@ async fn main() -> color_eyre::Result<()> {
color_eyre::install().unwrap();
let args = Args::parse();
- let current_dir = args.current_dir;
+ if !args.current_dir.is_dir() {
+ return Err(std::io::Error::new(
+ std::io::ErrorKind::NotFound,
+ format!("{} is not a directory", args.current_dir.display()),
+ )
+ .into());
+ }
+
+ println!(
+ "🌴 Project root: {}",
+ args.current_dir.display().bright_yellow()
+ );
+
+ if args.local {
+ local(args).await
+ } else {
+ temp(args).await
+ }
+}
+
+async fn local(args: Args) -> Result<()> {
+ println!("🌴 Running in local mode");
+ std::env::set_current_dir(&args.current_dir)?;
+ preprocess_current_dir().await?;
+
+ ensure_entry_point().await?;
+
+ serve(args).await
+}
+
+async fn temp(args: Args) -> Result<()> {
+ // Create a /tmp/reluax-XXXXXX directory for the server to pre-process files in.
+ let tmp_dir = tempfile::Builder::new()
+ .prefix("reluax-")
+ .tempdir()
+ .unwrap();
- if !current_dir.is_dir() {
+ if !tmp_dir.path().is_dir() {
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
- format!("{} is not a directory", current_dir.display()),
+ format!("{} is not a directory", tmp_dir.path().display()),
)
.into());
}
+ println!(
+ "⏲️ Created temporary directory {}",
+ tmp_dir.path().display().bright_blue()
+ );
- std::env::set_current_dir(current_dir)?;
+ println!(
+ "⏲️ Will serve from {}",
+ tmp_dir.path().display().bright_blue()
+ );
+
+ // copy all files from the current directory to the temporary directory recursively.
+ let copied = recurse_copy(&args.current_dir, tmp_dir.path())?;
+
+ println!("⏲️ {} files copied", copied.bright_green());
+
+ std::env::set_current_dir(tmp_dir.path())?;
+
+ preprocess_current_dir().await?;
+
+ ensure_entry_point().await?;
+
+ serve(args).await
+}
- luax::preprocess_dir(std::env::current_dir()?.as_path())?;
+async fn preprocess_current_dir() -> Result<()> {
+ let preprocessed = luax::preprocess_dir(std::env::current_dir()?.as_path())?;
- println!("⛱️ Reluax files preprocessed!");
+ println!(
+ "⛱️ {} Reluax files preprocessed!",
+ preprocessed.bright_green()
+ );
+ Ok(())
+}
+
+async fn ensure_entry_point() -> Result<()> {
let entry = PathBuf::from("reluax.lua");
if !entry.is_file() {
@@ -104,7 +112,29 @@ async fn main() -> color_eyre::Result<()> {
.into());
}
- server::Server::serve(args.port).await?;
-
Ok(())
}
+
+async fn serve(args: Args) -> Result<()> {
+ server::Server::serve(args.port).await
+}
+
+fn recurse_copy(from: &Path, to: &Path) -> Result<usize> {
+ let mut copied = 0;
+ for entry in std::fs::read_dir(from)? {
+ let entry = entry?;
+ let path = entry.path();
+ let file_name = path.file_name().unwrap();
+ let to = to.join(file_name);
+
+ if path.is_dir() {
+ std::fs::create_dir(&to)?;
+ copied += recurse_copy(&path, &to)?;
+ } else {
+ std::fs::copy(&path, &to)?;
+ copied += 1;
+ }
+ }
+
+ Ok(copied)
+}
diff --git a/src/server.rs b/src/server.rs
index 4e3812f..106f9f8 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -12,10 +12,12 @@ use hyper_util::rt::TokioIo;
use tokio::net::TcpListener;
use crate::error::ReluaxError;
-use crate::{table_to_html, Result};
+use crate::luax::table_to_html;
+use color_eyre::Result;
use rlua::Lua;
pub struct Server {
+ port: u16,
lua: Arc<Mutex<Lua>>,
}
@@ -23,20 +25,17 @@ struct State {
lua: Arc<Mutex<Lua>>,
}
-static PORT: std::sync::OnceLock<u16> = std::sync::OnceLock::new();
-
impl Server {
pub async fn serve(port: u16) -> Result<()> {
- PORT.set(port).unwrap();
-
let server = Self {
+ port,
lua: Arc::new(Mutex::new(Lua::new())),
};
server.start().await
}
async fn start(self) -> Result<()> {
- let addr = SocketAddr::from(([127, 0, 0, 1], *PORT.get().unwrap()));
+ let addr = SocketAddr::from(([127, 0, 0, 1], self.port));
let listener = TcpListener::bind(addr).await?;
loop {