Skip to main content

obj_alloc/
deser.rs

1use field_collex::{Collexetable, FieldCollex, FieldValue};
2use field_collex::collex::serialize::{FieldCollexSerdeHelper, FieldCollexSerdeWrapper};
3use serde::{Deserialize, Deserializer};
4use serde::de::Error;
5use crate::{Id, IdMap, OrdAllocator};
6use crate::pair::Pair;
7
8impl<'de, K, T, O> Deserialize<'de> for OrdAllocator<K, T, O>
9where
10    O: Collexetable<T> + Deserialize<'de>,
11    T: FieldValue + Deserialize<'de>,
12    K: Id + Deserialize<'de>,
13{
14    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
15    where
16        D: Deserializer<'de>,
17    {
18        // 核心优化1:直接复用 FieldCollexSerdeHelper,避免二次解析 FieldCollex
19        // (原逻辑是先解析 FieldCollex,再从 FieldCollex 取元素;现在直接解析到 Helper,提前拿到结构化数据)
20        let collex_helper: FieldCollexSerdeHelper<Pair<K,O>, T> = FieldCollexSerdeWrapper::<Pair<K,O>, T>::deserialize(deserializer)
21            .map_err(|err|D::Error::custom(format!("反序列化 FieldCollexSerdeHelper 失败: {}", err)))?
22            .into();
23        
24        // 核心优化2:利用 elements 的长度预分配 IdMap 容量,避免 HashMap 动态扩容(性能提升关键)
25        let elements_len = collex_helper.elements.len();
26        let mut id_map = IdMap::<K, T>::with_id_capacity(elements_len);
27        
28        // 核心优化3:直接遍历预解析的 Vec<E>,而非通过 FieldCollex 迭代器(减少迭代器开销)
29        // 遍历过程中无额外内存分配,直接操作已有 Vec
30        for obj in collex_helper.elements.iter() {
31            let obj_id = obj.0; // 取出 Obj 中的 K(Id)
32            let t_value = obj.1.collexate(); // 从 O 生成 T
33            // 插入时无 HashMap 扩容开销(已预分配)
34            id_map.insert_with_id(obj_id, t_value);
35        }
36        
37        // 还原 FieldCollex(复用已解析的 span/unit/elements,无重复构造)
38        let collex = FieldCollex::with_elements(collex_helper.span, collex_helper.unit, collex_helper.elements)
39            .map_err(|e| D::Error::custom(format!("反序列化时创建 FieldCollex 失败: {}", e)))?;
40        
41        Ok(Self {
42            id_map,
43            collex,
44        })
45    }
46}
47
48
49#[cfg(test)]
50mod tests {
51    use field_collex::collex::serialize::{default_span, default_unit};
52    use serde::Serialize;
53    use super::*;
54    use serde_json;
55    use span_core::Span;
56    use crate::DefaultId;
57    
58    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
59    pub struct TestO(pub u32);
60    pub type TestT = u32;
61    impl Collexetable<TestT> for TestO {
62        fn collexate(&self) -> TestT { self.0 }
63        
64        fn collexate_ref(&self) -> &TestT {
65            &self.0
66        }
67        
68        fn collexate_mut(&mut self) -> &mut TestT {
69            &mut self.0
70        }
71    }
72    
73    // ============================ 2. 功能测试 ============================
74    /// 核心功能:验证序列化/反序列化后数据一致性
75    #[test]
76    fn test_obj_allocator_serde_consistency() {
77        // 步骤1:构造原始 ObjAllocator
78        let span = Span::Finite(0u32..100u32);
79        let unit = 10u32;
80        let elements = vec![
81            Pair(DefaultId(1), TestO(10)),
82            Pair(DefaultId(2), TestO(20)),
83            Pair(DefaultId(3), TestO(30)),
84        ];
85        // 构造 FieldCollex
86        let collex = FieldCollex::with_elements(span.clone(), unit.clone(), elements.clone())
87            .expect("构造 FieldCollex 失败");
88        // 构造 IdMap(手动插入与 elements 匹配的 Id/T)
89        let mut id_map = IdMap::<DefaultId, TestT>::with_capacity(elements.len());
90        for obj in &elements {
91            id_map.insert_with_id(obj.0, obj.1.collexate());
92        }
93        // 原始 ObjAllocator
94        let original = OrdAllocator { id_map, collex };
95        
96        // 步骤2:序列化
97        let json = serde_json::to_string(&original).expect("序列化失败");
98        println!("序列化结果:\n{}", json);
99        
100        // 步骤3:反序列化
101        let deserialized: OrdAllocator<DefaultId, TestT, TestO> = serde_json::from_str(&json)
102            .expect("反序列化失败");
103        
104        // 步骤4:验证一致性
105        let (id_map,collex) = deserialized.into_raw_parts();
106        // 验证 collex 一致
107        assert_eq!(collex.span().clone(), default_span());
108        assert_eq!(collex.unit().clone(), default_unit::<u32>());
109        assert_eq!(collex
110                       .into_iter()
111                       .collect::<Vec<Pair<DefaultId, TestO>>>(), elements);
112        // 验证 id_map 一致(遍历所有 Id 检查值)
113        for obj in &elements {
114            let id = obj.0;
115            let expected_t = obj.1.collexate();
116            assert_eq!(id_map.inner.get(&id.as_u64()), Some(&expected_t));
117        }
118        // 验证 IdMap 容量(预分配生效)
119        assert!(id_map.inner.capacity() >= elements.len());
120    }
121    
122    /// 边界测试:空元素场景
123    #[test]
124    fn test_obj_allocator_serde_empty() {
125        // 构造空元素的 FieldCollex
126        let span = Span::new_finite(0u32, 50u32);
127        let unit = 1032;
128        let collex = FieldCollex::new(span, unit)
129            .expect("构造空 FieldCollex 失败");
130        let original: OrdAllocator<DefaultId, TestT, TestO> = OrdAllocator {
131            id_map: IdMap::with_capacity(0),
132            collex,
133        };
134        
135        // 序列化 + 反序列化
136        let json = serde_json::to_string(&original).unwrap();
137        let deserialized: OrdAllocator<DefaultId, TestT, TestO> = serde_json::from_str(&json).unwrap();
138        
139        // 验证空
140        assert!(deserialized.collex.is_empty());
141        assert!(deserialized.id_map.inner.is_empty());
142    }
143}