diff --git a/Cargo.toml b/Cargo.toml index 77b6672..86b63d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "gtmpl" +name = "gtmpl-moyan" version = "0.7.1" -authors = ["Florian Dieminger "] +authors = ["Florian Dieminger ", "moyan "] description = "The Golang Templating Language for Rust" license = "MIT" repository = "https://github.com/fiji-flo/gtmpl-rust" diff --git a/src/funcs.rs b/src/funcs.rs index 49077e0..baa2fae 100644 --- a/src/funcs.rs +++ b/src/funcs.rs @@ -37,6 +37,7 @@ pub static BUILTINS: &[(&str, Func)] = &[ ("printf", printf as Func), ("index", index as Func), ("call", call as Func), + ("slice", slice as Func), ]; macro_rules! val { @@ -545,6 +546,78 @@ fn cmp(left: &Value, right: &Value) -> Option { } } +pub fn slice(args: &[Value]) -> Result { + if args.is_empty() { + return Err(FuncError::ExactlyXArgs("slice".to_string(), 1)); + } + match &args[0] { + Value::String(s) => { + let mut indices = Vec::new(); + for arg in &args[1..] { + if let Value::Number(n) = arg { + if let Some(i) = n.as_i64() { + indices.push(i as usize); + } else { + return Err(FuncError::Generic("slice bounds out of range".to_string())); + } + } else { + return Err(FuncError::Generic( + "slice bounds must be numbers".to_string(), + )); + } + } + let result = match indices.len() { + 0 => s.clone(), + 1 => s[indices[0]..].to_string(), + 2 => s[indices[0]..indices[1]].to_string(), + 3 => { + // Go 语法中的 x[1:2:3] 在 Rust 中不直接支持 capacity, + // 这里简化处理,只取 slice[1..2] + if indices[0] <= indices[1] && indices[1] <= s.len() { + s[indices[0]..indices[1]].to_string() + } else { + return Err(FuncError::Generic("slice bounds out of range".to_string())); + } + } + _ => return Err(FuncError::ExactlyXArgs("a".to_string(), 4)), + }; + Ok(Value::String(result)) + } + Value::Array(arr) => { + let mut indices = Vec::new(); + for arg in &args[1..] { + if let Value::Number(n) = arg { + if let Some(i) = n.as_i64() { + indices.push(i as usize); + } else { + return Err(FuncError::Generic("slice bounds out of range".to_string())); + } + } else { + return Err(FuncError::Generic( + "slice bounds must be numbers".to_string(), + )); + } + } + let result = match indices.len() { + 0 => arr.clone(), + 1 => arr[indices[0]..].to_vec(), + 2 => arr[indices[0]..indices[1]].to_vec(), + 3 => { + // 同样简化处理 + if indices[0] <= indices[1] && indices[1] <= arr.len() { + arr[indices[0]..indices[1]].to_vec() + } else { + return Err(FuncError::Generic("slice bounds out of range".to_string())); + } + } + _ => return Err(FuncError::ExactlyXArgs("Doesn't engouh arg".to_string(), 4)), + }; + Ok(Value::Array(result)) + } + _ => Err(FuncError::Generic("slice".to_string())), + } +} + #[cfg(test)] mod tests_mocked { use super::*; diff --git a/src/node.rs b/src/node.rs index c324f01..cfd10dc 100644 --- a/src/node.rs +++ b/src/node.rs @@ -507,7 +507,6 @@ node!(NumberNode { }); impl NumberNode { - #[cfg_attr(feature = "cargo-clippy", allow(clippy::float_cmp))] pub fn new( tr: TreeId, pos: Pos, diff --git a/tests/define.rs b/tests/define.rs index d802bf3..037a9bb 100644 --- a/tests/define.rs +++ b/tests/define.rs @@ -1,5 +1,5 @@ -use gtmpl::{Context, Template}; use gtmpl_derive::Gtmpl; +use gtmpl_moyan::{Context, Template}; #[test] fn simple_define() { diff --git a/tests/niladic.rs b/tests/niladic.rs index 979b62d..11a6eb7 100644 --- a/tests/niladic.rs +++ b/tests/niladic.rs @@ -1,6 +1,6 @@ use anyhow::anyhow; -use gtmpl::{Func, FuncError, Value}; use gtmpl_derive::Gtmpl; +use gtmpl_moyan::{Func, FuncError, Value}; fn plus_one(args: &[Value]) -> Result { if let Value::Object(ref o) = &args[0] { @@ -22,6 +22,6 @@ struct AddMe { #[test] fn simple_niladic_method() { let add_me = AddMe { num: 42, plus_one }; - let output = gtmpl::template("The answer is: {{ .plus_one }}", add_me); + let output = gtmpl_moyan::template("The answer is: {{ .plus_one }}", add_me); assert_eq!(&output.unwrap(), "The answer is: 43"); }