use crate::descriptor::DescriptorProto; use crate::descriptor::EnumDescriptorProto; use crate::descriptor::FileDescriptorProto; pub(crate) enum MessageOrEnum<'a> { Message(&'a DescriptorProto), Enum(&'a EnumDescriptorProto), } impl<'a> MessageOrEnum<'a> { fn from_two_options( m: Option<&'a DescriptorProto>, e: Option<&'a EnumDescriptorProto>, ) -> MessageOrEnum<'a> { match (m, e) { (Some(_), Some(_)) => panic!("enum and message with the same name"), (Some(m), None) => MessageOrEnum::Message(m), (None, Some(e)) => MessageOrEnum::Enum(e), (None, None) => panic!("not found"), } } } pub(crate) fn find_message_or_enum<'a>( file: &'a FileDescriptorProto, name_to_package: &str, ) -> (String, MessageOrEnum<'a>) { let mut path = name_to_package.split('.'); let first = path.next().unwrap(); let child_message = file .get_message_type() .iter() .find(|m| m.get_name() == first); let child_enum = file.get_enum_type().iter().find(|e| e.get_name() == first); let mut package_to_name = String::new(); let mut me = MessageOrEnum::from_two_options(child_message, child_enum); for name in path { let message = match me { MessageOrEnum::Message(m) => m, MessageOrEnum::Enum(_) => panic!("enum has no children"), }; if !package_to_name.is_empty() { package_to_name.push_str("."); } package_to_name.push_str(message.get_name()); let child_message = message .get_nested_type() .iter() .find(|m| m.get_name() == name); let child_enum = message .get_enum_type() .iter() .find(|e| e.get_name() == name); me = MessageOrEnum::from_two_options(child_message, child_enum) } (package_to_name, me) }