Daily update. Wrote some mtgott tests, fixed some bugs
This commit is contained in:
parent
9ce0e602b3
commit
7f30675aab
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
target
|
target
|
||||||
.idea
|
.idea
|
||||||
src/bin/PRIKOL.rs
|
src/bin/sandbox.rs
|
||||||
|
sandbox
|
||||||
155
Cargo.lock
generated
155
Cargo.lock
generated
@ -86,15 +86,6 @@ dependencies = [
|
|||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "block-buffer"
|
|
||||||
version = "0.10.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
|
||||||
dependencies = [
|
|
||||||
"generic-array",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.10.1"
|
version = "1.10.1"
|
||||||
@ -107,35 +98,6 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cpufeatures"
|
|
||||||
version = "0.2.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crypto-common"
|
|
||||||
version = "0.1.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
|
||||||
dependencies = [
|
|
||||||
"generic-array",
|
|
||||||
"typenum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "digest"
|
|
||||||
version = "0.10.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
|
||||||
dependencies = [
|
|
||||||
"block-buffer",
|
|
||||||
"crypto-common",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@ -184,16 +146,6 @@ dependencies = [
|
|||||||
"pin-utils",
|
"pin-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "generic-array"
|
|
||||||
version = "0.14.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
|
||||||
dependencies = [
|
|
||||||
"typenum",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.31.1"
|
version = "0.31.1"
|
||||||
@ -287,17 +239,6 @@ version = "1.0.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "json5"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1"
|
|
||||||
dependencies = [
|
|
||||||
"pest",
|
|
||||||
"pest_derive",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.171"
|
version = "0.2.171"
|
||||||
@ -373,51 +314,6 @@ version = "2.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pest"
|
|
||||||
version = "2.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
"thiserror",
|
|
||||||
"ucd-trie",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pest_derive"
|
|
||||||
version = "2.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5"
|
|
||||||
dependencies = [
|
|
||||||
"pest",
|
|
||||||
"pest_generator",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pest_generator"
|
|
||||||
version = "2.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841"
|
|
||||||
dependencies = [
|
|
||||||
"pest",
|
|
||||||
"pest_meta",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pest_meta"
|
|
||||||
version = "2.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0"
|
|
||||||
dependencies = [
|
|
||||||
"once_cell",
|
|
||||||
"pest",
|
|
||||||
"sha2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@ -520,17 +416,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sha2"
|
|
||||||
version = "0.10.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"cpufeatures",
|
|
||||||
"digest",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
@ -564,26 +449,6 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
|
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror"
|
|
||||||
version = "2.0.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror-impl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-impl"
|
|
||||||
version = "2.0.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.44.2"
|
version = "1.44.2"
|
||||||
@ -658,30 +523,12 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typenum"
|
|
||||||
version = "1.18.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ucd-trie"
|
|
||||||
version = "0.1.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "version_check"
|
|
||||||
version = "0.9.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
@ -766,8 +613,6 @@ name = "yyyi_ru"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"json5",
|
|
||||||
"mtgott",
|
"mtgott",
|
||||||
"serde_json",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "yyyi_ru"
|
name = "yyyi_ru"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = "0.8.3"
|
axum = "0.8.3"
|
||||||
tokio = { version = "1.44.1", features = ["rt-multi-thread"] }
|
tokio = { version = "1.44.1", features = ["rt-multi-thread"] }
|
||||||
json5 = "0.4.1"
|
|
||||||
serde_json = "1.0.140"
|
|
||||||
mtgott = { path = "./mtgott" }
|
mtgott = { path = "./mtgott" }
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
{% import "lang_macro.html" as lang_macro %}
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let func : & dyn for<'a> Fn(& 'a u32) -> &'a u32;
|
|
||||||
func = &|u: &u32| -> &u32 {u};
|
|
||||||
let y = 6u32;
|
|
||||||
println!("{}", func(&y));
|
|
||||||
}
|
|
||||||
@ -12,7 +12,7 @@ use std::rc::Rc;
|
|||||||
pub fn search_dir_rec_helper(
|
pub fn search_dir_rec_helper(
|
||||||
res: &mut Vec<Vec<String>>,
|
res: &mut Vec<Vec<String>>,
|
||||||
fs_path: PathBuf, virtual_path: String,
|
fs_path: PathBuf, virtual_path: String,
|
||||||
allowed_extensions: &[&str], is_valid_name: fn(&str) -> bool, recc: u32
|
allowed_extensions: &[&str], is_valid_name: &dyn Fn(&str) -> bool, recc: u32
|
||||||
)-> Result<(), Box<dyn Error>> {
|
)-> Result<(), Box<dyn Error>> {
|
||||||
if recc == 0 { return Err("Recursion limit exceeded".into()); }
|
if recc == 0 { return Err("Recursion limit exceeded".into()); }
|
||||||
let fs_path = canonicalize(fs_path)?;
|
let fs_path = canonicalize(fs_path)?;
|
||||||
@ -45,65 +45,87 @@ pub fn search_dir_rec_helper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn search_dir(
|
pub fn search_dir(
|
||||||
p: &str, allowed_extensions: &[&str], is_valid_name: fn(&str) -> bool)
|
p: &str, allowed_extensions: &[&str], is_valid_name: &dyn Fn(&str) -> bool)
|
||||||
-> Result<Vec<Vec<String>>, Box<dyn Error>> {
|
-> Result<Vec<Vec<String>>, Box<dyn Error>> {
|
||||||
let mut res: Vec<Vec<String>> = (0..allowed_extensions.len()).map(|_| Vec::new()).collect();
|
let mut res: Vec<Vec<String>> = (0..allowed_extensions.len()).map(|_| Vec::new()).collect();
|
||||||
search_dir_rec_helper(&mut res, PathBuf::from(p), String::new(), allowed_extensions, is_valid_name, 100)?;
|
search_dir_rec_helper(&mut res, PathBuf::from(p), String::new(), allowed_extensions, is_valid_name, 100)?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MtgottDirContent {
|
pub struct MtgottDirFiles {
|
||||||
mtgott: Vec<String>,
|
pub mtgott: Vec<String>,
|
||||||
imtgott: Vec<String>,
|
pub imtgott: Vec<String>,
|
||||||
plain: Vec<String>
|
pub plain: Vec<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search_mtgott_dir(p: &str, plain_ext: &str) -> Result<MtgottDirContent, Box<dyn Error>> {
|
pub fn search_mtgott_dir(p: &str, plain_ext: &str) -> Result<MtgottDirFiles, Box<dyn Error>> {
|
||||||
let mut all = search_dir(p, &[
|
let mut all = search_dir(p, &[
|
||||||
&(String::from(".mtgott") + plain_ext),
|
&(String::from(".mtgott") + plain_ext),
|
||||||
&(String::from(".imtgott") + plain_ext),
|
&(String::from(".imtgott") + plain_ext),
|
||||||
plain_ext
|
plain_ext
|
||||||
], is_special_name)?;
|
], &(|s| !is_special_name(s)))?;
|
||||||
Ok(MtgottDirContent{
|
Ok(MtgottDirFiles {
|
||||||
mtgott: std::mem::take(&mut all[0]),
|
mtgott: std::mem::take(&mut all[0]),
|
||||||
imtgott: std::mem::take(&mut all[1]),
|
imtgott: std::mem::take(&mut all[1]),
|
||||||
plain: std::mem::take(&mut all[2]),
|
plain: std::mem::take(&mut all[2]),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all_templates(p: &str, plain_ext: &str) -> Result<MTGOTT, Box<dyn Error>> {
|
pub struct FileWithPath {
|
||||||
let source = search_mtgott_dir(p, plain_ext)?;
|
pub v_path: String,
|
||||||
|
pub text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MtgottDirContent {
|
||||||
|
pub mtgott: Vec<FileWithPath>,
|
||||||
|
pub imtgott: Vec<FileWithPath>,
|
||||||
|
pub plain: Vec<FileWithPath>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_file_vector(p: &str, plain_ext: &str, secondary_ext: &str, files: Vec<String>) -> Result<Vec<FileWithPath>, Box<dyn Error>> {
|
||||||
|
files.iter().map(|v_path| -> Result<FileWithPath, Box<dyn Error>> {
|
||||||
|
Ok(FileWithPath{
|
||||||
|
v_path: v_path.clone(),
|
||||||
|
text: String::from_utf8(fs::read(
|
||||||
|
&format!("{p}/{v_path}{secondary_ext}{plain_ext}")
|
||||||
|
)?)?})
|
||||||
|
}).collect::<Result<Vec<FileWithPath>, Box<dyn Error>>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_mtgott_dir_content(p: &str, plain_ext: &str) -> Result<MtgottDirContent, Box<dyn Error>> {
|
||||||
|
let MtgottDirFiles{mtgott, imtgott, plain} = search_mtgott_dir(p, plain_ext)?;
|
||||||
|
Ok(MtgottDirContent {
|
||||||
|
mtgott: read_file_vector(p, plain_ext, ".mtgott", mtgott)?,
|
||||||
|
imtgott: read_file_vector(p, plain_ext, ".imtgott", imtgott)?,
|
||||||
|
plain: read_file_vector(p, plain_ext, "", plain)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_all_templates_from_dir_text(dir: MtgottDirContent, plain_ext: &str) -> Result<MTGOTT, Box<dyn Error>> {
|
||||||
let mut res = MTGOTT{root: SharedValue::Dict(HashMap::new()), source_expressions: Vec::new(), source_elements: Vec::new()};
|
let mut res = MTGOTT{root: SharedValue::Dict(HashMap::new()), source_expressions: Vec::new(), source_elements: Vec::new()};
|
||||||
for cut_path in source.mtgott {
|
for FileWithPath{v_path, text} in dir.mtgott {
|
||||||
let path = format!("{cut_path}.mtgott{plain_ext}");
|
let path = format!("{v_path}.mtgott{}", plain_ext);
|
||||||
let text_bytes = fs::read(PathBuf::from(p).join(&path))?;
|
let plemege = parse_one_file_packed(&text, &v_path, &mut res.source_expressions)?;
|
||||||
let text = std::str::from_utf8(&text_bytes)?;
|
|
||||||
let plemege = parse_one_file_packed(text, &cut_path, &mut res.source_expressions)?;
|
|
||||||
let compiled = plemege_to_value(plemege, &path, &mut res.source_elements, &mut res.source_expressions, 150)?;
|
let compiled = plemege_to_value(plemege, &path, &mut res.source_elements, &mut res.source_expressions, 150)?;
|
||||||
add_path_to_root(&mut res.root, &cut_path, '/', compiled)?
|
add_path_with_slashes_to_root(&mut res.root, &v_path, compiled)?
|
||||||
}
|
}
|
||||||
for cut_path in source.imtgott {
|
for FileWithPath{v_path, text} in dir.imtgott {
|
||||||
let path = format!("{cut_path}.imtgott{plain_ext}");
|
let path = format!("{v_path}.imtgott{}", plain_ext);
|
||||||
let text_bytes = fs::read(PathBuf::from(p).join(&path))?;
|
let plemege = parse_one_file_simplified(&text, &v_path, &mut res.source_expressions)?;
|
||||||
let text = std::str::from_utf8(&text_bytes)?;
|
|
||||||
let plemege = parse_one_file_simplified(text, &cut_path, &mut res.source_expressions)?;
|
|
||||||
let compiled = plemege_to_value(plemege, &path, &mut res.source_elements, &mut res.source_expressions, 150)?;
|
let compiled = plemege_to_value(plemege, &path, &mut res.source_elements, &mut res.source_expressions, 150)?;
|
||||||
add_path_to_root(&mut res.root, &cut_path, '/', compiled)?
|
add_path_with_slashes_to_root(&mut res.root, &v_path, compiled)?
|
||||||
}
|
}
|
||||||
for cut_path in source.plain {
|
for FileWithPath{v_path, text} in dir.plain {
|
||||||
let path = format!("{cut_path}{plain_ext}");
|
add_path_with_slashes_to_root(&mut res.root, &v_path, SharedValue::Str(text))?
|
||||||
let text_bytes = fs::read(PathBuf::from(p).join(&path))?;
|
|
||||||
let text = String::from_utf8(text_bytes)?;
|
|
||||||
add_path_to_root(&mut res.root, &cut_path, '/', SharedValue::Str(text))?
|
|
||||||
}
|
}
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all_templates_plus_builtins(
|
pub fn get_all_templates_plus_builtins_from_dir_text(
|
||||||
p: &str, plain_ext: &str,
|
dir: MtgottDirContent, plain_ext: &str,
|
||||||
sanitize: fn(&str) -> String,
|
sanitize: fn(&str) -> String,
|
||||||
) -> Result<MTGOTT, Box<dyn Error>>{
|
) -> Result<MTGOTT, Box<dyn Error>>{
|
||||||
let mut res = get_all_templates(p, plain_ext)?;
|
let mut res = get_all_templates_from_dir_text(dir, plain_ext)?;
|
||||||
add_path_with_slashes_to_root(&mut res.root, "sanitize", SharedValue::Fn(Box::new(
|
add_path_with_slashes_to_root(&mut res.root, "sanitize", SharedValue::Fn(Box::new(
|
||||||
/* One obvious problem with this sanitizer is that it makes copy even when it
|
/* One obvious problem with this sanitizer is that it makes copy even when it
|
||||||
* takes full ownership of some string and does not have to replace any characters*/
|
* takes full ownership of some string and does not have to replace any characters*/
|
||||||
@ -124,6 +146,10 @@ pub fn get_all_templates_plus_builtins(
|
|||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_root_html(p: &str) -> Result<MTGOTT, Box<dyn Error>>{
|
pub fn get_root_html_from_dir_text_html(dir: MtgottDirContent) -> Result<MTGOTT, Box<dyn Error>>{
|
||||||
get_all_templates_plus_builtins(p, ".html", escape_for_html)
|
get_all_templates_plus_builtins_from_dir_text(dir, ".html", escape_for_html)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_root_html(p: &str) -> Result<MTGOTT, Box<dyn Error>> {
|
||||||
|
get_root_html_from_dir_text_html(read_mtgott_dir_content(p, ".html")?)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -251,13 +251,13 @@ impl<'a> Parser<'a> {
|
|||||||
return Err(self.new_unexpected_char_error(expected_pack_name))
|
return Err(self.new_unexpected_char_error(expected_pack_name))
|
||||||
}
|
}
|
||||||
let child_name: &str = &self.text[p1..self.p];
|
let child_name: &str = &self.text[p1..self.p];
|
||||||
if !is_special_name(child_name) {
|
if is_special_name(child_name) {
|
||||||
return Err(FileParsingError::new(illegal_pack_name, p1, self.p))
|
return Err(FileParsingError::new(illegal_pack_name, p1, self.p))
|
||||||
}
|
}
|
||||||
if let Some(_) = res.get(child_name) {
|
if let Some(_) = res.get(child_name) {
|
||||||
return Err(FileParsingError::new(pack_member_name_already_occupied, p1, self.p))
|
return Err(FileParsingError::new(pack_member_name_already_occupied, p1, self.p))
|
||||||
}
|
}
|
||||||
self.skip_normal_word();
|
self.skip_whitespace();
|
||||||
|
|
||||||
if self.is_ahead("$}"){
|
if self.is_ahead("$}"){
|
||||||
self.p += 2;
|
self.p += 2;
|
||||||
@ -471,7 +471,7 @@ impl<'a> Parser<'a> {
|
|||||||
return finishing_touches(ReasonOfElementEnd{p1: self.p, cmd: BlockEndingTag::EOF}, res);
|
return finishing_touches(ReasonOfElementEnd{p1: self.p, cmd: BlockEndingTag::EOF}, res);
|
||||||
} else if self.is_ahead("{{") {
|
} else if self.is_ahead("{{") {
|
||||||
fin_static(self, tp1, &mut res);
|
fin_static(self, tp1, &mut res);
|
||||||
self.skip_whitespace();
|
self.p += 2;
|
||||||
if !self.is_ahead("}}") {
|
if !self.is_ahead("}}") {
|
||||||
let expr: Expression = self.parse_expression(
|
let expr: Expression = self.parse_expression(
|
||||||
arg_names, &mut (0..arg_names.len()).collect(), recc)?;
|
arg_names, &mut (0..arg_names.len()).collect(), recc)?;
|
||||||
@ -488,7 +488,7 @@ impl<'a> Parser<'a> {
|
|||||||
tp1 = self.p;
|
tp1 = self.p;
|
||||||
} else if self.is_ahead("{[") {
|
} else if self.is_ahead("{[") {
|
||||||
fin_static(self, tp1, &mut res);
|
fin_static(self, tp1, &mut res);
|
||||||
self.skip_whitespace();
|
self.p += 2;
|
||||||
let expr: Expression = self.parse_expression(
|
let expr: Expression = self.parse_expression(
|
||||||
arg_names, &mut (0..arg_names.len()).collect(), recc)?;
|
arg_names, &mut (0..arg_names.len()).collect(), recc)?;
|
||||||
res.push(SubElement::InsertExpr(expr));
|
res.push(SubElement::InsertExpr(expr));
|
||||||
@ -750,7 +750,9 @@ impl<'a> Parser<'a> {
|
|||||||
) -> Result<Option<Expression>, FileParsingError> {
|
) -> Result<Option<Expression>, FileParsingError> {
|
||||||
self.check_recursion_limit(recc)?;
|
self.check_recursion_limit(recc)?;
|
||||||
self.skip_whitespace();
|
self.skip_whitespace();
|
||||||
if self.is_char_ahead('(') {
|
if self.is_tag_end_ahead() {
|
||||||
|
Ok(None)
|
||||||
|
} else if self.is_char_ahead('(') {
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
let expr = self.parse_expression(arg_names, used_local_consts, recc - 1)?;
|
let expr = self.parse_expression(arg_names, used_local_consts, recc - 1)?;
|
||||||
self.skip_whitespace();
|
self.skip_whitespace();
|
||||||
|
|||||||
125
mtgott/tests/april_24.rs
Normal file
125
mtgott/tests/april_24.rs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
extern crate mtgott;
|
||||||
|
use mtgott::dirsearch::*;
|
||||||
|
use mtgott::runtime::*;
|
||||||
|
|
||||||
|
|
||||||
|
macro_rules! assert_gave {
|
||||||
|
($a:expr, $str:literal) => {
|
||||||
|
assert_eq!($a, String::from($str))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t001(){
|
||||||
|
let i = MtgottDirContent{mtgott: vec![
|
||||||
|
FileWithPath{v_path: "boba".into(), text: "{$ aboba = \"xdds\" $}".into()}
|
||||||
|
], imtgott: vec![
|
||||||
|
FileWithPath{v_path: "index".into(), text: "{{ boba.aboba }}".into()}
|
||||||
|
], plain: vec![]};
|
||||||
|
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||||
|
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "xdds");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t002(){
|
||||||
|
let i = MtgottDirContent{mtgott: vec![
|
||||||
|
FileWithPath{v_path: "boba/biba/aaa/bbb".into(), text: "{$ aboba = \"xdds\" $}".into()}
|
||||||
|
], imtgott: vec![
|
||||||
|
FileWithPath{v_path: "index".into(), text: "{{ boba. biba .aaa.bbb.aboba }}".into()}
|
||||||
|
], plain: vec![]};
|
||||||
|
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||||
|
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "xdds");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t003(){
|
||||||
|
let i = MtgottDirContent{mtgott: vec![
|
||||||
|
FileWithPath{v_path: "boba/biba/aaa/bbb".into(), text: "{$ aboba = \"xdds\" $}".into()}
|
||||||
|
], imtgott: vec![
|
||||||
|
FileWithPath{v_path: "index/yyy/eee".into(), text: "{{ boba. biba .aaa.bbb.aboba }}".into()}
|
||||||
|
], plain: vec![]};
|
||||||
|
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||||
|
assert_gave!(r.render(Value::Int(0), "index.yyy.eee", 50).unwrap(), "xdds");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t004(){
|
||||||
|
let i = MtgottDirContent{mtgott: vec![
|
||||||
|
FileWithPath{v_path: "boba/biba/aaa/bbb".into(), text: "{$ pack $} {$ AAA = \"xdds\" $} {$}".into()}
|
||||||
|
], imtgott: vec![
|
||||||
|
FileWithPath{v_path: "index/yyy/eee".into(), text: "{{ boba. biba .aaa.bbb.pack.AAA }}".into()}
|
||||||
|
], plain: vec![]};
|
||||||
|
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||||
|
assert_gave!(r.render(Value::Int(0), "index.yyy.eee", 50).unwrap(), "xdds");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t005(){
|
||||||
|
let i = MtgottDirContent{mtgott: vec![
|
||||||
|
FileWithPath{v_path: "file".into(), text: "{$ pack $} {$ const = 12345 $} {$}".into()}
|
||||||
|
], imtgott: vec![
|
||||||
|
FileWithPath{v_path: "index".into(), text: "{{ file.pack.const }}".into()}
|
||||||
|
], plain: vec![]};
|
||||||
|
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||||
|
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "12345");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t006(){
|
||||||
|
let i = MtgottDirContent{mtgott: vec![
|
||||||
|
FileWithPath{v_path: "file".into(), text: "{$ pack $} {$ const = file.pack.pack2.chislo $} {$ pack2 $} {$ chislo = 123 $} {$} {$}".into()}
|
||||||
|
], imtgott: vec![
|
||||||
|
FileWithPath{v_path: "index".into(), text: "{{ file.pack.const }}".into()}
|
||||||
|
], plain: vec![]};
|
||||||
|
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||||
|
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "123");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t007(){
|
||||||
|
let i = MtgottDirContent{mtgott: vec![
|
||||||
|
FileWithPath{v_path: "file".into(), text: "{$ pack $}{$c=45$}{$} {@ el @}---{{this.pack.c}}---{@} ".into()}
|
||||||
|
], imtgott: vec![
|
||||||
|
FileWithPath{v_path: "index".into(), text: "{[file.el]}".into()}
|
||||||
|
], plain: vec![]};
|
||||||
|
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||||
|
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "---45---");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t008(){
|
||||||
|
let i = MtgottDirContent{mtgott: vec![
|
||||||
|
FileWithPath{v_path: "file".into(), text: "{@ el a@}---{{a}}---{@} ".into()}
|
||||||
|
], imtgott: vec![
|
||||||
|
FileWithPath{v_path: "index".into(), text: "{[file.el \"45\"]}".into()}
|
||||||
|
], plain: vec![]};
|
||||||
|
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||||
|
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "---45---");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t009(){
|
||||||
|
let i = MtgottDirContent{mtgott: vec![
|
||||||
|
FileWithPath{v_path: "file".into(), text: "{@ el a b c d e f g @}---{{a}}---{{c}}---{{e}}---{{g}}---{@} ".into()}
|
||||||
|
], imtgott: vec![
|
||||||
|
FileWithPath{v_path: "index".into(), text: "{[file.el 1 2 3 4 5 6 7]}".into()}
|
||||||
|
], plain: vec![]};
|
||||||
|
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||||
|
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "---1---3---5---7---");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t010(){
|
||||||
|
let i = MtgottDirContent{mtgott: vec![
|
||||||
|
FileWithPath{v_path: "file".into(), text: "{@el a b @} {{a}}{{b}} {@} ".into()}
|
||||||
|
], imtgott: vec![
|
||||||
|
FileWithPath{v_path: "index".into(), text: "{[file.el 1 2]}".into()}
|
||||||
|
], plain: vec![]};
|
||||||
|
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||||
|
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "12");
|
||||||
|
}
|
||||||
121
src/lib.rs
121
src/lib.rs
@ -1 +1,120 @@
|
|||||||
pub mod yyyi_ru;
|
use axum;
|
||||||
|
use std::io;
|
||||||
|
use std::fs;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use axum::http::HeaderValue;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use axum::http;
|
||||||
|
use mtgott::dirsearch::{search_dir, get_root_html};
|
||||||
|
use mtgott::runtime::{MTGOTT, Value};
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
struct StaticAsset {
|
||||||
|
content_type: HeaderValue,
|
||||||
|
content: Vec<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AssetsCache {
|
||||||
|
static_assets: HashMap<String, StaticAsset>,
|
||||||
|
pages: MTGOTT,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ExtensionContentTypeCorr{
|
||||||
|
extension: &'static str,
|
||||||
|
content_type: HeaderValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_static_assets(p: &str, need: &[ExtensionContentTypeCorr]) -> Result<HashMap<String, StaticAsset>, Box<dyn Error>> {
|
||||||
|
let e: Vec<&'static str> = need.iter().map(|corr: &ExtensionContentTypeCorr| corr.extension).collect();
|
||||||
|
let content = search_dir(p, &e, &(|_| true))?;
|
||||||
|
let mut st: HashMap<String, StaticAsset> = HashMap::new();
|
||||||
|
for i in 0..need.len() {
|
||||||
|
let extension: &str = need[i].extension;
|
||||||
|
let content_type: &HeaderValue = &need[i].content_type;
|
||||||
|
for virtual_path in &content[i] {
|
||||||
|
let path_org = format!("{p}/{virtual_path}{extension}");
|
||||||
|
st.insert(format!("{virtual_path}{extension}"), StaticAsset{
|
||||||
|
content_type: content_type.clone(),
|
||||||
|
content: fs::read(&path_org)?,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(st)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_needed_static_assets(p: &str) -> Result<HashMap<String, StaticAsset>, Box<dyn Error>> {
|
||||||
|
load_static_assets(p, &[
|
||||||
|
ExtensionContentTypeCorr{extension: ".css", content_type: HeaderValue::from_str("text/css").unwrap()},
|
||||||
|
ExtensionContentTypeCorr{extension: ".jpeg", content_type: HeaderValue::from_str("image/jpeg").unwrap()},
|
||||||
|
ExtensionContentTypeCorr{extension: ".jpg", content_type: HeaderValue::from_str("image/jpeg").unwrap()},
|
||||||
|
ExtensionContentTypeCorr{extension: ".png", content_type: HeaderValue::from_str("image/png").unwrap()},
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AssetsCache {
|
||||||
|
fn load_assets(assets_dir: &str) -> Result<AssetsCache, Box<dyn Error>> {
|
||||||
|
Ok(AssetsCache {
|
||||||
|
static_assets: load_needed_static_assets(assets_dir)?,
|
||||||
|
pages: get_root_html(&format!("{assets_dir}/HypertextPages"))?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn static_assets(
|
||||||
|
axum::extract::Path(path): axum::extract::Path<String>,
|
||||||
|
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>,
|
||||||
|
) -> Result<([(axum::http::HeaderName, axum::http::HeaderValue); 1], Vec<u8>), axum::http::StatusCode> {
|
||||||
|
if let Some(file) = assets.static_assets.get(&path) {
|
||||||
|
return Ok((
|
||||||
|
[(http::header::CONTENT_TYPE, file.content_type.clone())],
|
||||||
|
file.content.clone()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
Err(axum::http::StatusCode::NOT_FOUND)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn page_index(
|
||||||
|
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>,
|
||||||
|
// axum::extract::Extension(t): axum::extract::Extension<tera::Tera>
|
||||||
|
) -> axum::response::Html<String> {
|
||||||
|
let gr = Value::Int(0);
|
||||||
|
axum::response::Html(assets.pages.render(gr, "index", 500).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn page_blog(
|
||||||
|
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>,
|
||||||
|
// axum::extract::Extension(t): axum::extract::Extension<tera::Tera>
|
||||||
|
) -> impl axum::response::IntoResponse {
|
||||||
|
// let mut context = tera::Context::new();
|
||||||
|
// context.insert("lang", &assets.missing_text[0].0);
|
||||||
|
// context.insert("pres", &assets.missing_text[0].1);
|
||||||
|
// axum::response::Html(assets.templates.render("blog.html", &context).expect("Tera failure"))
|
||||||
|
axum::response::Html(String::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fallback_page() -> axum::http::StatusCode {
|
||||||
|
axum::http::StatusCode::NOT_FOUND
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run_yyyi_ru() {
|
||||||
|
let assets_dir = format!("{}/assets", env!("CARGO_MANIFEST_DIR"));
|
||||||
|
let address = "0.0.0.0:3000";
|
||||||
|
println!("Assets dir: {assets_dir:?}");
|
||||||
|
|
||||||
|
let assets = Arc::new(AssetsCache::load_assets(&assets_dir).unwrap());
|
||||||
|
|
||||||
|
// build our application with a single route
|
||||||
|
let app = axum::Router::new()
|
||||||
|
.without_v07_checks()
|
||||||
|
.route("/", axum::routing::MethodRouter::new().get(page_index))
|
||||||
|
.route("/assets/{*path}", axum::routing::get(static_assets))
|
||||||
|
.route("/blog", axum::routing::get(page_blog))
|
||||||
|
.fallback(fallback_page).with_state(assets);
|
||||||
|
// .layer(axum::Extension(templates));
|
||||||
|
|
||||||
|
// run our app with hyper, listening globally on port 3000
|
||||||
|
let listener = tokio::net::TcpListener::bind(address).await.unwrap();
|
||||||
|
println!("Running on http://{address}");
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use yyyi_ru::yyyi_ru::MAIN;
|
use yyyi_ru::run_yyyi_ru;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
MAIN().await
|
run_yyyi_ru().await
|
||||||
}
|
}
|
||||||
@ -1,163 +0,0 @@
|
|||||||
use axum;
|
|
||||||
use std::io;
|
|
||||||
use std::fs;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use axum::http::HeaderValue;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use axum::http;
|
|
||||||
use json5;
|
|
||||||
use serde_json;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct StaticAsset {
|
|
||||||
content_type: HeaderValue,
|
|
||||||
content: Vec<u8>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct AssetsCache {
|
|
||||||
// templates: tera::Tera,
|
|
||||||
static_assets: HashMap<String, StaticAsset>,
|
|
||||||
missing_text: Vec<(String, serde_json::Value)>
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ExtensionContentTypeCorr{
|
|
||||||
extension: &'static str,
|
|
||||||
content_type: HeaderValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_static_html_page(p: &Path) -> io::Result<StaticAsset> {
|
|
||||||
Ok(StaticAsset {
|
|
||||||
content_type: HeaderValue::from_str("text/html").unwrap(),
|
|
||||||
content: fs::read(p)?
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_static_assets(p: &Path, need: &[ExtensionContentTypeCorr]) -> io::Result<HashMap<String, StaticAsset>> {
|
|
||||||
if !p.is_dir() {
|
|
||||||
return Err(io::Error::from(io::ErrorKind::NotADirectory))
|
|
||||||
}
|
|
||||||
let mut st: HashMap<String, StaticAsset> = HashMap::new();
|
|
||||||
let mut td: Vec<String> = vec![String::new()];
|
|
||||||
while td.len() > 0 {
|
|
||||||
let dshp_dir: String = td.pop().unwrap();
|
|
||||||
let p_dir = p.join(dshp_dir.clone());
|
|
||||||
for entry in fs::read_dir(p_dir)? {
|
|
||||||
let entry = entry?;
|
|
||||||
let dshp_child = if dshp_dir.len() > 0 {
|
|
||||||
format!("{dshp_dir}/{}", entry.file_name().to_str().unwrap())
|
|
||||||
} else {
|
|
||||||
String::from(entry.file_name().to_str().unwrap())
|
|
||||||
};
|
|
||||||
let p_child = p.join(dshp_child.clone());
|
|
||||||
if p_child.is_dir() {
|
|
||||||
td.push(dshp_child);
|
|
||||||
} else {
|
|
||||||
if let Some(ext) = need.iter().find(|ext| {dshp_child.ends_with(ext.extension)}) {
|
|
||||||
st.insert(dshp_child.clone(), StaticAsset {
|
|
||||||
content_type: ext.content_type.clone(),
|
|
||||||
content: fs::read(p.join(dshp_child))?
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(st)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_needed_static_assets(p: &Path) -> io::Result<HashMap<String, StaticAsset>> {
|
|
||||||
load_static_assets(p, &[
|
|
||||||
ExtensionContentTypeCorr{extension: ".css", content_type: HeaderValue::from_str("text/css").unwrap()},
|
|
||||||
ExtensionContentTypeCorr{extension: ".jpeg", content_type: HeaderValue::from_str("image/jpeg").unwrap()},
|
|
||||||
ExtensionContentTypeCorr{extension: ".jpg", content_type: HeaderValue::from_str("image/jpeg").unwrap()},
|
|
||||||
ExtensionContentTypeCorr{extension: ".png", content_type: HeaderValue::from_str("image/png").unwrap()},
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_missing_text(assets: &Path) -> Result<Vec<(String, serde_json::Value)>, Box<dyn std::error::Error>> {
|
|
||||||
let languages = ["ru-RU", "en-US"];
|
|
||||||
let mut res: Vec<(String, serde_json::Value)> = Vec::with_capacity(languages.len());
|
|
||||||
for language in languages {
|
|
||||||
let fc = &fs::read(&assets.join(String::from("text/") + language + ".json5"))?;
|
|
||||||
let val: serde_json::Value = json5::from_str(std::str::from_utf8(fc)?)?;
|
|
||||||
res.push((String::from(language), val))
|
|
||||||
}
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_assets(assets_dir: &Path) -> AssetsCache {
|
|
||||||
// let tera_st = tera::Tera::new(
|
|
||||||
// &assets_dir.join("HypertextPages/**/*.html").to_str().unwrap()
|
|
||||||
// );
|
|
||||||
// if let Err(err) = &tera_st {
|
|
||||||
// println!("{err}")
|
|
||||||
// }
|
|
||||||
AssetsCache {
|
|
||||||
// templates: tera_st.unwrap(),
|
|
||||||
static_assets: load_needed_static_assets(assets_dir).expect("Failed to load static assets"),
|
|
||||||
missing_text: load_missing_text(assets_dir).expect("Failed to load gap-text")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn static_assets(
|
|
||||||
axum::extract::Path(path): axum::extract::Path<String>,
|
|
||||||
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>,
|
|
||||||
) -> Result<([(axum::http::HeaderName, axum::http::HeaderValue); 1], Vec<u8>), axum::http::StatusCode> {
|
|
||||||
if let Some(file) = assets.static_assets.get(&path) {
|
|
||||||
return Ok((
|
|
||||||
[(http::header::CONTENT_TYPE, file.content_type.clone())],
|
|
||||||
file.content.clone()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
Err(axum::http::StatusCode::NOT_FOUND)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn page_index(
|
|
||||||
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>,
|
|
||||||
// axum::extract::Extension(t): axum::extract::Extension<tera::Tera>
|
|
||||||
) -> axum::response::Html<String> {
|
|
||||||
// let mut context = tera::Context::new();
|
|
||||||
// let lang = &assets.missing_text[0].0;
|
|
||||||
// context.insert("lang", lang);
|
|
||||||
// context.insert("pres", &assets.missing_text[0].1);
|
|
||||||
// context.insert("age", &14);
|
|
||||||
// context.insert("aboutme_template", &(String::from("aboutme/") + lang + ".html"));
|
|
||||||
// axum::response::Html(assets.templates.render("index.html", &context).expect("Tera failure"))
|
|
||||||
axum::response::Html(String::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn page_blog(
|
|
||||||
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>,
|
|
||||||
// axum::extract::Extension(t): axum::extract::Extension<tera::Tera>
|
|
||||||
) -> impl axum::response::IntoResponse {
|
|
||||||
// let mut context = tera::Context::new();
|
|
||||||
// context.insert("lang", &assets.missing_text[0].0);
|
|
||||||
// context.insert("pres", &assets.missing_text[0].1);
|
|
||||||
// axum::response::Html(assets.templates.render("blog.html", &context).expect("Tera failure"))
|
|
||||||
axum::response::Html(String::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn fallback_page() -> axum::http::StatusCode {
|
|
||||||
axum::http::StatusCode::NOT_FOUND
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn MAIN() {
|
|
||||||
let assets_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("assets");
|
|
||||||
println!("Cargo manifest dir: {assets_dir:?}");
|
|
||||||
|
|
||||||
let assets = Arc::new(load_assets(&assets_dir));
|
|
||||||
|
|
||||||
// build our application with a single route
|
|
||||||
let app = axum::Router::new()
|
|
||||||
.without_v07_checks()
|
|
||||||
.route("/", axum::routing::MethodRouter::new().get(page_index))
|
|
||||||
.route("/assets/{*path}", axum::routing::get(static_assets))
|
|
||||||
.route("/blog", axum::routing::get(page_blog))
|
|
||||||
.fallback(fallback_page).with_state(assets);
|
|
||||||
// .layer(axum::Extension(templates));
|
|
||||||
|
|
||||||
// run our app with hyper, listening globally on port 3000
|
|
||||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
|
||||||
axum::serve(listener, app).await.unwrap();
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user