1 //! Convert parser model to rust-protobuf model
2 
3 mod option_resolver;
4 mod type_resolver;
5 
6 use protobuf;
7 use protobuf::descriptor::descriptor_proto::ReservedRange;
8 use protobuf::descriptor::field_descriptor_proto;
9 use protobuf::descriptor::field_descriptor_proto::Type;
10 use protobuf::descriptor::FieldDescriptorProto;
11 use protobuf::descriptor::OneofDescriptorProto;
12 use protobuf::reflect::FileDescriptor;
13 use protobuf_support::json_name::json_name;
14 use protobuf_support::text_format::escape_bytes_to;
15 
16 use crate::case_convert::camel_case;
17 use crate::path::fs_path_to_proto_path;
18 use crate::proto_path::ProtoPath;
19 use crate::protobuf_abs_path::ProtobufAbsPath;
20 use crate::protobuf_ident::ProtobufIdent;
21 use crate::pure::convert::option_resolver::OptionResoler;
22 use crate::pure::convert::option_resolver::ProtobufOptions;
23 use crate::pure::convert::type_resolver::MessageOrEnum;
24 use crate::pure::convert::type_resolver::TypeResolver;
25 use crate::pure::model;
26 use crate::FileDescriptorPair;
27 use crate::ProtobufAbsPathRef;
28 use crate::ProtobufIdentRef;
29 
30 #[derive(Debug, thiserror::Error)]
31 enum ConvertError {
32     #[error("default value is not a string literal")]
33     DefaultValueIsNotStringLiteral,
34     #[error("expecting a message for name {0}")]
35     ExpectingMessage(ProtobufAbsPath),
36     #[error("expecting an enum for name {0}")]
37     ExpectingEnum(ProtobufAbsPath),
38 }
39 
40 pub struct WithFullName<T> {
41     full_name: ProtobufAbsPath,
42     t: T,
43 }
44 
45 #[derive(Debug, PartialEq)]
46 enum TypeResolved {
47     Int32,
48     Int64,
49     Uint32,
50     Uint64,
51     Sint32,
52     Sint64,
53     Bool,
54     Fixed64,
55     Sfixed64,
56     Double,
57     String,
58     Bytes,
59     Fixed32,
60     Sfixed32,
61     Float,
62     Message(ProtobufAbsPath),
63     Enum(ProtobufAbsPath),
64     Group(ProtobufAbsPath),
65 }
66 
67 impl TypeResolved {
from_field(field: &FieldDescriptorProto) -> TypeResolved68     fn from_field(field: &FieldDescriptorProto) -> TypeResolved {
69         match field.type_() {
70             Type::TYPE_DOUBLE => TypeResolved::Double,
71             Type::TYPE_FLOAT => TypeResolved::Float,
72             Type::TYPE_INT64 => TypeResolved::Int64,
73             Type::TYPE_UINT64 => TypeResolved::Uint64,
74             Type::TYPE_INT32 => TypeResolved::Int32,
75             Type::TYPE_FIXED64 => TypeResolved::Fixed64,
76             Type::TYPE_FIXED32 => TypeResolved::Fixed32,
77             Type::TYPE_UINT32 => TypeResolved::Uint32,
78             Type::TYPE_SFIXED32 => TypeResolved::Sfixed32,
79             Type::TYPE_SFIXED64 => TypeResolved::Sfixed64,
80             Type::TYPE_SINT32 => TypeResolved::Sint32,
81             Type::TYPE_SINT64 => TypeResolved::Sint64,
82             Type::TYPE_BOOL => TypeResolved::Bool,
83             Type::TYPE_STRING => TypeResolved::String,
84             Type::TYPE_BYTES => TypeResolved::Bytes,
85             Type::TYPE_GROUP => {
86                 assert!(!field.type_name().is_empty());
87                 TypeResolved::Group(ProtobufAbsPath::new(field.type_name()))
88             }
89             Type::TYPE_ENUM => {
90                 assert!(!field.type_name().is_empty());
91                 TypeResolved::Enum(ProtobufAbsPath::new(field.type_name()))
92             }
93             Type::TYPE_MESSAGE => {
94                 assert!(!field.type_name().is_empty());
95                 TypeResolved::Message(ProtobufAbsPath::new(field.type_name()))
96             }
97         }
98     }
99 
type_enum(&self) -> Type100     fn type_enum(&self) -> Type {
101         match self {
102             TypeResolved::Bool => Type::TYPE_BOOL,
103             TypeResolved::Int32 => Type::TYPE_INT32,
104             TypeResolved::Int64 => Type::TYPE_INT64,
105             TypeResolved::Uint32 => Type::TYPE_UINT32,
106             TypeResolved::Uint64 => Type::TYPE_UINT64,
107             TypeResolved::Sint32 => Type::TYPE_SINT32,
108             TypeResolved::Sint64 => Type::TYPE_SINT64,
109             TypeResolved::Fixed32 => Type::TYPE_FIXED32,
110             TypeResolved::Fixed64 => Type::TYPE_FIXED64,
111             TypeResolved::Sfixed32 => Type::TYPE_SFIXED32,
112             TypeResolved::Sfixed64 => Type::TYPE_SFIXED64,
113             TypeResolved::Float => Type::TYPE_FLOAT,
114             TypeResolved::Double => Type::TYPE_DOUBLE,
115             TypeResolved::String => Type::TYPE_STRING,
116             TypeResolved::Bytes => Type::TYPE_BYTES,
117             TypeResolved::Message(_) => Type::TYPE_MESSAGE,
118             TypeResolved::Enum(_) => Type::TYPE_ENUM,
119             TypeResolved::Group(_) => Type::TYPE_GROUP,
120         }
121     }
122 
type_name(&self) -> Option<&ProtobufAbsPath>123     fn type_name(&self) -> Option<&ProtobufAbsPath> {
124         match self {
125             TypeResolved::Message(t) | TypeResolved::Enum(t) | TypeResolved::Group(t) => Some(t),
126             _ => None,
127         }
128     }
129 }
130 
131 pub(crate) struct Resolver<'a> {
132     type_resolver: TypeResolver<'a>,
133     current_file: &'a model::FileDescriptor,
134 }
135 
136 impl<'a> Resolver<'a> {
map_entry_name_for_field_name(field_name: &str) -> ProtobufIdent137     fn map_entry_name_for_field_name(field_name: &str) -> ProtobufIdent {
138         // Field name and message name must match, otherwise
139         // Google's validation fails.
140         // https://git.io/JeOvF
141         ProtobufIdent::from(format!("{}Entry", camel_case(field_name)))
142     }
143 
map_entry_field( &self, scope: &ProtobufAbsPath, name: &str, number: i32, field_type: &model::FieldType, ) -> anyhow::Result<protobuf::descriptor::FieldDescriptorProto>144     fn map_entry_field(
145         &self,
146         scope: &ProtobufAbsPath,
147         name: &str,
148         number: i32,
149         field_type: &model::FieldType,
150     ) -> anyhow::Result<protobuf::descriptor::FieldDescriptorProto> {
151         // should be consisent with DescriptorBuilder::ValidateMapEntry
152 
153         let mut output = protobuf::descriptor::FieldDescriptorProto::new();
154 
155         output.set_name(name.to_owned());
156         output.set_number(number);
157 
158         let t = self.field_type(&scope, name, field_type)?;
159         output.set_type(t.type_enum());
160         if let Some(t_name) = t.type_name() {
161             output.set_type_name(t_name.path.clone());
162         }
163 
164         output.set_label(field_descriptor_proto::Label::LABEL_OPTIONAL);
165 
166         output.set_json_name(json_name(&name));
167 
168         Ok(output)
169     }
170 
map_entry_message( &self, scope: &ProtobufAbsPath, field_name: &str, key: &model::FieldType, value: &model::FieldType, ) -> anyhow::Result<protobuf::descriptor::DescriptorProto>171     fn map_entry_message(
172         &self,
173         scope: &ProtobufAbsPath,
174         field_name: &str,
175         key: &model::FieldType,
176         value: &model::FieldType,
177     ) -> anyhow::Result<protobuf::descriptor::DescriptorProto> {
178         let mut output = protobuf::descriptor::DescriptorProto::new();
179 
180         output.options.mut_or_insert_default().set_map_entry(true);
181         output.set_name(Resolver::map_entry_name_for_field_name(field_name).into_string());
182         output
183             .field
184             .push(self.map_entry_field(&scope, "key", 1, key)?);
185         output
186             .field
187             .push(self.map_entry_field(&scope, "value", 2, value)?);
188 
189         Ok(output)
190     }
191 
group_message( &self, scope: &ProtobufAbsPath, name: &str, fields: &[model::WithLoc<model::Field>], ) -> anyhow::Result<protobuf::descriptor::DescriptorProto>192     fn group_message(
193         &self,
194         scope: &ProtobufAbsPath,
195         name: &str,
196         fields: &[model::WithLoc<model::Field>],
197     ) -> anyhow::Result<protobuf::descriptor::DescriptorProto> {
198         let mut output = protobuf::descriptor::DescriptorProto::new();
199 
200         output.set_name(name.to_owned());
201 
202         for f in fields {
203             output.field.push(self.field(scope, f, None)?);
204         }
205 
206         Ok(output)
207     }
208 
message( &self, scope: &ProtobufAbsPathRef, input: &model::Message, ) -> anyhow::Result<protobuf::descriptor::DescriptorProto>209     fn message(
210         &self,
211         scope: &ProtobufAbsPathRef,
212         input: &model::Message,
213     ) -> anyhow::Result<protobuf::descriptor::DescriptorProto> {
214         let mut nested_scope = scope.to_owned();
215         nested_scope.push_simple(ProtobufIdentRef::new(&input.name));
216 
217         let mut output = protobuf::descriptor::DescriptorProto::new();
218         output.set_name(input.name.clone());
219 
220         let mut nested_messages = Vec::new();
221 
222         for m in &input.messages {
223             let message = self.message(&nested_scope, &m.t)?;
224             nested_messages.push(model::WithLoc {
225                 t: message,
226                 loc: m.loc,
227             });
228         }
229 
230         for f in input.regular_fields_including_in_oneofs() {
231             match &f.t.typ {
232                 model::FieldType::Map(t) => {
233                     let message = self.map_entry_message(&nested_scope, &f.t.name, &t.0, &t.1)?;
234                     nested_messages.push(model::WithLoc {
235                         t: message,
236                         loc: f.loc,
237                     });
238                 }
239                 model::FieldType::Group(model::Group {
240                     name: group_name,
241                     fields,
242                     ..
243                 }) => {
244                     let message = self.group_message(&nested_scope, group_name, fields)?;
245                     nested_messages.push(model::WithLoc {
246                         t: message,
247                         loc: f.loc,
248                     });
249                 }
250                 _ => (),
251             }
252         }
253 
254         // Preserve declaration order
255         nested_messages.sort_by_key(|m| m.loc);
256         output.nested_type = nested_messages
257             .into_iter()
258             .map(|model::WithLoc { t, .. }| t)
259             .collect();
260 
261         output.enum_type = input
262             .enums
263             .iter()
264             .map(|e| self.enumeration(scope, e))
265             .collect::<Result<_, _>>()?;
266 
267         {
268             let mut fields = Vec::new();
269 
270             for fo in &input.fields {
271                 match &fo.t {
272                     model::FieldOrOneOf::Field(f) => {
273                         let oneof_index = if self.is_proto3_optional(f) {
274                             let oneof_index = output.oneof_decl.len() as i32;
275                             let mut oneof = OneofDescriptorProto::new();
276                             oneof.set_name(format!("_{}", f.name));
277                             output.oneof_decl.push(oneof);
278                             Some(oneof_index)
279                         } else {
280                             None
281                         };
282                         fields.push(self.field(&nested_scope, f, oneof_index)?);
283                     }
284                     model::FieldOrOneOf::OneOf(o) => {
285                         let oneof_index = output.oneof_decl.len();
286                         for f in &o.fields {
287                             fields.push(self.field(&nested_scope, f, Some(oneof_index as i32))?);
288                         }
289                         output.oneof_decl.push(self.oneof(scope, o)?);
290                     }
291                 }
292             }
293 
294             output.field = fields;
295         }
296 
297         for ext in &input.extension_ranges {
298             let mut extension_range = protobuf::descriptor::descriptor_proto::ExtensionRange::new();
299             extension_range.set_start(ext.from);
300             extension_range.set_end(ext.to + 1);
301             output.extension_range.push(extension_range);
302         }
303         for ext in &input.extensions {
304             let mut extension = self.field(scope, &ext.t.field, None)?;
305             extension.set_extendee(
306                 self.type_resolver
307                     .resolve_message_or_enum(scope, &ext.t.extendee)?
308                     .full_name
309                     .path,
310             );
311             output.extension.push(extension);
312         }
313 
314         for reserved in &input.reserved_nums {
315             let mut reserved_range = ReservedRange::new();
316             reserved_range.set_start(reserved.from);
317             reserved_range.set_end(reserved.to + 1);
318             output.reserved_range.push(reserved_range);
319         }
320         output.reserved_name = input.reserved_names.clone().into();
321 
322         Ok(output)
323     }
324 
service_method( &self, input: &model::Method, ) -> anyhow::Result<protobuf::descriptor::MethodDescriptorProto>325     fn service_method(
326         &self,
327         input: &model::Method,
328     ) -> anyhow::Result<protobuf::descriptor::MethodDescriptorProto> {
329         let scope = &self.current_file.package;
330         let mut output = protobuf::descriptor::MethodDescriptorProto::new();
331         output.set_name(input.name.clone());
332         output.set_input_type(
333             self.type_resolver
334                 .resolve_message_or_enum(scope, &input.input_type)?
335                 .full_name
336                 .to_string(),
337         );
338         output.set_output_type(
339             self.type_resolver
340                 .resolve_message_or_enum(scope, &input.output_type)?
341                 .full_name
342                 .to_string(),
343         );
344         Ok(output)
345     }
346 
service( &self, input: &model::Service, ) -> anyhow::Result<protobuf::descriptor::ServiceDescriptorProto>347     fn service(
348         &self,
349         input: &model::Service,
350     ) -> anyhow::Result<protobuf::descriptor::ServiceDescriptorProto> {
351         let mut output = protobuf::descriptor::ServiceDescriptorProto::new();
352         output.set_name(input.name.clone());
353 
354         output.method = input
355             .methods
356             .iter()
357             .map(|m| self.service_method(m))
358             .collect::<Result<_, _>>()?;
359 
360         Ok(output)
361     }
362 
is_proto3_optional(&self, input: &model::WithLoc<model::Field>) -> bool363     fn is_proto3_optional(&self, input: &model::WithLoc<model::Field>) -> bool {
364         (self.current_file.syntax, input.t.rule)
365             == (model::Syntax::Proto3, Some(model::Rule::Optional))
366     }
367 
field( &self, scope: &ProtobufAbsPathRef, input: &model::WithLoc<model::Field>, oneof_index: Option<i32>, ) -> anyhow::Result<protobuf::descriptor::FieldDescriptorProto>368     fn field(
369         &self,
370         scope: &ProtobufAbsPathRef,
371         input: &model::WithLoc<model::Field>,
372         oneof_index: Option<i32>,
373     ) -> anyhow::Result<protobuf::descriptor::FieldDescriptorProto> {
374         let mut output = protobuf::descriptor::FieldDescriptorProto::new();
375         output.set_name(input.t.name.clone());
376 
377         if let model::FieldType::Map(..) = input.t.typ {
378             output.set_label(protobuf::descriptor::field_descriptor_proto::Label::LABEL_REPEATED);
379         } else {
380             output.set_label(label(input.t.rule));
381 
382             if self.is_proto3_optional(input) {
383                 output.set_proto3_optional(true);
384             }
385         }
386 
387         let t = self.field_type(scope, &input.t.name, &input.t.typ)?;
388         output.set_type(t.type_enum());
389         if let Some(t_name) = t.type_name() {
390             output.set_type_name(t_name.path.clone());
391         }
392 
393         output.set_number(input.t.number);
394         // TODO: move default to option parser
395         if let Some(ref default) = input.t.options.as_slice().by_name("default") {
396             let default = match output.type_() {
397                 protobuf::descriptor::field_descriptor_proto::Type::TYPE_STRING => {
398                     if let &model::ProtobufConstant::String(ref s) = default {
399                         s.decode_utf8()?
400                     } else {
401                         return Err(ConvertError::DefaultValueIsNotStringLiteral.into());
402                     }
403                 }
404                 protobuf::descriptor::field_descriptor_proto::Type::TYPE_BYTES => {
405                     if let &model::ProtobufConstant::String(ref s) = default {
406                         let mut buf = String::new();
407                         escape_bytes_to(&s.decode_bytes()?, &mut buf);
408                         buf
409                     } else {
410                         return Err(ConvertError::DefaultValueIsNotStringLiteral.into());
411                     }
412                 }
413                 _ => default.format(),
414             };
415             output.set_default_value(default);
416         }
417 
418         if let Some(oneof_index) = oneof_index {
419             output.set_oneof_index(oneof_index);
420         }
421 
422         if let Some(json_name) = input.t.options.as_slice().by_name_string("json_name")? {
423             output.set_json_name(json_name);
424         } else {
425             output.set_json_name(json_name(&input.t.name));
426         }
427 
428         Ok(output)
429     }
430 
find_message_by_abs_name( &self, abs_path: &ProtobufAbsPath, ) -> anyhow::Result<WithFullName<&'a model::Message>>431     fn find_message_by_abs_name(
432         &self,
433         abs_path: &ProtobufAbsPath,
434     ) -> anyhow::Result<WithFullName<&'a model::Message>> {
435         let with_full_name = self
436             .type_resolver
437             .find_message_or_enum_by_abs_name(abs_path)?;
438         match with_full_name.t {
439             MessageOrEnum::Message(m) => Ok(WithFullName {
440                 t: m,
441                 full_name: with_full_name.full_name,
442             }),
443             MessageOrEnum::Enum(..) => Err(ConvertError::ExpectingMessage(abs_path.clone()).into()),
444         }
445     }
446 
find_enum_by_abs_name( &self, abs_path: &ProtobufAbsPath, ) -> anyhow::Result<&'a model::Enumeration>447     fn find_enum_by_abs_name(
448         &self,
449         abs_path: &ProtobufAbsPath,
450     ) -> anyhow::Result<&'a model::Enumeration> {
451         match self
452             .type_resolver
453             .find_message_or_enum_by_abs_name(abs_path)?
454             .t
455         {
456             MessageOrEnum::Enum(e) => Ok(e),
457             MessageOrEnum::Message(..) => Err(ConvertError::ExpectingEnum(abs_path.clone()).into()),
458         }
459     }
460 
field_type( &self, scope: &ProtobufAbsPathRef, name: &str, input: &model::FieldType, ) -> anyhow::Result<TypeResolved>461     fn field_type(
462         &self,
463         scope: &ProtobufAbsPathRef,
464         name: &str,
465         input: &model::FieldType,
466     ) -> anyhow::Result<TypeResolved> {
467         Ok(match *input {
468             model::FieldType::Bool => TypeResolved::Bool,
469             model::FieldType::Int32 => TypeResolved::Int32,
470             model::FieldType::Int64 => TypeResolved::Int64,
471             model::FieldType::Uint32 => TypeResolved::Uint32,
472             model::FieldType::Uint64 => TypeResolved::Uint64,
473             model::FieldType::Sint32 => TypeResolved::Sint32,
474             model::FieldType::Sint64 => TypeResolved::Sint64,
475             model::FieldType::Fixed32 => TypeResolved::Fixed32,
476             model::FieldType::Fixed64 => TypeResolved::Fixed64,
477             model::FieldType::Sfixed32 => TypeResolved::Sfixed32,
478             model::FieldType::Sfixed64 => TypeResolved::Sfixed64,
479             model::FieldType::Float => TypeResolved::Float,
480             model::FieldType::Double => TypeResolved::Double,
481             model::FieldType::String => TypeResolved::String,
482             model::FieldType::Bytes => TypeResolved::Bytes,
483             model::FieldType::MessageOrEnum(ref name) => {
484                 let t = self.type_resolver.resolve_message_or_enum(scope, &name)?;
485                 match t.t {
486                     MessageOrEnum::Message(..) => TypeResolved::Message(t.full_name),
487                     MessageOrEnum::Enum(..) => TypeResolved::Enum(t.full_name),
488                 }
489             }
490             model::FieldType::Map(..) => {
491                 let mut type_name = scope.to_owned();
492                 type_name.push_simple(&Resolver::map_entry_name_for_field_name(name));
493                 TypeResolved::Message(type_name)
494             }
495             model::FieldType::Group(model::Group {
496                 name: ref group_name,
497                 ..
498             }) => {
499                 let mut type_name = scope.to_owned();
500                 type_name.push_simple(ProtobufIdentRef::new(group_name));
501                 TypeResolved::Group(type_name)
502             }
503         })
504     }
505 
enum_value( &self, _scope: &ProtobufAbsPathRef, input: &model::EnumValue, ) -> anyhow::Result<protobuf::descriptor::EnumValueDescriptorProto>506     fn enum_value(
507         &self,
508         _scope: &ProtobufAbsPathRef,
509         input: &model::EnumValue,
510     ) -> anyhow::Result<protobuf::descriptor::EnumValueDescriptorProto> {
511         let mut output = protobuf::descriptor::EnumValueDescriptorProto::new();
512         output.set_name(input.name.clone());
513         output.set_number(input.number);
514         Ok(output)
515     }
516 
enumeration( &self, scope: &ProtobufAbsPathRef, input: &model::Enumeration, ) -> anyhow::Result<protobuf::descriptor::EnumDescriptorProto>517     fn enumeration(
518         &self,
519         scope: &ProtobufAbsPathRef,
520         input: &model::Enumeration,
521     ) -> anyhow::Result<protobuf::descriptor::EnumDescriptorProto> {
522         let mut output = protobuf::descriptor::EnumDescriptorProto::new();
523         output.set_name(input.name.clone());
524         output.value = input
525             .values
526             .iter()
527             .map(|v| self.enum_value(scope, &v))
528             .collect::<Result<_, _>>()?;
529         Ok(output)
530     }
531 
oneof( &self, _scope: &ProtobufAbsPathRef, input: &model::OneOf, ) -> anyhow::Result<protobuf::descriptor::OneofDescriptorProto>532     fn oneof(
533         &self,
534         _scope: &ProtobufAbsPathRef,
535         input: &model::OneOf,
536     ) -> anyhow::Result<protobuf::descriptor::OneofDescriptorProto> {
537         let mut output = protobuf::descriptor::OneofDescriptorProto::new();
538         output.set_name(input.name.clone());
539         Ok(output)
540     }
541 
extension( &self, scope: &ProtobufAbsPath, input: &model::Extension, ) -> anyhow::Result<( protobuf::descriptor::FieldDescriptorProto, Option<protobuf::descriptor::DescriptorProto>, )>542     fn extension(
543         &self,
544         scope: &ProtobufAbsPath,
545         input: &model::Extension,
546     ) -> anyhow::Result<(
547         protobuf::descriptor::FieldDescriptorProto,
548         Option<protobuf::descriptor::DescriptorProto>,
549     )> {
550         let mut field = self.field(scope, &input.field, None)?;
551         field.set_extendee(
552             self.type_resolver
553                 .resolve_message_or_enum(scope, &input.extendee)?
554                 .full_name
555                 .to_string(),
556         );
557         let group_messages = if let model::FieldType::Group(g) = &input.field.t.typ {
558             Some(self.group_message(scope, &g.name, &g.fields)?)
559         } else {
560             None
561         };
562         Ok((field, group_messages))
563     }
564 }
565 
syntax(input: model::Syntax) -> String566 fn syntax(input: model::Syntax) -> String {
567     match input {
568         model::Syntax::Proto2 => "proto2".to_owned(),
569         model::Syntax::Proto3 => "proto3".to_owned(),
570     }
571 }
572 
label(input: Option<model::Rule>) -> protobuf::descriptor::field_descriptor_proto::Label573 fn label(input: Option<model::Rule>) -> protobuf::descriptor::field_descriptor_proto::Label {
574     match input {
575         Some(model::Rule::Optional) => {
576             protobuf::descriptor::field_descriptor_proto::Label::LABEL_OPTIONAL
577         }
578         Some(model::Rule::Required) => {
579             protobuf::descriptor::field_descriptor_proto::Label::LABEL_REQUIRED
580         }
581         Some(model::Rule::Repeated) => {
582             protobuf::descriptor::field_descriptor_proto::Label::LABEL_REPEATED
583         }
584         None => protobuf::descriptor::field_descriptor_proto::Label::LABEL_OPTIONAL,
585     }
586 }
587 
populate_dependencies( input: &model::FileDescriptor, output: &mut protobuf::descriptor::FileDescriptorProto, )588 pub(crate) fn populate_dependencies(
589     input: &model::FileDescriptor,
590     output: &mut protobuf::descriptor::FileDescriptorProto,
591 ) {
592     for import in &input.imports {
593         if import.vis == model::ImportVis::Public {
594             output
595                 .public_dependency
596                 .push(output.dependency.len() as i32);
597         } else if import.vis == model::ImportVis::Weak {
598             output.weak_dependency.push(output.dependency.len() as i32);
599         }
600         output.dependency.push(import.path.to_string());
601     }
602 }
603 
file_descriptor( name: &ProtoPath, input: &model::FileDescriptor, deps: &[FileDescriptorPair], ) -> anyhow::Result<protobuf::descriptor::FileDescriptorProto>604 pub(crate) fn file_descriptor(
605     name: &ProtoPath,
606     input: &model::FileDescriptor,
607     deps: &[FileDescriptorPair],
608 ) -> anyhow::Result<protobuf::descriptor::FileDescriptorProto> {
609     let resolver = Resolver {
610         current_file: &input,
611         type_resolver: TypeResolver {
612             current_file: &input,
613             deps,
614         },
615     };
616 
617     let mut output = protobuf::descriptor::FileDescriptorProto::new();
618     output.set_name(fs_path_to_proto_path(name));
619     output.set_syntax(syntax(input.syntax));
620 
621     if input.package != ProtobufAbsPath::root() {
622         output.set_package(input.package.to_root_rel().to_string());
623     }
624 
625     populate_dependencies(&input, &mut output);
626 
627     let mut messages = Vec::new();
628     let mut services = Vec::new();
629 
630     let mut extensions = Vec::new();
631     for e in &input.extensions {
632         let (ext, group_messages) = resolver.extension(&resolver.current_file.package, &e.t)?;
633         extensions.push(ext);
634         messages.extend(group_messages.map(model::WithLoc::with_loc(e.loc)));
635     }
636     output.extension = extensions;
637 
638     for m in &input.messages {
639         let message = resolver.message(&resolver.current_file.package, &m.t)?;
640         messages.push(model::WithLoc {
641             t: message,
642             loc: m.loc,
643         });
644     }
645 
646     for s in &input.services {
647         let service = resolver.service(&s.t)?;
648         services.push(model::WithLoc {
649             t: service,
650             loc: s.loc,
651         })
652     }
653 
654     // Preserve declaration order
655     messages.sort_by_key(|m| m.loc);
656     output.message_type = messages
657         .into_iter()
658         .map(|model::WithLoc { t, .. }| t)
659         .collect();
660 
661     output.enum_type = input
662         .enums
663         .iter()
664         .map(|e| resolver.enumeration(&resolver.current_file.package, e))
665         .collect::<Result<_, _>>()?;
666 
667     output.service = services
668         .into_iter()
669         .map(|model::WithLoc { t, .. }| t)
670         .collect();
671 
672     let descriptor_without_options = FileDescriptor::new_dynamic(
673         output.clone(),
674         &deps
675             .iter()
676             .map(|d| d.descriptor.clone())
677             .collect::<Vec<_>>(),
678     )?;
679 
680     let option_resolver = OptionResoler {
681         resolver: &resolver,
682         descriptor_without_options,
683     };
684 
685     option_resolver.file(&mut output)?;
686 
687     Ok(output)
688 }
689