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