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}