moduforge_model/
attrs.rs

1use std::ops::{Deref, DerefMut};
2use std::ops::{Index, IndexMut};
3use im::HashMap;
4use serde::{Deserialize, Serialize, Deserializer, Serializer};
5use serde_json::Value;
6//pub type Attrs = HashMap<String, Value>;
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub struct Attrs {
10    pub attrs: HashMap<String, Value>,
11}
12
13impl Serialize for Attrs {
14    fn serialize<S>(
15        &self,
16        serializer: S,
17    ) -> Result<S::Ok, S::Error>
18    where
19        S: Serializer,
20    {
21        self.attrs.serialize(serializer)
22    }
23}
24
25impl<'de> Deserialize<'de> for Attrs {
26    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
27    where
28        D: Deserializer<'de>,
29    {
30        let map = HashMap::<String, Value>::deserialize(deserializer)?;
31        Ok(Attrs { attrs: map })
32    }
33}
34
35impl Default for Attrs {
36    fn default() -> Self {
37        Self { attrs: HashMap::new() }
38    }
39}
40
41impl Index<&str> for Attrs {
42    type Output = Value;
43
44    fn index(
45        &self,
46        key: &str,
47    ) -> &Self::Output {
48        self.get_safe(key).expect("Key not found")
49    }
50}
51
52// 实现 IndexMut trait 用于修改值
53impl IndexMut<&str> for Attrs {
54    fn index_mut(
55        &mut self,
56        key: &str,
57    ) -> &mut Self::Output {
58        if !self.attrs.contains_key(key) {
59            self.attrs.insert(key.to_string(), Value::Null);
60        }
61        self.attrs.get_mut(key).expect("Key not found")
62    }
63}
64
65impl Attrs {
66    pub fn from(new_values: HashMap<String, Value>) -> Self {
67        Self { attrs: new_values }
68    }
69    pub fn get_value<T: serde::de::DeserializeOwned>(
70        &self,
71        key: &str,
72    ) -> Option<T> {
73        self.attrs.get(key).and_then(|v| serde_json::from_value(v.clone()).ok())
74    }
75    pub fn update(
76        &self,
77        new_values: HashMap<String, Value>,
78    ) -> Self {
79        let mut attrs = self.attrs.clone();
80        for (key, value) in new_values {
81            attrs.insert(key, value);
82        }
83        Attrs { attrs }
84    }
85    pub fn get_safe(
86        &self,
87        key: &str,
88    ) -> Option<&Value> {
89        self.attrs.get(key)
90    }
91}
92
93impl Deref for Attrs {
94    type Target = HashMap<String, Value>;
95
96    fn deref(&self) -> &Self::Target {
97        &self.attrs
98    }
99}
100
101impl DerefMut for Attrs {
102    fn deref_mut(&mut self) -> &mut Self::Target {
103        &mut self.attrs
104    }
105}
106
107/// 用于选择性序列化 Attrs 的包装器
108#[derive(Debug, Clone, PartialEq, Eq, Hash)]
109pub struct FilteredAttrs<'a> {
110    attrs: &'a Attrs,
111    filter_key: &'a str,
112}
113
114impl<'a> FilteredAttrs<'a> {
115    pub fn new(
116        attrs: &'a Attrs,
117        filter_key: &'a str,
118    ) -> Self {
119        Self { attrs, filter_key }
120    }
121}
122
123impl<'a> Serialize for FilteredAttrs<'a> {
124    fn serialize<S>(
125        &self,
126        serializer: S,
127    ) -> Result<S::Ok, S::Error>
128    where
129        S: serde::Serializer,
130    {
131        let mut map = serde_json::Map::new();
132        if let Some(value) = self.attrs.get_safe(self.filter_key) {
133            map.insert(self.filter_key.to_string(), value.clone());
134        }
135        map.serialize(serializer)
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142    use serde_json::json;
143
144    #[test]
145    fn test_attrs_default() {
146        let attrs = Attrs::default();
147        assert!(attrs.attrs.is_empty());
148    }
149
150    #[test]
151    fn test_attrs_from() {
152        let mut map = HashMap::new();
153        map.insert("key1".to_string(), json!("value1"));
154        map.insert("key2".to_string(), json!(42));
155
156        let attrs = Attrs::from(map.clone());
157        assert_eq!(attrs.attrs, map);
158    }
159
160    #[test]
161    fn test_index_access() {
162        let mut attrs = Attrs::default();
163        attrs["key1"] = json!("value1");
164        attrs["key2"] = json!(42);
165        println!("attrs key1: {:?}", attrs["key1"]);
166        assert_eq!(attrs["key1"], json!("value1"));
167        assert_eq!(attrs["key2"], json!(42));
168    }
169
170    #[test]
171    fn test_index_mut_auto_create() {
172        let mut attrs = Attrs::default();
173        attrs["new_key"] = json!("new_value");
174        println!("attrs new_key: {:?}", attrs["new_key"]);
175        assert_eq!(attrs["new_key"], json!("new_value"));
176    }
177
178    #[test]
179    fn test_get_value() {
180        let mut attrs = Attrs::default();
181        attrs["string"] = json!("test");
182        attrs["number"] = json!(42);
183        attrs["boolean"] = json!(true);
184
185        assert_eq!(
186            attrs.get_value::<String>("string"),
187            Some("test".to_string())
188        );
189        assert_eq!(attrs.get_value::<i32>("number"), Some(42));
190        assert_eq!(attrs.get_value::<bool>("boolean"), Some(true));
191        assert_eq!(attrs.get_value::<String>("nonexistent"), None);
192    }
193
194    #[test]
195    fn test_update() {
196        let mut attrs = Attrs::default();
197        attrs["key1"] = json!("value1");
198
199        let mut new_values = HashMap::new();
200        new_values.insert("key2".to_string(), json!("value2"));
201        new_values.insert("key1".to_string(), json!("updated_value"));
202
203        let updated = attrs.update(new_values);
204
205        assert_eq!(updated["key1"], json!("updated_value"));
206        assert_eq!(updated["key2"], json!("value2"));
207    }
208
209    #[test]
210    fn test_deref() {
211        let mut attrs = Attrs::default();
212        attrs["key1"] = json!("value1");
213
214        // Test Deref
215        assert_eq!(attrs.get("key1"), Some(&json!("value1")));
216
217        // Test DerefMut
218        attrs.insert("key2".to_string(), json!("value2"));
219        assert_eq!(attrs["key2"], json!("value2"));
220    }
221
222    #[test]
223    #[should_panic(expected = "Key not found")]
224    fn test_index_panic() {
225        let attrs = Attrs::default();
226        let _ = attrs["nonexistent"];
227    }
228
229    #[test]
230    fn test_get_safe() {
231        let mut attrs = Attrs::default();
232        attrs["key1"] = json!("value1");
233
234        assert_eq!(attrs.get_safe("key1"), Some(&json!("value1")));
235        assert_eq!(attrs.get_safe("nonexistent"), None);
236    }
237}