use std::collections::hash_map; use std::collections::HashMap; use std::fmt; use std::hash::Hash; use crate::reflect::map::ReflectMap; use crate::reflect::map::ReflectMapIter; use crate::reflect::map::ReflectMapIterTrait; use crate::reflect::runtime_types::RuntimeTypeTrait; use crate::reflect::ProtobufValue; use crate::reflect::ReflectValueBox; use crate::reflect::ReflectValueRef; use crate::reflect::RuntimeType; #[derive(Clone)] enum Maps { U32(HashMap), I32(HashMap), U64(HashMap), I64(HashMap), Bool(HashMap), String(HashMap), } impl fmt::Debug for Maps { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Maps::U32(map) => fmt::Debug::fmt(map, f), Maps::I32(map) => fmt::Debug::fmt(map, f), Maps::U64(map) => fmt::Debug::fmt(map, f), Maps::I64(map) => fmt::Debug::fmt(map, f), Maps::Bool(map) => fmt::Debug::fmt(map, f), Maps::String(map) => fmt::Debug::fmt(map, f), } } } impl Maps { fn len(&self) -> usize { match self { Maps::U32(m) => m.len(), Maps::I32(m) => m.len(), Maps::U64(m) => m.len(), Maps::I64(m) => m.len(), Maps::Bool(m) => m.len(), Maps::String(m) => m.len(), } } fn is_empty(&self) -> bool { match self { Maps::U32(m) => m.is_empty(), Maps::I32(m) => m.is_empty(), Maps::U64(m) => m.is_empty(), Maps::I64(m) => m.is_empty(), Maps::Bool(m) => m.is_empty(), Maps::String(m) => m.is_empty(), } } fn clear(&mut self) { match self { Maps::U32(m) => m.clear(), Maps::I32(m) => m.clear(), Maps::U64(m) => m.clear(), Maps::I64(m) => m.clear(), Maps::Bool(m) => m.clear(), Maps::String(m) => m.clear(), } } fn key_type(&self) -> RuntimeType { match self { Maps::U32(..) => RuntimeType::U32, Maps::I32(..) => RuntimeType::I32, Maps::U64(..) => RuntimeType::U64, Maps::I64(..) => RuntimeType::I64, Maps::Bool(..) => RuntimeType::Bool, Maps::String(..) => RuntimeType::String, } } } #[derive(Clone)] pub(crate) struct DynamicMap { /// Type of value. /// /// Type of key is defined by the maps key. value: RuntimeType, maps: Maps, } impl fmt::Debug for DynamicMap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.maps, f) } } impl DynamicMap { pub fn new(key: RuntimeType, value: RuntimeType) -> DynamicMap { DynamicMap { value, maps: match key { RuntimeType::U32 => Maps::U32(HashMap::new()), RuntimeType::I32 => Maps::I32(HashMap::new()), RuntimeType::U64 => Maps::U64(HashMap::new()), RuntimeType::I64 => Maps::I64(HashMap::new()), RuntimeType::Bool => Maps::Bool(HashMap::new()), RuntimeType::String => Maps::String(HashMap::new()), t => panic!("type cannot be hashmap key: {}", t), }, } } } struct DynamicMapIterImpl<'a, K: ProtobufValue + Eq + Hash + 'static> { iter: hash_map::Iter<'a, K, ReflectValueBox>, value: &'a RuntimeType, } impl<'a, K: ProtobufValue + Eq + Hash + 'static> ReflectMapIterTrait<'a> for DynamicMapIterImpl<'a, K> { fn next(&mut self) -> Option<(ReflectValueRef<'a>, ReflectValueRef<'a>)> { self.iter .next() .map(|(k, v)| (K::RuntimeType::as_ref(k), v.as_value_ref())) } fn key_type(&self) -> RuntimeType { K::RuntimeType::runtime_type_box() } fn value_type(&self) -> RuntimeType { self.value.clone() } } impl ReflectMap for DynamicMap { fn reflect_iter(&self) -> ReflectMapIter { match &self.maps { Maps::U32(m) => ReflectMapIter::new(DynamicMapIterImpl { iter: m.iter(), value: &self.value, }), Maps::I32(m) => ReflectMapIter::new(DynamicMapIterImpl { iter: m.iter(), value: &self.value, }), Maps::U64(m) => ReflectMapIter::new(DynamicMapIterImpl { iter: m.iter(), value: &self.value, }), Maps::I64(m) => ReflectMapIter::new(DynamicMapIterImpl { iter: m.iter(), value: &self.value, }), Maps::Bool(m) => ReflectMapIter::new(DynamicMapIterImpl { iter: m.iter(), value: &self.value, }), Maps::String(m) => ReflectMapIter::new(DynamicMapIterImpl { iter: m.iter(), value: &self.value, }), } } fn len(&self) -> usize { self.maps.len() } fn is_empty(&self) -> bool { self.maps.is_empty() } fn get<'a>(&'a self, key: ReflectValueRef) -> Option> { match (&self.maps, key) { (Maps::U32(m), ReflectValueRef::U32(v)) => m.get(&v), (Maps::U64(m), ReflectValueRef::U64(v)) => m.get(&v), (Maps::I32(m), ReflectValueRef::I32(v)) => m.get(&v), (Maps::I64(m), ReflectValueRef::I64(v)) => m.get(&v), (Maps::Bool(m), ReflectValueRef::Bool(v)) => m.get(&v), (Maps::String(m), ReflectValueRef::String(v)) => m.get(&*v), _ => None, } .map(ReflectValueBox::as_value_ref) } fn insert(&mut self, key: ReflectValueBox, value: ReflectValueBox) { assert!(value.get_type() == self.value); match (&mut self.maps, &key) { (Maps::U32(m), ReflectValueBox::U32(k)) => m.insert(*k, value), (Maps::U64(m), ReflectValueBox::U64(k)) => m.insert(*k, value), (Maps::I32(m), ReflectValueBox::I32(k)) => m.insert(*k, value), (Maps::I64(m), ReflectValueBox::I64(k)) => m.insert(*k, value), (Maps::Bool(m), ReflectValueBox::Bool(k)) => m.insert(*k, value), (Maps::String(m), _) => match key { ReflectValueBox::String(k) => m.insert(k, value), _ => panic!("wrong key type"), }, _ => panic!("wrong key type"), }; } fn clear(&mut self) { self.maps.clear() } fn key_type(&self) -> RuntimeType { self.maps.key_type() } fn value_type(&self) -> RuntimeType { self.value.clone() } }