1 use std::collections::HashMap;
2 use std::ops::Range;
3 
4 use crate::descriptor::field_descriptor_proto::Label;
5 use crate::descriptor::DescriptorProto;
6 use crate::descriptor::EnumDescriptorProto;
7 use crate::descriptor::FileDescriptorProto;
8 use crate::owning_ref::OwningRef;
9 use crate::reflect::error::ReflectError;
10 use crate::reflect::field::index::FieldIndex;
11 use crate::reflect::file::building::FileDescriptorBuilding;
12 use crate::reflect::file::fds::fds_extend_with_public;
13 use crate::reflect::message::is_initialized_is_always_true::compute_is_initialized_is_always_true;
14 use crate::reflect::name::concat_paths;
15 use crate::reflect::service::index::ServiceIndex;
16 use crate::reflect::FileDescriptor;
17 
18 #[derive(Debug)]
19 pub(crate) struct MessageIndices {
20     pub(crate) proto: OwningRef<FileDescriptorProto, DescriptorProto>,
21     pub(crate) name_to_package: String,
22     pub(crate) full_name: String,
23     pub(crate) enclosing_message: Option<usize>,
24     pub(crate) nested_messages: Vec<usize>,
25     pub(crate) nested_enums: Range<usize>,
26     pub(crate) oneofs: Range<usize>,
27     pub(crate) map_entry: bool,
28     pub(crate) message_index: MessageFieldIndices,
29     pub(crate) is_initialized_is_always_true: bool,
30 }
31 
32 #[derive(Debug, Default)]
33 pub(crate) struct MessageFieldIndices {
34     /// Index of the first field in global field index.
35     pub(crate) first_field_index: usize,
36     pub(crate) field_count: usize,
37     /// Extensions follow fields in global field index.
38     pub(crate) extension_count: usize,
39     // Following fields map to the local field index.
40     pub(crate) field_index_by_name: HashMap<String, usize>,
41     pub(crate) field_index_by_name_or_json_name: HashMap<String, usize>,
42     pub(crate) field_index_by_number: HashMap<u32, usize>,
43 }
44 
45 impl MessageFieldIndices {
regular_field_range(&self) -> Range<usize>46     pub(crate) fn regular_field_range(&self) -> Range<usize> {
47         self.first_field_index..(self.first_field_index + self.field_count)
48     }
49 
extension_field_range(&self) -> Range<usize>50     pub(crate) fn extension_field_range(&self) -> Range<usize> {
51         self.first_field_index + self.field_count
52             ..self.first_field_index + self.field_count + self.extension_count
53     }
54 
slice_fields<'a>(&self, file_fields: &'a [FieldIndex]) -> &'a [FieldIndex]55     pub(crate) fn slice_fields<'a>(&self, file_fields: &'a [FieldIndex]) -> &'a [FieldIndex] {
56         &file_fields[self.first_field_index..self.first_field_index + self.field_count]
57     }
58 }
59 
60 #[derive(Debug)]
61 pub(crate) struct EnumIndices {
62     pub(crate) proto: OwningRef<FileDescriptorProto, EnumDescriptorProto>,
63     pub(crate) name_to_package: String,
64     pub(crate) full_name: String,
65     pub(crate) enclosing_message: Option<usize>,
66     pub(crate) index_by_name: HashMap<String, usize>,
67     pub(crate) index_by_number: HashMap<i32, usize>,
68 }
69 
70 impl EnumIndices {
new( name_to_package: String, enclosing_message: Option<usize>, proto: OwningRef<FileDescriptorProto, EnumDescriptorProto>, file: &FileDescriptorProto, ) -> EnumIndices71     pub(crate) fn new(
72         name_to_package: String,
73         enclosing_message: Option<usize>,
74         proto: OwningRef<FileDescriptorProto, EnumDescriptorProto>,
75         file: &FileDescriptorProto,
76     ) -> EnumIndices {
77         let mut index_by_name = HashMap::new();
78         let mut index_by_number = HashMap::new();
79         for (i, v) in proto.value.iter().enumerate() {
80             index_by_number.insert(v.number(), i);
81             index_by_name.insert(v.name().to_owned(), i);
82         }
83         let full_name = concat_paths(file.package(), &name_to_package);
84         EnumIndices {
85             proto,
86             full_name,
87             name_to_package,
88             enclosing_message,
89             index_by_name,
90             index_by_number,
91         }
92     }
93 }
94 
95 #[derive(Debug)]
96 pub(crate) struct OneofIndices {
97     pub(crate) containing_message: usize,
98     pub(crate) index_in_containing_message: usize,
99     /// Synthetic oneof for proto3 optional field.
100     pub(crate) synthetic: bool,
101     pub(crate) fields: Vec<usize>,
102 }
103 
104 /// Common `FileDescriptor` data for generated and dynamic file descriptors.
105 #[derive(Debug)]
106 pub(crate) struct FileDescriptorCommon {
107     /// Direct dependencies of this file.
108     pub(crate) dependencies: Vec<FileDescriptor>,
109     /// All messages in this file.
110     pub(crate) messages: Vec<MessageIndices>,
111     pub(crate) message_by_name_to_package: HashMap<String, usize>,
112     pub(crate) top_level_messages: Vec<usize>,
113     pub(crate) enums: Vec<EnumIndices>,
114     pub(crate) enums_by_name_to_package: HashMap<String, usize>,
115     pub(crate) oneofs: Vec<OneofIndices>,
116     pub(crate) services: Vec<ServiceIndex>,
117     pub(crate) first_extension_field_index: usize,
118     /// All fields followed by file-level extensions.
119     pub(crate) fields: Vec<FieldIndex>,
120 }
121 
122 impl FileDescriptorCommon {
extension_field_range(&self) -> Range<usize>123     pub(crate) fn extension_field_range(&self) -> Range<usize> {
124         self.first_extension_field_index..self.fields.len()
125     }
126 
new( file: OwningRef<FileDescriptorProto, FileDescriptorProto>, dependencies: Vec<FileDescriptor>, ) -> crate::Result<FileDescriptorCommon>127     pub(crate) fn new(
128         file: OwningRef<FileDescriptorProto, FileDescriptorProto>,
129         dependencies: Vec<FileDescriptor>,
130     ) -> crate::Result<FileDescriptorCommon> {
131         let deps_with_public = fds_extend_with_public(dependencies.clone());
132 
133         let mut messages = Vec::new();
134         let mut enums = Vec::new();
135         let mut oneofs = Vec::new();
136         let mut top_level_messages = Vec::new();
137 
138         // Top-level enums start with zero
139         for e in file.flat_map_slice(|f| &f.enum_type) {
140             enums.push(EnumIndices::new(e.name().to_owned(), None, e, file.owner()));
141         }
142 
143         for message in file.flat_map_slice(|f| &f.message_type) {
144             let message_index = Self::index_message_and_inners(
145                 file.owner(),
146                 message,
147                 None,
148                 "",
149                 &mut messages,
150                 &mut enums,
151                 &mut oneofs,
152             )?;
153             top_level_messages.push(message_index);
154         }
155 
156         let message_by_name_to_package = Self::build_message_by_name_to_package(&messages);
157         let enums_by_name_to_package = Self::build_enum_by_name_to_package(&enums);
158 
159         let mut services = Vec::new();
160 
161         for service in &file.service {
162             let service_index = ServiceIndex::index(
163                 service,
164                 &FileDescriptorBuilding {
165                     current_file_descriptor: file.owner(),
166                     deps_with_public: &deps_with_public,
167                     message_by_name_to_package: &message_by_name_to_package,
168                     messages: &messages,
169                     enums_by_name_to_package: &enums_by_name_to_package,
170                 },
171             )?;
172             services.push(service_index);
173         }
174 
175         let mut fields = Vec::new();
176 
177         Self::build_message_index(
178             file.owner(),
179             &deps_with_public,
180             &mut messages,
181             &mut fields,
182             &message_by_name_to_package,
183             &enums_by_name_to_package,
184         )?;
185 
186         let first_extension_field_index = fields.len();
187         for ext in file.flat_map_slice(|f| &f.extension) {
188             fields.push(FieldIndex::index(
189                 None,
190                 ext,
191                 &FileDescriptorBuilding {
192                     current_file_descriptor: file.owner(),
193                     deps_with_public: &deps_with_public,
194                     message_by_name_to_package: &message_by_name_to_package,
195                     messages: &messages,
196                     enums_by_name_to_package: &enums_by_name_to_package,
197                 },
198             )?);
199         }
200 
201         compute_is_initialized_is_always_true(&mut messages, &fields, file.owner());
202 
203         Ok(FileDescriptorCommon {
204             dependencies,
205             messages,
206             message_by_name_to_package,
207             enums,
208             top_level_messages,
209             enums_by_name_to_package,
210             oneofs,
211             services,
212             first_extension_field_index,
213             fields,
214         })
215     }
216 
is_map_entry(message: &DescriptorProto) -> crate::Result<bool>217     fn is_map_entry(message: &DescriptorProto) -> crate::Result<bool> {
218         // Must be consistent with
219         // DescriptorBuilder::ValidateMapEntry
220 
221         if !message.options.map_entry() {
222             return Ok(false);
223         }
224 
225         if !message.name().ends_with("Entry") {
226             return Err(ReflectError::MapEntryNameMustEndWithEntry.into());
227         }
228         if !message.extension.is_empty()
229             || !message.extension_range.is_empty()
230             || !message.nested_type.is_empty()
231             || !message.enum_type.is_empty()
232         {
233             return Err(ReflectError::MapEntryMustHaveNo.into());
234         }
235 
236         if message.field.len() != 2 {
237             return Err(ReflectError::MapEntryIncorrectFields.into());
238         }
239 
240         let key = &message.field[0];
241         let value = &message.field[1];
242 
243         if key.number() != 1
244             || key.name() != "key"
245             || key.label() != Label::LABEL_OPTIONAL
246             || value.number() != 2
247             || value.name() != "value"
248             || value.label() != Label::LABEL_OPTIONAL
249         {
250             return Err(ReflectError::MapEntryIncorrectFields.into());
251         }
252 
253         Ok(true)
254     }
255 
index_message_and_inners( file: &FileDescriptorProto, message: OwningRef<FileDescriptorProto, DescriptorProto>, parent: Option<usize>, parent_name_to_package: &str, messages: &mut Vec<MessageIndices>, enums: &mut Vec<EnumIndices>, oneofs: &mut Vec<OneofIndices>, ) -> crate::Result<usize>256     fn index_message_and_inners(
257         file: &FileDescriptorProto,
258         message: OwningRef<FileDescriptorProto, DescriptorProto>,
259         parent: Option<usize>,
260         parent_name_to_package: &str,
261         messages: &mut Vec<MessageIndices>,
262         enums: &mut Vec<EnumIndices>,
263         oneofs: &mut Vec<OneofIndices>,
264     ) -> crate::Result<usize> {
265         let name_to_package = concat_paths(parent_name_to_package, message.name());
266 
267         let message_index = messages.len();
268         messages.push(MessageIndices {
269             proto: message.clone(),
270             full_name: concat_paths(file.package(), &name_to_package),
271             name_to_package: name_to_package.clone(),
272             enclosing_message: parent,
273             nested_messages: Vec::with_capacity(message.nested_type.len()),
274             nested_enums: enums.len()..enums.len() + message.enum_type.len(),
275             oneofs: oneofs.len()..oneofs.len() + message.oneof_decl.len(),
276             message_index: MessageFieldIndices::default(),
277             map_entry: Self::is_map_entry(&message)?,
278             // Initialized later.
279             is_initialized_is_always_true: false,
280         });
281 
282         for e in message.flat_map_slice(|m| &m.enum_type) {
283             enums.push(EnumIndices::new(
284                 concat_paths(&name_to_package, e.name()),
285                 Some(message_index),
286                 e,
287                 file,
288             ));
289         }
290 
291         for (i, _oneof) in message.oneof_decl.iter().enumerate() {
292             let fields: Vec<_> = message
293                 .field
294                 .iter()
295                 .enumerate()
296                 .filter(|(_, f)| f.has_oneof_index() && f.oneof_index() == i as i32)
297                 .collect();
298             let synthetic = fields.len() == 1 && fields[0].1.proto3_optional();
299             oneofs.push(OneofIndices {
300                 containing_message: message_index,
301                 index_in_containing_message: i,
302                 synthetic,
303                 fields: fields.iter().map(|(i, _)| *i).collect(),
304             });
305         }
306 
307         for nested in message.flat_map_slice(|m| &m.nested_type) {
308             let nested_index = Self::index_message_and_inners(
309                 file,
310                 nested,
311                 Some(message_index),
312                 &name_to_package,
313                 messages,
314                 enums,
315                 oneofs,
316             )?;
317             messages[message_index].nested_messages.push(nested_index);
318         }
319 
320         Ok(message_index)
321     }
322 
build_message_by_name_to_package(messages: &[MessageIndices]) -> HashMap<String, usize>323     fn build_message_by_name_to_package(messages: &[MessageIndices]) -> HashMap<String, usize> {
324         messages
325             .iter()
326             .enumerate()
327             .map(|(i, m)| (m.name_to_package.to_owned(), i))
328             .collect()
329     }
330 
build_enum_by_name_to_package(enums: &[EnumIndices]) -> HashMap<String, usize>331     fn build_enum_by_name_to_package(enums: &[EnumIndices]) -> HashMap<String, usize> {
332         enums
333             .iter()
334             .enumerate()
335             .map(|(i, e)| (e.name_to_package.to_owned(), i))
336             .collect()
337     }
338 
build_message_index( file: &FileDescriptorProto, deps_with_public: &[FileDescriptor], messages: &mut [MessageIndices], fields: &mut Vec<FieldIndex>, message_by_name_to_package: &HashMap<String, usize>, enums_by_name_to_package: &HashMap<String, usize>, ) -> crate::Result<()>339     fn build_message_index(
340         file: &FileDescriptorProto,
341         deps_with_public: &[FileDescriptor],
342         messages: &mut [MessageIndices],
343         fields: &mut Vec<FieldIndex>,
344         message_by_name_to_package: &HashMap<String, usize>,
345         enums_by_name_to_package: &HashMap<String, usize>,
346     ) -> crate::Result<()> {
347         for i in 0..messages.len() {
348             let message_proto = &messages[i].proto;
349             let building = FileDescriptorBuilding {
350                 current_file_descriptor: file,
351                 deps_with_public,
352                 message_by_name_to_package,
353                 messages,
354                 enums_by_name_to_package,
355             };
356             let message_index = Self::index_message(i, message_proto, &building, fields)?;
357             messages[i].message_index = message_index;
358         }
359         Ok(())
360     }
361 
index_message( message_index: usize, proto: &OwningRef<FileDescriptorProto, DescriptorProto>, building: &FileDescriptorBuilding, fields: &mut Vec<FieldIndex>, ) -> crate::Result<MessageFieldIndices>362     fn index_message(
363         message_index: usize,
364         proto: &OwningRef<FileDescriptorProto, DescriptorProto>,
365         building: &FileDescriptorBuilding,
366         fields: &mut Vec<FieldIndex>,
367     ) -> crate::Result<MessageFieldIndices> {
368         let mut index_by_name = HashMap::new();
369         let mut index_by_name_or_json_name = HashMap::new();
370         let mut index_by_number = HashMap::new();
371 
372         let first_field_index = fields.len();
373 
374         for field in proto.flat_map_slice(|m| &m.field) {
375             fields.push(FieldIndex::index(Some(message_index), field, building)?);
376         }
377 
378         let field_count = proto.field.len();
379 
380         for (i, f) in proto.field.iter().enumerate() {
381             let field_index = &fields[first_field_index + i];
382 
383             if index_by_number.insert(f.number() as u32, i).is_some() {
384                 return Err(ReflectError::NonUniqueFieldName(f.name().to_owned()).into());
385             }
386             if index_by_name.insert(f.name().to_owned(), i).is_some() {
387                 return Err(ReflectError::NonUniqueFieldName(f.name().to_owned()).into());
388             }
389             if index_by_name_or_json_name
390                 .insert(f.name().to_owned(), i)
391                 .is_some()
392             {
393                 return Err(ReflectError::NonUniqueFieldName(f.name().to_owned()).into());
394             }
395 
396             if field_index.json_name != f.name() {
397                 if index_by_name_or_json_name
398                     .insert(field_index.json_name.clone(), i)
399                     .is_some()
400                 {
401                     return Err(ReflectError::NonUniqueFieldName(f.name().to_owned()).into());
402                 }
403             }
404         }
405 
406         for ext in proto.flat_map_slice(|m| &m.extension) {
407             fields.push(FieldIndex::index(Some(message_index), ext, building)?);
408         }
409 
410         let extension_count = proto.extension.len();
411 
412         Ok(MessageFieldIndices {
413             first_field_index,
414             field_count,
415             extension_count,
416             field_index_by_name: index_by_name,
417             field_index_by_name_or_json_name: index_by_name_or_json_name,
418             field_index_by_number: index_by_number,
419         })
420     }
421 }
422