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