protobuf/reflect/
find_message_or_enum.rs
1use crate::descriptor::DescriptorProto;
2use crate::descriptor::EnumDescriptorProto;
3use crate::descriptor::FileDescriptorProto;
4
5pub(crate) enum MessageOrEnum<'a> {
6 Message(&'a DescriptorProto),
7 Enum(&'a EnumDescriptorProto),
8}
9
10impl<'a> MessageOrEnum<'a> {
11 fn from_two_options(
12 m: Option<&'a DescriptorProto>,
13 e: Option<&'a EnumDescriptorProto>,
14 ) -> Option<MessageOrEnum<'a>> {
15 match (m, e) {
16 (Some(_), Some(_)) => panic!("enum and message with the same name"),
17 (Some(m), None) => Some(MessageOrEnum::Message(m)),
18 (None, Some(e)) => Some(MessageOrEnum::Enum(e)),
19 (None, None) => None,
20 }
21 }
22}
23
24pub(crate) fn find_message_or_enum<'a>(
25 file: &'a FileDescriptorProto,
26 name_to_package: &str,
27) -> Option<(String, MessageOrEnum<'a>)> {
28 assert!(!name_to_package.starts_with("."));
29 assert!(!name_to_package.is_empty());
30
31 let mut path = name_to_package.split('.');
32 let first = path.next().unwrap();
33 let child_message = file.message_type.iter().find(|m| m.name() == first);
34 let child_enum = file.enum_type.iter().find(|e| e.name() == first);
35
36 let mut package_to_name = String::new();
37 let mut me = MessageOrEnum::from_two_options(child_message, child_enum)?;
38
39 for name in path {
40 let message = match me {
41 MessageOrEnum::Message(m) => m,
42 MessageOrEnum::Enum(_) => panic!("enum has no children"),
43 };
44
45 if !package_to_name.is_empty() {
46 package_to_name.push_str(".");
47 }
48 package_to_name.push_str(message.name());
49
50 let child_message = message.nested_type.iter().find(|m| m.name() == name);
51 let child_enum = message.enum_type.iter().find(|e| e.name() == name);
52 me = MessageOrEnum::from_two_options(child_message, child_enum)?;
53 }
54
55 Some((package_to_name, me))
56}