From d93e8f7c9e6d8309e0567480ba2d50b67bba7bab Mon Sep 17 00:00:00 2001 From: shenjack-5600u <3695888@qq.com> Date: Wed, 9 Apr 2025 21:22:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E8=83=BD=E4=B8=8D=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E9=82=A3=E4=B9=88=E7=B2=BE=E7=A1=AE=EF=BC=88=EF=BC=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ica-rs/src/py/class.rs | 281 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 258 insertions(+), 23 deletions(-) diff --git a/ica-rs/src/py/class.rs b/ica-rs/src/py/class.rs index 548303a..8c4ab8c 100644 --- a/ica-rs/src/py/class.rs +++ b/ica-rs/src/py/class.rs @@ -5,7 +5,10 @@ use std::collections::HashMap; use pyo3::{ pyclass, pymethods, pymodule, - types::{PyBool, PyDict, PyDictMethods, PyModule, PyModuleMethods, PyString}, + types::{ + PyAnyMethods, PyBool, PyBoolMethods, PyDict, PyDictMethods, PyFloat, PyInt, PyList, + PyListMethods, PyModule, PyModuleMethods, PyString, PyStringMethods, PyTypeMethods, + }, Bound, IntoPyObject, PyAny, PyRef, PyResult, }; use toml::Value as TomlValue; @@ -13,19 +16,37 @@ use tracing::{event, Level}; #[derive(Debug, Clone)] pub enum ConfigItem { + None, String(String), - Integer(i64), + Int(i64), Float(f64), - Boolean(bool), - Array(Vec), - Table(HashMap), + Bool(bool), + Array(Vec), + Table(HashMap), } -#[derive(Clone)] +#[derive(Clone, Debug)] #[pyclass] #[pyo3(name = "ConfigItem")] pub struct ConfigItemPy { pub item: ConfigItem, + pub default_value: ConfigItem, +} + +impl ConfigItemPy { + pub fn new(item: ConfigItem, default_value: ConfigItem) -> Self { + Self { + item, + default_value, + } + } + + pub fn new_uninit(default_value: ConfigItem) -> Self { + Self { + item: ConfigItem::None, + default_value, + } + } } #[derive(Clone)] @@ -40,6 +61,231 @@ pub struct ConfigStoragePy { /// 我也不知道为啥就突然有这玩意了( pub const MAX_CFG_DEPTH: usize = 10; +fn parse_py_string(obj: &Bound<'_, PyAny>) -> PyResult { + let py_str = obj.downcast::()?; + let value = py_str.to_str()?; + Ok(value.to_string()) +} + +fn parse_py_bool(obj: &Bound<'_, PyAny>) -> PyResult { + let py_bool = obj.downcast::()?; + Ok(py_bool.is_true()) +} + +fn parse_py_int(obj: &Bound<'_, PyAny>) -> PyResult { + let py_int = obj.downcast::()?; + py_int.extract::() +} + +fn parse_py_float(obj: &Bound<'_, PyAny>) -> PyResult { + let py_float = obj.downcast::()?; + py_float.extract::() +} + +impl ConfigStoragePy { + /// 递归 list 解析配置 + /// + /// 用个 Result 来标记递归过深 + fn parse_py_list( + args: &Bound<'_, PyList>, + list: &mut Vec, + current_deepth: usize, + ) -> Result<(), usize> { + if current_deepth > MAX_CFG_DEPTH { + return Err(current_deepth); + } else { + for value in args.iter() { + // 匹配 item + let value_type = value.get_type(); + if value_type.is_instance_of::() { + let py_dict = value.downcast::().unwrap(); + let mut new_map = HashMap::new(); + match Self::parse_py_dict(py_dict, &mut new_map, current_deepth + 1) { + Ok(_) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::Table(new_map))); + } + Err(e) => { + event!(Level::WARN, "value(dict) 解析时出现错误: {}", e); + } + } + } else if value_type.is_instance_of::() { + let py_list = value.downcast::().unwrap(); + let mut new_list = Vec::new(); + match Self::parse_py_list(py_list, &mut new_list, current_deepth + 1) { + Ok(_) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::Array(new_list))); + } + Err(e) => { + event!(Level::WARN, "value(list) 解析时出现错误: {}", e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_string(&value) { + Ok(value) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::String(value))); + } + Err(e) => { + event!(Level::WARN, "value(string) 解析时出现错误: {}", e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_bool(&value) { + Ok(value) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::Bool(value))); + } + Err(e) => { + event!(Level::WARN, "value(bool) 解析时出现错误: {}", e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_int(&value) { + Ok(value) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::Int(value))); + } + Err(e) => { + event!(Level::WARN, "value(int) 解析时出现错误: {}", e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_float(&value) { + Ok(value) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::Float(value))); + } + Err(e) => { + event!(Level::WARN, "value(float) 解析时出现错误: {}", e); + } + } + } else { + // 先丢个 warning 出去 + match value_type.name() { + Ok(type_name) => { + event!(Level::WARN, "value 为不支持的 {} 类型", type_name) + } + Err(e) => { + event!(Level::WARN, "value 为不支持的类型 (获取类型名失败: {})", e) + } + } + continue; + } + } + } + Ok(()) + } + + /// 递归 dict 解析配置 + /// + /// 用个 Result 来标记递归过深 + fn parse_py_dict( + kwargs: &Bound<'_, PyDict>, + map: &mut HashMap, + current_deepth: usize, + ) -> Result<(), usize> { + if current_deepth > MAX_CFG_DEPTH { + Err(current_deepth) + } else { + for (key, value) in kwargs.iter() { + if let Ok(name) = key.downcast::() { + let name = name.to_string(); + // 匹配 item + let value_type = value.get_type(); + if value_type.is_instance_of::() { + let py_dict = value.downcast::().unwrap(); + let mut new_map = HashMap::new(); + match Self::parse_py_dict(py_dict, &mut new_map, current_deepth + 1) { + Ok(_) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::Table(new_map)), + ); + } + Err(e) => { + event!(Level::WARN, "value(dict) {} 解析时出现错误: {}", name, e); + } + } + } else if value_type.is_instance_of::() { + let py_list = value.downcast::().unwrap(); + let mut new_list = Vec::new(); + match Self::parse_py_list(py_list, &mut new_list, current_deepth + 1) { + Ok(_) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::Array(new_list)), + ); + } + Err(e) => { + event!(Level::WARN, "value(list) {} 解析时出现错误: {}", name, e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_string(&value) { + Ok(value) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::String(value)), + ); + } + Err(e) => { + event!(Level::WARN, "value(string) {} 解析时出现错误: {}", name, e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_bool(&value) { + Ok(value) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::Bool(value)), + ); + } + Err(e) => { + event!(Level::WARN, "value(bool) {} 解析时出现错误: {}", name, e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_int(&value) { + Ok(value) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::Int(value)), + ); + } + Err(e) => { + event!(Level::WARN, "value(int) {} 解析时出现错误: {}", name, e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_float(&value) { + Ok(value) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::Float(value)), + ); + } + Err(e) => { + event!(Level::WARN, "value(float) {} 解析时出现错误: {}", name, e); + } + } + } else { + // 先丢个 warning 出去 + match value_type.name() { + Ok(type_name) => { + event!(Level::WARN, "value {} 为不支持的 {} 类型", name, type_name) + } + Err(e) => event!( + Level::WARN, + "value {} 为不支持的类型 (获取类型名失败: {})", + name, + e + ), + } + continue; + } + } + } + Ok(()) + } + } +} + #[pymethods] impl ConfigStoragePy { #[new] @@ -48,7 +294,12 @@ impl ConfigStoragePy { match kwargs { Some(kwargs) => { let mut keys = HashMap::new(); - for (key, value) in kwargs.iter() {} + // 解析 kwargs + Self::parse_py_dict(kwargs, &mut keys, 0).map_err(|e| { + event!(Level::ERROR, "配置解析过深: {}", e); + pyo3::exceptions::PyValueError::new_err(format!("配置解析过深: {}", e)) + })?; + // 解析完成 Ok(Self { keys }) } None => Ok(Self { @@ -62,22 +313,6 @@ impl ConfigStoragePy { pub fn get_max_allowed_depth(&self) -> usize { MAX_CFG_DEPTH } } -impl ConfigStoragePy { - /// 递归解析配置 - /// - /// 用个 Result 来标记递归过深 - fn parse_init_key( - map: &mut HashMap, - current_deepth: usize, - ) -> Result<(), usize> { - if current_deepth > MAX_CFG_DEPTH { - Err(current_deepth) - } else { - Ok(()) - } - } -} - #[derive(Clone)] #[pyclass] #[pyo3(name = "ConfigData")]