1use std::collections::HashMap;
2use std::ops::Range;
3
4use crate::descriptor::field_descriptor_proto::Label;
5use crate::descriptor::DescriptorProto;
6use crate::descriptor::EnumDescriptorProto;
7use crate::descriptor::FileDescriptorProto;
8use crate::owning_ref::OwningRef;
9use crate::reflect::error::ReflectError;
10use crate::reflect::field::index::FieldIndex;
11use crate::reflect::file::building::FileDescriptorBuilding;
12use crate::reflect::file::fds::fds_extend_with_public;
13use crate::reflect::message::is_initialized_is_always_true::compute_is_initialized_is_always_true;
14use crate::reflect::name::concat_paths;
15use crate::reflect::service::index::ServiceIndex;
16use crate::reflect::FileDescriptor;
17
18#[derive(Debug)]
19pub(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)]
33pub(crate) struct MessageFieldIndices {
34 pub(crate) first_field_index: usize,
36 pub(crate) field_count: usize,
37 pub(crate) extension_count: usize,
39 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
45impl MessageFieldIndices {
46 pub(crate) fn regular_field_range(&self) -> Range<usize> {
47 self.first_field_index..(self.first_field_index + self.field_count)
48 }
49
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
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)]
61pub(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
70impl EnumIndices {
71 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)]
96pub(crate) struct OneofIndices {
97 pub(crate) containing_message: usize,
98 pub(crate) index_in_containing_message: usize,
99 pub(crate) synthetic: bool,
101 pub(crate) fields: Vec<usize>,
102}
103
104#[derive(Debug)]
106pub(crate) struct FileDescriptorCommon {
107 pub(crate) dependencies: Vec<FileDescriptor>,
109 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 pub(crate) fields: Vec<FieldIndex>,
120}
121
122impl FileDescriptorCommon {
123 pub(crate) fn extension_field_range(&self) -> Range<usize> {
124 self.first_extension_field_index..self.fields.len()
125 }
126
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 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
217 fn is_map_entry(message: &DescriptorProto) -> crate::Result<bool> {
218 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
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 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
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
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
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
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}