• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::descriptor::FieldDescriptorProto;
2 use crate::descriptor::FieldDescriptorProto_Label;
3 use crate::json::json_name;
4 use crate::message::Message;
5 use crate::reflect::acc::Accessor;
6 use crate::reflect::acc::FieldAccessor;
7 use crate::reflect::map::ReflectMap;
8 use crate::reflect::repeated::ReflectRepeated;
9 use crate::reflect::EnumValueDescriptor;
10 use crate::reflect::ReflectValueRef;
11 
12 /// Reference to a value stored in a field, optional, repeated or map.
13 // TODO: implement Eq
14 pub 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.
26 pub struct FieldDescriptor {
27     proto: &'static FieldDescriptorProto,
28     accessor: FieldAccessor,
29     json_name: String,
30 }
31 
32 impl FieldDescriptor {
new( accessor: FieldAccessor, proto: &'static FieldDescriptorProto, ) -> FieldDescriptor33     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
proto(&self) -> &'static FieldDescriptorProto52     pub fn proto(&self) -> &'static FieldDescriptorProto {
53         self.proto
54     }
55 
56     /// Field name as specified in `.proto` file
name(&self) -> &'static str57     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
json_name(&self) -> &str68     pub fn json_name(&self) -> &str {
69         &self.json_name
70     }
71 
72     /// If this field repeated?
is_repeated(&self) -> bool73     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.
has_field(&self, m: &dyn Message) -> bool85     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.
len_field(&self, m: &dyn Message) -> usize98     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.
get_message<'a>(&self, m: &'a dyn Message) -> &'a dyn Message109     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`.
get_enum(&self, m: &dyn Message) -> &'static EnumValueDescriptor121     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`.
get_str<'a>(&self, m: &'a dyn Message) -> &'a str133     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`.
get_bytes<'a>(&self, m: &'a dyn Message) -> &'a [u8]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`.
get_u32(&self, m: &dyn Message) -> u32157     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`.
get_u64(&self, m: &dyn Message) -> u64169     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`.
get_i32(&self, m: &dyn Message) -> i32181     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`.
get_i64(&self, m: &dyn Message) -> i64193     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`.
get_bool(&self, m: &dyn Message) -> bool205     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`.
get_f32(&self, m: &dyn Message) -> f32217     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`.
get_f64(&self, m: &dyn Message) -> f64229     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.
get_reflect<'a>(&self, m: &'a dyn Message) -> ReflectFieldRef<'a>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 }
246