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