protobuf/reflect/acc/v2/
map.rs

1use std::collections::BTreeMap;
2use std::collections::HashMap;
3use std::fmt;
4use std::hash::Hash;
5
6use crate::message_dyn::MessageDyn;
7use crate::message_full::MessageFull;
8use crate::reflect::acc::v2::AccessorV2;
9use crate::reflect::acc::FieldAccessor;
10use crate::reflect::map::ReflectMapMut;
11use crate::reflect::map::ReflectMapRef;
12use crate::reflect::runtime_types::RuntimeTypeMapKey;
13use crate::reflect::runtime_types::RuntimeTypeTrait;
14use crate::reflect::ProtobufValue;
15use crate::reflect::RuntimeType;
16
17pub(crate) trait MapFieldAccessor: Send + Sync + 'static {
18    fn get_reflect<'a>(&self, m: &'a dyn MessageDyn) -> ReflectMapRef<'a>;
19    fn mut_reflect<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectMapMut<'a>;
20    fn _element_type(&self) -> (RuntimeType, RuntimeType);
21}
22
23pub(crate) struct MapFieldAccessorHolder {
24    pub accessor: Box<dyn MapFieldAccessor>,
25}
26
27impl<'a> fmt::Debug for MapFieldAccessorHolder {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        f.debug_struct("MapFieldAccessorHolder").finish()
30    }
31}
32
33struct MapFieldAccessorImpl<M, T>
34where
35    M: MessageFull,
36{
37    get_field: fn(&M) -> &T,
38    mut_field: fn(&mut M) -> &mut T,
39}
40
41impl<M, K, V> MapFieldAccessor for MapFieldAccessorImpl<M, HashMap<K, V>>
42where
43    M: MessageFull,
44    K: ProtobufValue + Eq + Hash,
45    K::RuntimeType: RuntimeTypeMapKey,
46    V: ProtobufValue,
47{
48    fn get_reflect<'a>(&self, m: &'a dyn MessageDyn) -> ReflectMapRef<'a> {
49        let m = m.downcast_ref().unwrap();
50        let map = (self.get_field)(m);
51        ReflectMapRef::new(map)
52    }
53
54    fn mut_reflect<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectMapMut<'a> {
55        let m = m.downcast_mut().unwrap();
56        let map = (self.mut_field)(m);
57        ReflectMapMut::new(map)
58    }
59
60    fn _element_type(&self) -> (RuntimeType, RuntimeType) {
61        (
62            K::RuntimeType::runtime_type_box(),
63            V::RuntimeType::runtime_type_box(),
64        )
65    }
66}
67
68impl<M, K, V> MapFieldAccessor for MapFieldAccessorImpl<M, BTreeMap<K, V>>
69where
70    M: MessageFull,
71    K: ProtobufValue + Ord,
72    K::RuntimeType: RuntimeTypeMapKey,
73    V: ProtobufValue,
74{
75    fn get_reflect<'a>(&self, m: &'a dyn MessageDyn) -> ReflectMapRef<'a> {
76        let m = m.downcast_ref().unwrap();
77        let map = (self.get_field)(m);
78        ReflectMapRef::new(map)
79    }
80
81    fn mut_reflect<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectMapMut<'a> {
82        let m = m.downcast_mut().unwrap();
83        let map = (self.mut_field)(m);
84        ReflectMapMut::new(map)
85    }
86
87    fn _element_type(&self) -> (RuntimeType, RuntimeType) {
88        (
89            K::RuntimeType::runtime_type_box(),
90            V::RuntimeType::runtime_type_box(),
91        )
92    }
93}
94
95/// Make accessor for map field.
96/// This is code generated by rust-protobuf before 3.5.
97pub fn make_map_simpler_accessor<M, K, V>(
98    name: &'static str,
99    get_field: for<'a> fn(&'a M) -> &'a HashMap<K, V>,
100    mut_field: for<'a> fn(&'a mut M) -> &'a mut HashMap<K, V>,
101) -> FieldAccessor
102where
103    M: MessageFull + 'static,
104    K: ProtobufValue + Hash + Eq,
105    K::RuntimeType: RuntimeTypeMapKey,
106    V: ProtobufValue,
107{
108    make_map_simpler_accessor_new(name, get_field, mut_field)
109}
110
111/// Make accessor for map field, new version
112// This is only used in generated code.
113// Rust compiler allows it, and we want to avoid exposing traits in public API.
114#[allow(private_bounds)]
115pub fn make_map_simpler_accessor_new<M, T>(
116    name: &'static str,
117    get_field: for<'a> fn(&'a M) -> &'a T,
118    mut_field: for<'a> fn(&'a mut M) -> &'a mut T,
119) -> FieldAccessor
120where
121    M: MessageFull,
122    MapFieldAccessorImpl<M, T>: MapFieldAccessor,
123{
124    FieldAccessor::new(
125        name,
126        AccessorV2::Map(MapFieldAccessorHolder {
127            accessor: Box::new(MapFieldAccessorImpl::<M, T> {
128                get_field,
129                mut_field,
130            }),
131        }),
132    )
133}