fix(config): 优化 lua 数据校验逻辑
- 新增 parse_sequence 统一处理数组校验
This commit is contained in:
108
src/config.rs
108
src/config.rs
@@ -67,6 +67,7 @@ impl fmt::Display for ValueValidator {
|
|||||||
impl ValueValidator {
|
impl ValueValidator {
|
||||||
/// 【纯粹校验入口】只进行逻辑与结构判定,零副作用、不产生内存分配
|
/// 【纯粹校验入口】只进行逻辑与结构判定,零副作用、不产生内存分配
|
||||||
pub fn validate(&self, value: &Value) -> mlua::Result<()> {
|
pub fn validate(&self, value: &Value) -> mlua::Result<()> {
|
||||||
|
let mut n = 0;
|
||||||
if matches!(self, Self::Target) {
|
if matches!(self, Self::Target) {
|
||||||
println!("跟踪taget{}", value.type_name());
|
println!("跟踪taget{}", value.type_name());
|
||||||
}
|
}
|
||||||
@@ -74,7 +75,8 @@ impl ValueValidator {
|
|||||||
println!("跟踪args2{}", value.type_name());
|
println!("跟踪args2{}", value.type_name());
|
||||||
}
|
}
|
||||||
if matches!(self, Self::Env) {
|
if matches!(self, Self::Env) {
|
||||||
println!("跟踪env{}", value.type_name());
|
n = n + 1;
|
||||||
|
println!("跟踪env{} {}", n, value.type_name());
|
||||||
}
|
}
|
||||||
match self {
|
match self {
|
||||||
Self::Target => match value {
|
Self::Target => match value {
|
||||||
@@ -109,6 +111,38 @@ impl ValueValidator {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// fn parse_sequence(&self,index: i64,item: &Value) -> mlua::Result<()> {
|
||||||
|
// match item {
|
||||||
|
// Value::String(_) | Value::Integer(_) | Value::Number(_) | Value::Boolean(_) => {}
|
||||||
|
// other => {
|
||||||
|
// return Err(conversion_error(format!(
|
||||||
|
// "第 {} 个元素类型无效: {}",
|
||||||
|
// index,
|
||||||
|
// other.type_name()
|
||||||
|
// )));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
fn parse_sequence(&self, index: i64, item: &Value) -> mlua::Result<()> {
|
||||||
|
match item {
|
||||||
|
Value::String(_) | Value::Integer(_) | Value::Number(_) | Value::Boolean(_) => Ok(()),
|
||||||
|
Value::Table(tbl) => match self {
|
||||||
|
Self::Env => self.validate_sequence_table(tbl),
|
||||||
|
Self::Args => Err(conversion_error(format!(
|
||||||
|
"{} 仅支持一维数组,不能包含嵌套 Table,索引位置: {index}",
|
||||||
|
self
|
||||||
|
))),
|
||||||
|
Self::Target => Err(conversion_error(format!("{} 仅支持字符串", self))),
|
||||||
|
},
|
||||||
|
other => Err(conversion_error(format!(
|
||||||
|
"{} 第 {} 个元素类型无效: {}",
|
||||||
|
self,
|
||||||
|
index,
|
||||||
|
other.type_name()
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 校验 Table 是否为严格连续的纯数组,并递归校验其内部元素
|
/// 校验 Table 是否为严格连续的纯数组,并递归校验其内部元素
|
||||||
fn validate_sequence_table(&self, tbl: &Table) -> mlua::Result<()> {
|
fn validate_sequence_table(&self, tbl: &Table) -> mlua::Result<()> {
|
||||||
@@ -117,39 +151,10 @@ impl ValueValidator {
|
|||||||
// 1. 顺序遍历连续整数索引 1..N
|
// 1. 顺序遍历连续整数索引 1..N
|
||||||
loop {
|
loop {
|
||||||
let item: Value = tbl.raw_get(index)?;
|
let item: Value = tbl.raw_get(index)?;
|
||||||
if matches!(item, Value::Nil) {
|
if matches!(&item, Value::Nil) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match self {
|
self.parse_sequence(index, &item)?;
|
||||||
Self::Args => match item {
|
|
||||||
Value::Table(_) => {
|
|
||||||
return Err(conversion_error(format!(
|
|
||||||
"{} 仅支持一维数组,不能包含嵌套 Table,索引位置: {index}",
|
|
||||||
self
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
Value::String(_)|Value::Integer(_)|Value::Number(_)|Value::Boolean(_) => {}
|
|
||||||
_ => {return Err(conversion_error("args异常"))}
|
|
||||||
},
|
|
||||||
Self::Env => match item {
|
|
||||||
Value::Table(_) => self.validate(&item)?,
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// // 元素规则判断
|
|
||||||
// match item {
|
|
||||||
// // Args 规则拦截:禁止嵌套数组
|
|
||||||
// Value::Table(_) if matches!(self, Self::Args) => {
|
|
||||||
// return Err(conversion_error(format!(
|
|
||||||
// "{} 仅支持一维数组,不能包含嵌套 Table,索引位置{index}",
|
|
||||||
// self
|
|
||||||
// )));
|
|
||||||
// }
|
|
||||||
// // 标量或合法嵌套表:调用 validate 递归深度判定
|
|
||||||
// _ => self.validate(&item)?,
|
|
||||||
// }
|
|
||||||
|
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
@@ -206,6 +211,8 @@ impl ValueValidator {
|
|||||||
}
|
}
|
||||||
Ok(raw_parts)
|
Ok(raw_parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 校验环境变量名的合法性(Windows 约束:非空、不含 '='、不含 NUL)
|
||||||
fn parse_env_name(name: &Value) -> mlua::Result<String> {
|
fn parse_env_name(name: &Value) -> mlua::Result<String> {
|
||||||
let name_str = match name {
|
let name_str = match name {
|
||||||
Value::String(s) => match s.to_str() {
|
Value::String(s) => match s.to_str() {
|
||||||
@@ -277,9 +284,12 @@ impl ValueValidator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut env_map = HashMap::new();
|
let mut env_map = HashMap::new();
|
||||||
|
let mut n = 0i32;
|
||||||
for pair in tbl.pairs::<Value, Value>() {
|
for pair in tbl.pairs::<Value, Value>() {
|
||||||
|
n += 1;
|
||||||
|
|
||||||
let (raw_key, raw_val) = pair?;
|
let (raw_key, raw_val) = pair?;
|
||||||
|
println!("env {} {}", n, raw_val.type_name());
|
||||||
let (key, val) = Self::parse_env_pair(&raw_key, &raw_val)?;
|
let (key, val) = Self::parse_env_pair(&raw_key, &raw_val)?;
|
||||||
env_map.insert(key, val);
|
env_map.insert(key, val);
|
||||||
}
|
}
|
||||||
@@ -347,36 +357,6 @@ pub fn collect_value_into(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 校验环境变量名的合法性(Windows 约束:非空、不含 '='、不含 NUL)
|
|
||||||
// fn parse_env_name(name: &Value, val: &Value) -> mlua::Result<String> {
|
|
||||||
// let name_str = match name {
|
|
||||||
// Value::String(s) => s.to_str()?.to_string(),
|
|
||||||
//
|
|
||||||
// _ => {
|
|
||||||
// return Err(conversion_error(format!(
|
|
||||||
// "env 配置解析失败:(对应的值: {}, 类型: {}) 无效的键值!示例 HOME=\"/home\" 或 PATH = {{ \"C:/tools/\", \"D:/Windows\"}})",
|
|
||||||
// val.to_string()?,
|
|
||||||
// val.type_name()
|
|
||||||
// )));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// if name_str.is_empty() {
|
|
||||||
// return Err(conversion_error("环境变量名不能为空"));
|
|
||||||
// }
|
|
||||||
// if name_str.contains('=') {
|
|
||||||
// return Err(conversion_error(format!(
|
|
||||||
// "环境变量名 [{}] 不能包含 '='",
|
|
||||||
// name_str
|
|
||||||
// )));
|
|
||||||
// }
|
|
||||||
// if name_str.contains('\0') {
|
|
||||||
// return Err(conversion_error(format!(
|
|
||||||
// "环境变量名 [{}] 不能包含 NUL 字符",
|
|
||||||
// name_str
|
|
||||||
// )));
|
|
||||||
// }
|
|
||||||
// Ok(name_str)
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// 递归将任意 Lua Value 展开为扁平的字符串片段列表
|
/// 递归将任意 Lua Value 展开为扁平的字符串片段列表
|
||||||
// fn collect_env_segments(value: Value, out: &mut Vec<OsString>) -> mlua::Result<()>{OK(())}
|
// fn collect_env_segments(value: Value, out: &mut Vec<OsString>) -> mlua::Result<()>{OK(())}
|
||||||
@@ -503,7 +483,7 @@ mod tests {
|
|||||||
target = "C:/tools/git.exe",
|
target = "C:/tools/git.exe",
|
||||||
args = { "--no-pager"},
|
args = { "--no-pager"},
|
||||||
env = {
|
env = {
|
||||||
PATH = { "C:/tools/git/bin", "C:/Windows", get_env("PATH") },
|
PATH = { "C:/tools/git/bin", "C:/Windows", get_env("PATH")},
|
||||||
HOME = "C:/tools/home",
|
HOME = "C:/tools/home",
|
||||||
CONST = 3,
|
CONST = 3,
|
||||||
BOOL = true,
|
BOOL = true,
|
||||||
|
|||||||
Reference in New Issue
Block a user