protobuf/reflect/
field.rs

1use crate::descriptor::FieldDescriptorProto;
2use crate::descriptor::FieldDescriptorProto_Label;
3use crate::json::json_name;
4use crate::message::Message;
5use crate::reflect::acc::Accessor;
6use crate::reflect::acc::FieldAccessor;
7use crate::reflect::map::ReflectMap;
8use crate::reflect::repeated::ReflectRepeated;
9use crate::reflect::EnumValueDescriptor;
10use crate::reflect::ReflectValueRef;
11
12/// Reference to a value stored in a field, optional, repeated or map.
13// TODO: implement Eq
14pub enum ReflectFieldRef<'a> {
15    /// Singular field, optional or required in proto3 and just plain field in proto3
16    Optional(Option<ReflectValueRef<'a>>),
17    /// Repeated field
18    Repeated(&'a dyn ReflectRepeated),
19    /// Map field
20    Map(&'a dyn ReflectMap),
21}
22
23/// Field descriptor.
24///
25/// Can be used for runtime reflection.
26pub struct FieldDescriptor {
27    proto: &'static FieldDescriptorProto,
28    accessor: FieldAccessor,
29    json_name: String,
30}
31
32impl FieldDescriptor {
33    pub(crate) fn new(
34        accessor: FieldAccessor,
35        proto: &'static FieldDescriptorProto,
36    ) -> FieldDescriptor {
37        assert_eq!(proto.get_name(), accessor.name);
38        let json_name = if !proto.get_json_name().is_empty() {
39            proto.get_json_name().to_string()
40        } else {
41            json_name(proto.get_name())
42        };
43        FieldDescriptor {
44            proto,
45            accessor,
46            // probably could be lazy-init
47            json_name,
48        }
49    }
50
51    /// Get `.proto` description of field
52    pub fn proto(&self) -> &'static FieldDescriptorProto {
53        self.proto
54    }
55
56    /// Field name as specified in `.proto` file
57    pub fn name(&self) -> &'static str {
58        self.proto.get_name()
59    }
60
61    /// JSON field name.
62    ///
63    /// Can be different from `.proto` field name.
64    ///
65    /// See [JSON mapping][json] for details.
66    ///
67    /// [json]: https://developers.google.com/protocol-buffers/docs/proto3#json
68    pub fn json_name(&self) -> &str {
69        &self.json_name
70    }
71
72    /// If this field repeated?
73    pub fn is_repeated(&self) -> bool {
74        self.proto.get_label() == FieldDescriptorProto_Label::LABEL_REPEATED
75    }
76
77    /// Check if field is set in given message.
78    ///
79    /// For repeated field or map field return `true` if
80    /// collection is not empty.
81    ///
82    /// # Panics
83    ///
84    /// If this field belongs to a different message type.
85    pub fn has_field(&self, m: &dyn Message) -> bool {
86        match &self.accessor.accessor {
87            Accessor::V1(a) => a.has_field_generic(m),
88        }
89    }
90
91    /// Return length of repeated field.
92    ///
93    /// For singular field return `1` if field is set and `0` otherwise.
94    ///
95    /// # Panics
96    ///
97    /// If this field belongs to a different message type.
98    pub fn len_field(&self, m: &dyn Message) -> usize {
99        match &self.accessor.accessor {
100            Accessor::V1(a) => a.len_field_generic(m),
101        }
102    }
103
104    /// Get message field or default instance if field is unset.
105    ///
106    /// # Panics
107    /// If this field belongs to a different message type or
108    /// field type is not message.
109    pub fn get_message<'a>(&self, m: &'a dyn Message) -> &'a dyn Message {
110        match &self.accessor.accessor {
111            Accessor::V1(a) => a.get_message_generic(m),
112        }
113    }
114
115    /// Get `enum` field.
116    ///
117    /// # Panics
118    ///
119    /// If this field belongs to a different message type
120    /// or field type is not singular `enum`.
121    pub fn get_enum(&self, m: &dyn Message) -> &'static EnumValueDescriptor {
122        match &self.accessor.accessor {
123            Accessor::V1(a) => a.get_enum_generic(m),
124        }
125    }
126
127    /// Get `string` field.
128    ///
129    /// # Panics
130    ///
131    /// If this field belongs to a different message type
132    /// or field type is not singular `string`.
133    pub fn get_str<'a>(&self, m: &'a dyn Message) -> &'a str {
134        match &self.accessor.accessor {
135            Accessor::V1(a) => a.get_str_generic(m),
136        }
137    }
138
139    /// Get `bytes` field.
140    ///
141    /// # Panics
142    ///
143    /// If this field belongs to a different message type
144    /// or field type is not singular `bytes`.
145    pub fn get_bytes<'a>(&self, m: &'a dyn Message) -> &'a [u8] {
146        match &self.accessor.accessor {
147            Accessor::V1(a) => a.get_bytes_generic(m),
148        }
149    }
150
151    /// Get `u32` field.
152    ///
153    /// # Panics
154    ///
155    /// If this field belongs to a different message type
156    /// or field type is not singular `u32`.
157    pub fn get_u32(&self, m: &dyn Message) -> u32 {
158        match &self.accessor.accessor {
159            Accessor::V1(a) => a.get_u32_generic(m),
160        }
161    }
162
163    /// Get `u64` field.
164    ///
165    /// # Panics
166    ///
167    /// If this field belongs to a different message type
168    /// or field type is not singular `u64`.
169    pub fn get_u64(&self, m: &dyn Message) -> u64 {
170        match &self.accessor.accessor {
171            Accessor::V1(a) => a.get_u64_generic(m),
172        }
173    }
174
175    /// Get `i32` field.
176    ///
177    /// # Panics
178    ///
179    /// If this field belongs to a different message type
180    /// or field type is not singular `i32`.
181    pub fn get_i32(&self, m: &dyn Message) -> i32 {
182        match &self.accessor.accessor {
183            Accessor::V1(a) => a.get_i32_generic(m),
184        }
185    }
186
187    /// Get `i64` field.
188    ///
189    /// # Panics
190    ///
191    /// If this field belongs to a different message type
192    /// or field type is not singular `i64`.
193    pub fn get_i64(&self, m: &dyn Message) -> i64 {
194        match &self.accessor.accessor {
195            Accessor::V1(a) => a.get_i64_generic(m),
196        }
197    }
198
199    /// Get `bool` field.
200    ///
201    /// # Panics
202    ///
203    /// If this field belongs to a different message type or
204    /// field type is not singular `bool`.
205    pub fn get_bool(&self, m: &dyn Message) -> bool {
206        match &self.accessor.accessor {
207            Accessor::V1(a) => a.get_bool_generic(m),
208        }
209    }
210
211    /// Get `float` field.
212    ///
213    /// # Panics
214    ///
215    /// If this field belongs to a different message type or
216    /// field type is not singular `float`.
217    pub fn get_f32(&self, m: &dyn Message) -> f32 {
218        match &self.accessor.accessor {
219            Accessor::V1(a) => a.get_f32_generic(m),
220        }
221    }
222
223    /// Get `double` field.
224    ///
225    /// # Panics
226    ///
227    /// If this field belongs to a different message type
228    /// or field type is not singular `double`.
229    pub fn get_f64(&self, m: &dyn Message) -> f64 {
230        match &self.accessor.accessor {
231            Accessor::V1(a) => a.get_f64_generic(m),
232        }
233    }
234
235    /// Get field of any type.
236    ///
237    /// # Panics
238    ///
239    /// If this field belongs to a different message type.
240    pub fn get_reflect<'a>(&self, m: &'a dyn Message) -> ReflectFieldRef<'a> {
241        match &self.accessor.accessor {
242            Accessor::V1(a) => a.get_reflect(m),
243        }
244    }
245}