protobuf/reflect/dynamic/
map.rs

1use std::collections::hash_map;
2use std::collections::HashMap;
3use std::fmt;
4use std::hash::Hash;
5
6use crate::reflect::map::ReflectMap;
7use crate::reflect::map::ReflectMapIter;
8use crate::reflect::map::ReflectMapIterTrait;
9use crate::reflect::runtime_types::RuntimeTypeTrait;
10use crate::reflect::ProtobufValue;
11use crate::reflect::ReflectValueBox;
12use crate::reflect::ReflectValueRef;
13use crate::reflect::RuntimeType;
14
15#[derive(Clone)]
16enum Maps {
17    U32(HashMap<u32, ReflectValueBox>),
18    I32(HashMap<i32, ReflectValueBox>),
19    U64(HashMap<u64, ReflectValueBox>),
20    I64(HashMap<i64, ReflectValueBox>),
21    Bool(HashMap<bool, ReflectValueBox>),
22    String(HashMap<String, ReflectValueBox>),
23}
24
25impl fmt::Debug for Maps {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        match self {
28            Maps::U32(map) => fmt::Debug::fmt(map, f),
29            Maps::I32(map) => fmt::Debug::fmt(map, f),
30            Maps::U64(map) => fmt::Debug::fmt(map, f),
31            Maps::I64(map) => fmt::Debug::fmt(map, f),
32            Maps::Bool(map) => fmt::Debug::fmt(map, f),
33            Maps::String(map) => fmt::Debug::fmt(map, f),
34        }
35    }
36}
37
38impl Maps {
39    fn len(&self) -> usize {
40        match self {
41            Maps::U32(m) => m.len(),
42            Maps::I32(m) => m.len(),
43            Maps::U64(m) => m.len(),
44            Maps::I64(m) => m.len(),
45            Maps::Bool(m) => m.len(),
46            Maps::String(m) => m.len(),
47        }
48    }
49
50    fn is_empty(&self) -> bool {
51        match self {
52            Maps::U32(m) => m.is_empty(),
53            Maps::I32(m) => m.is_empty(),
54            Maps::U64(m) => m.is_empty(),
55            Maps::I64(m) => m.is_empty(),
56            Maps::Bool(m) => m.is_empty(),
57            Maps::String(m) => m.is_empty(),
58        }
59    }
60
61    fn clear(&mut self) {
62        match self {
63            Maps::U32(m) => m.clear(),
64            Maps::I32(m) => m.clear(),
65            Maps::U64(m) => m.clear(),
66            Maps::I64(m) => m.clear(),
67            Maps::Bool(m) => m.clear(),
68            Maps::String(m) => m.clear(),
69        }
70    }
71
72    fn key_type(&self) -> RuntimeType {
73        match self {
74            Maps::U32(..) => RuntimeType::U32,
75            Maps::I32(..) => RuntimeType::I32,
76            Maps::U64(..) => RuntimeType::U64,
77            Maps::I64(..) => RuntimeType::I64,
78            Maps::Bool(..) => RuntimeType::Bool,
79            Maps::String(..) => RuntimeType::String,
80        }
81    }
82}
83
84#[derive(Clone)]
85pub(crate) struct DynamicMap {
86    /// Type of value.
87    ///
88    /// Type of key is defined by the maps key.
89    value: RuntimeType,
90    maps: Maps,
91}
92
93impl fmt::Debug for DynamicMap {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        fmt::Debug::fmt(&self.maps, f)
96    }
97}
98
99impl DynamicMap {
100    pub fn new(key: RuntimeType, value: RuntimeType) -> DynamicMap {
101        DynamicMap {
102            value,
103            maps: match key {
104                RuntimeType::U32 => Maps::U32(HashMap::new()),
105                RuntimeType::I32 => Maps::I32(HashMap::new()),
106                RuntimeType::U64 => Maps::U64(HashMap::new()),
107                RuntimeType::I64 => Maps::I64(HashMap::new()),
108                RuntimeType::Bool => Maps::Bool(HashMap::new()),
109                RuntimeType::String => Maps::String(HashMap::new()),
110                t => panic!("type cannot be hashmap key: {}", t),
111            },
112        }
113    }
114}
115
116struct DynamicMapIterImpl<'a, K: ProtobufValue + Eq + Hash + 'static> {
117    iter: hash_map::Iter<'a, K, ReflectValueBox>,
118    _value_type: &'a RuntimeType,
119}
120
121impl<'a, K: ProtobufValue + Eq + Hash + 'static> ReflectMapIterTrait<'a>
122    for DynamicMapIterImpl<'a, K>
123{
124    fn next(&mut self) -> Option<(ReflectValueRef<'a>, ReflectValueRef<'a>)> {
125        self.iter
126            .next()
127            .map(|(k, v)| (K::RuntimeType::as_ref(k), v.as_value_ref()))
128    }
129
130    fn _key_type(&self) -> RuntimeType {
131        K::RuntimeType::runtime_type_box()
132    }
133
134    fn _value_type(&self) -> RuntimeType {
135        self._value_type.clone()
136    }
137}
138
139impl ReflectMap for DynamicMap {
140    fn reflect_iter(&self) -> ReflectMapIter {
141        match &self.maps {
142            Maps::U32(m) => ReflectMapIter::new(DynamicMapIterImpl {
143                iter: m.iter(),
144                _value_type: &self.value,
145            }),
146            Maps::I32(m) => ReflectMapIter::new(DynamicMapIterImpl {
147                iter: m.iter(),
148                _value_type: &self.value,
149            }),
150            Maps::U64(m) => ReflectMapIter::new(DynamicMapIterImpl {
151                iter: m.iter(),
152                _value_type: &self.value,
153            }),
154            Maps::I64(m) => ReflectMapIter::new(DynamicMapIterImpl {
155                iter: m.iter(),
156                _value_type: &self.value,
157            }),
158            Maps::Bool(m) => ReflectMapIter::new(DynamicMapIterImpl {
159                iter: m.iter(),
160                _value_type: &self.value,
161            }),
162            Maps::String(m) => ReflectMapIter::new(DynamicMapIterImpl {
163                iter: m.iter(),
164                _value_type: &self.value,
165            }),
166        }
167    }
168
169    fn len(&self) -> usize {
170        self.maps.len()
171    }
172
173    fn is_empty(&self) -> bool {
174        self.maps.is_empty()
175    }
176
177    fn get<'a>(&'a self, key: ReflectValueRef) -> Option<ReflectValueRef<'a>> {
178        match (&self.maps, key) {
179            (Maps::U32(m), ReflectValueRef::U32(v)) => m.get(&v),
180            (Maps::U64(m), ReflectValueRef::U64(v)) => m.get(&v),
181            (Maps::I32(m), ReflectValueRef::I32(v)) => m.get(&v),
182            (Maps::I64(m), ReflectValueRef::I64(v)) => m.get(&v),
183            (Maps::Bool(m), ReflectValueRef::Bool(v)) => m.get(&v),
184            (Maps::String(m), ReflectValueRef::String(v)) => m.get(&*v),
185            _ => None,
186        }
187        .map(ReflectValueBox::as_value_ref)
188    }
189
190    fn insert(&mut self, key: ReflectValueBox, value: ReflectValueBox) {
191        assert!(value.get_type() == self.value);
192        match (&mut self.maps, &key) {
193            (Maps::U32(m), ReflectValueBox::U32(k)) => m.insert(*k, value),
194            (Maps::U64(m), ReflectValueBox::U64(k)) => m.insert(*k, value),
195            (Maps::I32(m), ReflectValueBox::I32(k)) => m.insert(*k, value),
196            (Maps::I64(m), ReflectValueBox::I64(k)) => m.insert(*k, value),
197            (Maps::Bool(m), ReflectValueBox::Bool(k)) => m.insert(*k, value),
198            (Maps::String(m), _) => match key {
199                ReflectValueBox::String(k) => m.insert(k, value),
200                _ => panic!("wrong key type"),
201            },
202            _ => panic!("wrong key type"),
203        };
204    }
205
206    fn clear(&mut self) {
207        self.maps.clear()
208    }
209
210    fn key_type(&self) -> RuntimeType {
211        self.maps.key_type()
212    }
213
214    fn value_type(&self) -> RuntimeType {
215        self.value.clone()
216    }
217}