use protobuf::reflect::EnumDescriptor; use protobuf::reflect::MessageDescriptor; use crate::gen::code_writer::CodeWriter; use crate::gen::file_descriptor::file_descriptor_call_expr; use crate::gen::inside::protobuf_crate_path; use crate::gen::scope::Scope; use crate::Customize; /// Abstract message or enum descriptor. pub(crate) trait Descriptor { const DESCRIPTOR_FN: &'static str; const TYPE_NAME: &'static str; const GET_BY_RELATIVE_NAME_NAME: &'static str; fn name_to_package(&self) -> &str; } impl Descriptor for MessageDescriptor { const DESCRIPTOR_FN: &'static str = "descriptor"; const TYPE_NAME: &'static str = "MessageDescriptor"; const GET_BY_RELATIVE_NAME_NAME: &'static str = "message_by_package_relative_name"; fn name_to_package(&self) -> &str { self.name_to_package() } } impl Descriptor for EnumDescriptor { const DESCRIPTOR_FN: &'static str = "enum_descriptor"; const TYPE_NAME: &'static str = "EnumDescriptor"; const GET_BY_RELATIVE_NAME_NAME: &'static str = "enum_by_package_relative_name"; fn name_to_package(&self) -> &str { self.name_to_package() } } pub(crate) fn write_fn_descriptor( descriptor: &D, scope: &Scope, customize: &Customize, w: &mut CodeWriter, ) { let sig = format!( "{}() -> {}::reflect::{}", D::DESCRIPTOR_FN, protobuf_crate_path(customize), D::TYPE_NAME, ); w.def_fn(&sig, |w| { let expr = format!( "{}.{}(\"{}\").unwrap()", file_descriptor_call_expr(scope), D::GET_BY_RELATIVE_NAME_NAME, descriptor.name_to_package() ); w.lazy_static( "descriptor", &format!( "{}::reflect::{}", protobuf_crate_path(customize), D::TYPE_NAME, ), &protobuf_crate_path(customize).to_string(), ); w.write_line(&format!("descriptor.get(|| {}).clone()", expr)); }); }