1 use super::code_writer::CodeWriter;
2 use super::rust_types_values::*;
3 use protobuf::descriptor::*;
4 use protobuf::descriptorx::*;
5 use Customize;
6 
7 struct ExtGen<'a> {
8     file: &'a FileDescriptorProto,
9     root_scope: &'a RootScope<'a>,
10     field: &'a FieldDescriptorProto,
11     customize: Customize,
12 }
13 
14 impl<'a> ExtGen<'a> {
extendee_rust_name(&self) -> String15     fn extendee_rust_name(&self) -> String {
16         type_name_to_rust_relative(self.field.get_extendee(), self.file, true, self.root_scope)
17     }
18 
repeated(&self) -> bool19     fn repeated(&self) -> bool {
20         match self.field.get_label() {
21             FieldDescriptorProto_Label::LABEL_REPEATED => true,
22             FieldDescriptorProto_Label::LABEL_OPTIONAL => false,
23             FieldDescriptorProto_Label::LABEL_REQUIRED => {
24                 panic!("required ext field: {}", self.field.get_name())
25             }
26         }
27     }
28 
return_type_gen(&self) -> ProtobufTypeGen29     fn return_type_gen(&self) -> ProtobufTypeGen {
30         if self.field.has_type_name() {
31             let rust_name_relative = type_name_to_rust_relative(
32                 self.field.get_type_name(),
33                 self.file,
34                 true,
35                 self.root_scope,
36             );
37             match self.field.get_field_type() {
38                 FieldDescriptorProto_Type::TYPE_MESSAGE => {
39                     ProtobufTypeGen::Message(rust_name_relative)
40                 }
41                 FieldDescriptorProto_Type::TYPE_ENUM => ProtobufTypeGen::Enum(rust_name_relative),
42                 t => panic!("unknown type: {:?}", t),
43             }
44         } else {
45             ProtobufTypeGen::Primitive(self.field.get_field_type(), PrimitiveTypeVariant::Default)
46         }
47     }
48 
write(&self, w: &mut CodeWriter)49     fn write(&self, w: &mut CodeWriter) {
50         let suffix = if self.repeated() {
51             "Repeated"
52         } else {
53             "Optional"
54         };
55         let field_type = format!("::protobuf::ext::ExtField{}", suffix);
56         w.pub_const(
57             &self.field.rust_name(),
58             &format!(
59                 "{}<{}, {}>",
60                 field_type,
61                 self.extendee_rust_name(),
62                 self.return_type_gen().rust_type(&self.customize),
63             ),
64             &format!(
65                 "{} {{ field_number: {}, phantom: ::std::marker::PhantomData }}",
66                 field_type,
67                 self.field.get_number()
68             ),
69         );
70     }
71 }
72 
write_extensions( file: &FileDescriptorProto, root_scope: &RootScope, w: &mut CodeWriter, customize: &Customize, )73 pub(crate) fn write_extensions(
74     file: &FileDescriptorProto,
75     root_scope: &RootScope,
76     w: &mut CodeWriter,
77     customize: &Customize,
78 ) {
79     if file.get_extension().is_empty() {
80         return;
81     }
82 
83     w.write_line("");
84     w.pub_mod("exts", |w| {
85         w.write_line("use protobuf::Message as Message_imported_for_functions;");
86 
87         for field in file.get_extension() {
88             if field.get_field_type() == FieldDescriptorProto_Type::TYPE_GROUP {
89                 continue;
90             }
91 
92             w.write_line("");
93             ExtGen {
94                 file: file,
95                 root_scope: root_scope,
96                 field: field,
97                 customize: customize.clone(),
98             }
99             .write(w);
100         }
101     });
102 }
103