aboutsummaryrefslogtreecommitdiff
path: root/src/reflect/acc/v2/map.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect/acc/v2/map.rs')
-rw-r--r--src/reflect/acc/v2/map.rs90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/reflect/acc/v2/map.rs b/src/reflect/acc/v2/map.rs
new file mode 100644
index 0000000..3d8df8b
--- /dev/null
+++ b/src/reflect/acc/v2/map.rs
@@ -0,0 +1,90 @@
+use std::collections::HashMap;
+use std::fmt;
+use std::hash::Hash;
+
+use crate::message_dyn::MessageDyn;
+use crate::message_full::MessageFull;
+use crate::reflect::acc::v2::AccessorV2;
+use crate::reflect::acc::FieldAccessor;
+use crate::reflect::map::ReflectMapMut;
+use crate::reflect::map::ReflectMapRef;
+use crate::reflect::runtime_types::RuntimeTypeHashable;
+use crate::reflect::runtime_types::RuntimeTypeTrait;
+use crate::reflect::ProtobufValue;
+use crate::reflect::RuntimeType;
+
+pub(crate) trait MapFieldAccessor: Send + Sync + 'static {
+ fn get_reflect<'a>(&self, m: &'a dyn MessageDyn) -> ReflectMapRef<'a>;
+ fn mut_reflect<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectMapMut<'a>;
+ fn element_type(&self) -> (RuntimeType, RuntimeType);
+}
+
+pub(crate) struct MapFieldAccessorHolder {
+ pub accessor: Box<dyn MapFieldAccessor>,
+}
+
+impl<'a> fmt::Debug for MapFieldAccessorHolder {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("MapFieldAccessorHolder").finish()
+ }
+}
+
+struct MapFieldAccessorImpl<M, K, V>
+where
+ M: MessageFull,
+ K: ProtobufValue,
+ V: ProtobufValue,
+{
+ get_field: fn(&M) -> &HashMap<K, V>,
+ mut_field: fn(&mut M) -> &mut HashMap<K, V>,
+}
+
+impl<M, K, V> MapFieldAccessor for MapFieldAccessorImpl<M, K, V>
+where
+ M: MessageFull,
+ K: ProtobufValue + Eq + Hash,
+ K::RuntimeType: RuntimeTypeHashable,
+ V: ProtobufValue,
+{
+ fn get_reflect<'a>(&self, m: &'a dyn MessageDyn) -> ReflectMapRef<'a> {
+ let m = m.downcast_ref().unwrap();
+ let map = (self.get_field)(m);
+ ReflectMapRef::new(map)
+ }
+
+ fn mut_reflect<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectMapMut<'a> {
+ let m = m.downcast_mut().unwrap();
+ let map = (self.mut_field)(m);
+ ReflectMapMut::new(map)
+ }
+
+ fn element_type(&self) -> (RuntimeType, RuntimeType) {
+ (
+ K::RuntimeType::runtime_type_box(),
+ V::RuntimeType::runtime_type_box(),
+ )
+ }
+}
+
+/// Make accessor for map field
+pub fn make_map_simpler_accessor<M, K, V>(
+ name: &'static str,
+ get_field: for<'a> fn(&'a M) -> &'a HashMap<K, V>,
+ mut_field: for<'a> fn(&'a mut M) -> &'a mut HashMap<K, V>,
+) -> FieldAccessor
+where
+ M: MessageFull + 'static,
+ K: ProtobufValue + Hash + Eq,
+ K::RuntimeType: RuntimeTypeHashable,
+ V: ProtobufValue,
+{
+ FieldAccessor::new(
+ name,
+ AccessorV2::Map(MapFieldAccessorHolder {
+ accessor: Box::new(MapFieldAccessorImpl::<M, K, V> {
+ get_field,
+ mut_field,
+ }),
+ }),
+ )
+}