1 use anyhow::Context;
2 use protobuf::descriptor::DescriptorProto;
3 use protobuf::descriptor::EnumDescriptorProto;
4 use protobuf::descriptor::EnumValueDescriptorProto;
5 use protobuf::descriptor::FieldDescriptorProto;
6 use protobuf::descriptor::FileDescriptorProto;
7 use protobuf::descriptor::MethodDescriptorProto;
8 use protobuf::descriptor::OneofDescriptorProto;
9 use protobuf::descriptor::ServiceDescriptorProto;
10 use protobuf::reflect::FieldDescriptor;
11 use protobuf::reflect::FileDescriptor;
12 use protobuf::reflect::MessageDescriptor;
13 use protobuf::MessageFull;
14 use protobuf::UnknownFields;
15 use protobuf::UnknownValue;
16 use protobuf_support::lexer::str_lit::StrLitDecodeError;
17 
18 use crate::model;
19 use crate::model::ProtobufConstant;
20 use crate::model::ProtobufConstantMessage;
21 use crate::model::ProtobufConstantMessageFieldName;
22 use crate::model::ProtobufOptionName;
23 use crate::model::ProtobufOptionNameExt;
24 use crate::model::ProtobufOptionNamePart;
25 use crate::model::WithLoc;
26 use crate::protobuf_path::ProtobufPath;
27 use crate::pure::convert::Resolver;
28 use crate::pure::convert::TypeResolved;
29 use crate::ProtobufAbsPath;
30 use crate::ProtobufAbsPathRef;
31 use crate::ProtobufIdent;
32 use crate::ProtobufIdentRef;
33 use crate::ProtobufRelPath;
34 use crate::ProtobufRelPathRef;
35 
36 #[derive(Debug, thiserror::Error)]
37 enum OptionResolverError {
38     #[error(transparent)]
39     OtherError(anyhow::Error),
40     #[error("extension is not a message: {0}")]
41     ExtensionIsNotMessage(String),
42     #[error("unknown field name: {0}")]
43     UnknownFieldName(String),
44     #[error("wrong extension type: option {0} extendee {1} expected extendee {2}")]
45     WrongExtensionType(String, String, String),
46     #[error("extension not found: {0}")]
47     ExtensionNotFound(String),
48     #[error("unknown enum value: {0}")]
49     UnknownEnumValue(String),
50     #[error("unsupported extension type: {0} {1} {2}")]
51     UnsupportedExtensionType(String, String, model::ProtobufConstant),
52     #[error("builtin option {0} not found for options {1}")]
53     BuiltinOptionNotFound(String, String),
54     #[error("builtin option {0} points to a non-singular field of {1}")]
55     BuiltinOptionPointsToNonSingularField(String, String),
56     #[error("incorrect string literal: {0}")]
57     StrLitDecodeError(#[source] StrLitDecodeError),
58     #[error("wrong option type, expecting {0}, got `{1}`")]
59     WrongOptionType(&'static str, String),
60     #[error("Message field requires a message constant")]
61     MessageFieldRequiresMessageConstant,
62     #[error("message not found by name {0}")]
63     MessageNotFound(ProtobufAbsPath),
64     #[error("message not found by name {0}")]
65     MessageFoundMoreThanOnce(ProtobufAbsPath),
66 }
67 
68 #[derive(Clone)]
69 enum LookupScope2 {
70     File(FileDescriptor),
71     Message(MessageDescriptor, ProtobufAbsPath),
72 }
73 
74 impl LookupScope2 {
current_path(&self) -> ProtobufAbsPath75     fn current_path(&self) -> ProtobufAbsPath {
76         match self {
77             LookupScope2::File(f) => ProtobufAbsPath::package_from_file_descriptor(f),
78             LookupScope2::Message(_, p) => p.clone(),
79         }
80     }
81 
messages(&self) -> Vec<MessageDescriptor>82     fn messages(&self) -> Vec<MessageDescriptor> {
83         match self {
84             LookupScope2::File(file) => file.messages().collect(),
85             LookupScope2::Message(message, _) => message.nested_messages().collect(),
86         }
87     }
88 
down(&self, name: &ProtobufIdentRef) -> Option<LookupScope2>89     fn down(&self, name: &ProtobufIdentRef) -> Option<LookupScope2> {
90         match self.messages().iter().find(|m| m.name() == name.as_str()) {
91             Some(m) => {
92                 let mut path = self.current_path();
93                 path.push_simple(name.clone());
94                 Some(LookupScope2::Message(m.clone(), path))
95             }
96             None => None,
97         }
98     }
99 
extensions(&self) -> Vec<FieldDescriptor>100     fn extensions(&self) -> Vec<FieldDescriptor> {
101         match self {
102             LookupScope2::File(f) => f.extensions().collect(),
103             LookupScope2::Message(m, _) => m.extensions().collect(),
104         }
105     }
106 }
107 
108 #[derive(Clone)]
109 pub(crate) struct LookupScopeUnion2 {
110     path: ProtobufAbsPath,
111     scopes: Vec<LookupScope2>,
112     partial_scopes: Vec<FileDescriptor>,
113 }
114 
115 impl LookupScopeUnion2 {
down(&self, name: &ProtobufIdentRef) -> LookupScopeUnion2116     fn down(&self, name: &ProtobufIdentRef) -> LookupScopeUnion2 {
117         let mut path: ProtobufAbsPath = self.path.clone();
118         path.push_simple(name);
119 
120         let mut scopes: Vec<_> = self.scopes.iter().flat_map(|f| f.down(name)).collect();
121         let mut partial_scopes = Vec::new();
122 
123         for partial_scope in &self.partial_scopes {
124             let package = ProtobufAbsPath::package_from_file_descriptor(partial_scope);
125             if package.as_ref() == path.as_ref() {
126                 scopes.push(LookupScope2::File(partial_scope.clone()));
127             } else if package.starts_with(&path) {
128                 partial_scopes.push(partial_scope.clone());
129             }
130         }
131         LookupScopeUnion2 {
132             path,
133             scopes,
134             partial_scopes,
135         }
136     }
137 
lookup(&self, path: &ProtobufRelPath) -> LookupScopeUnion2138     fn lookup(&self, path: &ProtobufRelPath) -> LookupScopeUnion2 {
139         let mut scope = self.clone();
140         for c in path.components() {
141             scope = scope.down(c);
142         }
143         scope
144     }
145 
extensions(&self) -> Vec<FieldDescriptor>146     fn extensions(&self) -> Vec<FieldDescriptor> {
147         self.scopes.iter().flat_map(|s| s.extensions()).collect()
148     }
149 
as_message(&self) -> anyhow::Result<MessageDescriptor>150     fn as_message(&self) -> anyhow::Result<MessageDescriptor> {
151         let mut messages: Vec<MessageDescriptor> = self
152             .scopes
153             .iter()
154             .filter_map(|s| match s {
155                 LookupScope2::Message(m, _) => Some(m.clone()),
156                 _ => None,
157             })
158             .collect();
159         let message = match messages.pop() {
160             Some(m) => m,
161             None => return Err(OptionResolverError::MessageNotFound(self.path.clone()).into()),
162         };
163         if !messages.is_empty() {
164             return Err(OptionResolverError::MessageFoundMoreThanOnce(self.path.clone()).into());
165         }
166         Ok(message)
167     }
168 }
169 
170 pub(crate) trait ProtobufOptions {
by_name(&self, name: &str) -> Option<&model::ProtobufConstant>171     fn by_name(&self, name: &str) -> Option<&model::ProtobufConstant>;
172 
by_name_bool(&self, name: &str) -> anyhow::Result<Option<bool>>173     fn by_name_bool(&self, name: &str) -> anyhow::Result<Option<bool>> {
174         match self.by_name(name) {
175             Some(model::ProtobufConstant::Bool(b)) => Ok(Some(*b)),
176             Some(c) => Err(OptionResolverError::WrongOptionType("bool", c.to_string()).into()),
177             None => Ok(None),
178         }
179     }
180 
by_name_string(&self, name: &str) -> anyhow::Result<Option<String>>181     fn by_name_string(&self, name: &str) -> anyhow::Result<Option<String>> {
182         match self.by_name(name) {
183             Some(model::ProtobufConstant::String(s)) => s
184                 .decode_utf8()
185                 .map(Some)
186                 .map_err(|e| OptionResolverError::StrLitDecodeError(e).into()),
187             Some(c) => Err(OptionResolverError::WrongOptionType("string", c.to_string()).into()),
188             None => Ok(None),
189         }
190     }
191 }
192 
193 impl<'a> ProtobufOptions for &'a [model::ProtobufOption] {
by_name(&self, name: &str) -> Option<&model::ProtobufConstant>194     fn by_name(&self, name: &str) -> Option<&model::ProtobufConstant> {
195         let option_name = ProtobufOptionName::simple(name);
196         for model::ProtobufOption { name, value } in *self {
197             if name == &option_name {
198                 return Some(&value);
199             }
200         }
201         None
202     }
203 }
204 
205 pub(crate) struct OptionResoler<'a> {
206     pub(crate) resolver: &'a Resolver<'a>,
207     pub(crate) descriptor_without_options: FileDescriptor,
208 }
209 
210 impl<'a> OptionResoler<'a> {
all_files(&self) -> Vec<FileDescriptor>211     fn all_files(&self) -> Vec<FileDescriptor> {
212         let mut files = Vec::new();
213         files.push(self.descriptor_without_options.clone());
214         files.extend(
215             self.resolver
216                 .type_resolver
217                 .deps
218                 .iter()
219                 .map(|p| p.descriptor.clone()),
220         );
221         files
222     }
223 
root_scope(&self) -> LookupScopeUnion2224     fn root_scope(&self) -> LookupScopeUnion2 {
225         let (scopes, partial_scopes) = self
226             .all_files()
227             .into_iter()
228             .partition::<Vec<_>, _>(|f| ProtobufAbsPath::package_from_file_descriptor(f).is_root());
229         LookupScopeUnion2 {
230             path: ProtobufAbsPath::root(),
231             scopes: scopes.into_iter().map(LookupScope2::File).collect(),
232             partial_scopes,
233         }
234     }
235 
lookup(&self, path: &ProtobufAbsPath) -> LookupScopeUnion2236     fn lookup(&self, path: &ProtobufAbsPath) -> LookupScopeUnion2 {
237         self.root_scope().lookup(&path.to_root_rel())
238     }
239 
find_message_by_abs_name( &self, path: &ProtobufAbsPath, ) -> anyhow::Result<MessageDescriptor>240     fn find_message_by_abs_name(
241         &self,
242         path: &ProtobufAbsPath,
243     ) -> anyhow::Result<MessageDescriptor> {
244         let scope = self.lookup(path);
245         scope.as_message()
246     }
247 
scope_resolved_candidates_rel( scope: &ProtobufAbsPathRef, rel: &ProtobufRelPathRef, ) -> Vec<ProtobufAbsPath>248     fn scope_resolved_candidates_rel(
249         scope: &ProtobufAbsPathRef,
250         rel: &ProtobufRelPathRef,
251     ) -> Vec<ProtobufAbsPath> {
252         scope
253             .self_and_parents()
254             .into_iter()
255             .map(|a| {
256                 let mut a = a.to_owned();
257                 a.push_relative(rel);
258                 a
259             })
260             .collect()
261     }
262 
scope_resolved_candidates( scope: &ProtobufAbsPathRef, path: &ProtobufPath, ) -> Vec<ProtobufAbsPath>263     fn scope_resolved_candidates(
264         scope: &ProtobufAbsPathRef,
265         path: &ProtobufPath,
266     ) -> Vec<ProtobufAbsPath> {
267         match path {
268             ProtobufPath::Abs(p) => vec![p.clone()],
269             ProtobufPath::Rel(p) => Self::scope_resolved_candidates_rel(scope, p),
270         }
271     }
272 
find_extension_by_abs_path( &self, path: &ProtobufAbsPathRef, ) -> anyhow::Result<Option<FieldDescriptor>>273     fn find_extension_by_abs_path(
274         &self,
275         path: &ProtobufAbsPathRef,
276     ) -> anyhow::Result<Option<FieldDescriptor>> {
277         let mut path = path.to_owned();
278         let extension = path.pop().unwrap();
279 
280         let scope = self.lookup(&path);
281 
282         for ext in scope.extensions() {
283             if ext.name() == extension.get() {
284                 return Ok(Some(ext.clone()));
285             }
286         }
287 
288         Ok(None)
289     }
290 
find_extension_by_path( &self, scope: &ProtobufAbsPathRef, path: &ProtobufPath, ) -> anyhow::Result<FieldDescriptor>291     fn find_extension_by_path(
292         &self,
293         scope: &ProtobufAbsPathRef,
294         path: &ProtobufPath,
295     ) -> anyhow::Result<FieldDescriptor> {
296         for candidate in Self::scope_resolved_candidates(scope, path) {
297             if let Some(e) = self.find_extension_by_abs_path(&candidate)? {
298                 return Ok(e);
299             }
300         }
301 
302         Err(OptionResolverError::ExtensionNotFound(path.to_string()).into())
303     }
304 
ext_resolve_field_ext( &self, scope: &ProtobufAbsPathRef, message: &MessageDescriptor, field_name: &ProtobufPath, ) -> anyhow::Result<FieldDescriptor>305     fn ext_resolve_field_ext(
306         &self,
307         scope: &ProtobufAbsPathRef,
308         message: &MessageDescriptor,
309         field_name: &ProtobufPath,
310     ) -> anyhow::Result<FieldDescriptor> {
311         let expected_extendee = ProtobufAbsPath::from_message(message);
312         let field = self.find_extension_by_path(scope, field_name)?;
313         if ProtobufAbsPath::new(field.proto().extendee()) != expected_extendee {
314             return Err(OptionResolverError::WrongExtensionType(
315                 format!("{}", field_name),
316                 format!("{}", field.proto().extendee()),
317                 format!("{}", expected_extendee),
318             )
319             .into());
320         }
321 
322         Ok(field)
323     }
324 
ext_resolve_field( &self, scope: &ProtobufAbsPathRef, message: &MessageDescriptor, field: &ProtobufOptionNamePart, ) -> anyhow::Result<FieldDescriptor>325     fn ext_resolve_field(
326         &self,
327         scope: &ProtobufAbsPathRef,
328         message: &MessageDescriptor,
329         field: &ProtobufOptionNamePart,
330     ) -> anyhow::Result<FieldDescriptor> {
331         match field {
332             ProtobufOptionNamePart::Direct(field) => match message.field_by_name(field.get()) {
333                 Some(field) => Ok(field),
334                 None => Err(OptionResolverError::UnknownFieldName(field.to_string()).into()),
335             },
336             ProtobufOptionNamePart::Ext(field) => {
337                 Ok(self.ext_resolve_field_ext(scope, message, field)?)
338             }
339         }
340     }
341 
custom_option_ext_step( &self, scope: &ProtobufAbsPathRef, options_type: &MessageDescriptor, options: &mut UnknownFields, option_name: &ProtobufOptionNamePart, option_name_rem: &[ProtobufOptionNamePart], option_value: &ProtobufConstant, ) -> anyhow::Result<()>342     fn custom_option_ext_step(
343         &self,
344         scope: &ProtobufAbsPathRef,
345         options_type: &MessageDescriptor,
346         options: &mut UnknownFields,
347         option_name: &ProtobufOptionNamePart,
348         option_name_rem: &[ProtobufOptionNamePart],
349         option_value: &ProtobufConstant,
350     ) -> anyhow::Result<()> {
351         let field = self.ext_resolve_field(scope, options_type, option_name)?;
352 
353         let field_type = TypeResolved::from_field(field.proto());
354 
355         match option_name_rem.split_first() {
356             Some((first, rem)) => {
357                 match field_type {
358                     TypeResolved::Message(message_name) => {
359                         let m = self.find_message_by_abs_name(&message_name)?;
360                         let mut unknown_fields = UnknownFields::new();
361                         self.custom_option_ext_step(
362                             scope,
363                             &m,
364                             &mut unknown_fields,
365                             first,
366                             rem,
367                             option_value,
368                         )?;
369                         options.add_length_delimited(
370                             field.proto().number() as u32,
371                             unknown_fields.write_to_bytes(),
372                         );
373                         Ok(())
374                     }
375                     TypeResolved::Group(..) => {
376                         // TODO: implement
377                         Ok(())
378                     }
379                     _ => Err(OptionResolverError::ExtensionIsNotMessage(format!(
380                         "scope: {}, option name: {}",
381                         scope, option_name
382                     ))
383                     .into()),
384                 }
385             }
386             None => {
387                 let value = match self.option_value_to_unknown_value(
388                     &field_type,
389                     option_value,
390                     &format!("{}", option_name),
391                 ) {
392                     Ok(value) => value,
393                     Err(e) => {
394                         let e = e.context(format!(
395                             "parsing custom option `{}` value `{}` at `{}`",
396                             option_name, option_value, scope
397                         ));
398                         return Err(e.into());
399                     }
400                 };
401 
402                 options.add_value(field.proto().number() as u32, value);
403                 Ok(())
404             }
405         }
406     }
407 
custom_option_ext<M>( &self, scope: &ProtobufAbsPathRef, options: &mut M, option_name: &ProtobufOptionNameExt, option_value: &ProtobufConstant, ) -> anyhow::Result<()> where M: MessageFull,408     fn custom_option_ext<M>(
409         &self,
410         scope: &ProtobufAbsPathRef,
411         options: &mut M,
412         option_name: &ProtobufOptionNameExt,
413         option_value: &ProtobufConstant,
414     ) -> anyhow::Result<()>
415     where
416         M: MessageFull,
417     {
418         self.custom_option_ext_step(
419             scope,
420             &M::descriptor(),
421             options.mut_unknown_fields(),
422             &option_name.0[0],
423             &option_name.0[1..],
424             option_value,
425         )
426     }
427 
fixed32( v: impl TryInto<u32, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>428     fn fixed32(
429         v: impl TryInto<u32, Error = impl std::error::Error + Send + Sync + 'static>,
430     ) -> anyhow::Result<UnknownValue> {
431         Ok(UnknownValue::Fixed32(v.try_into()?))
432     }
433 
sfixed32( v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>434     fn sfixed32(
435         v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>,
436     ) -> anyhow::Result<UnknownValue> {
437         Ok(UnknownValue::sfixed32(v.try_into()?))
438     }
439 
fixed64( v: impl TryInto<u64, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>440     fn fixed64(
441         v: impl TryInto<u64, Error = impl std::error::Error + Send + Sync + 'static>,
442     ) -> anyhow::Result<UnknownValue> {
443         Ok(UnknownValue::Fixed64(v.try_into()?))
444     }
445 
sfixed64( v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>446     fn sfixed64(
447         v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>,
448     ) -> anyhow::Result<UnknownValue> {
449         Ok(UnknownValue::sfixed64(v.try_into()?))
450     }
451 
int32( v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>452     fn int32(
453         v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>,
454     ) -> anyhow::Result<UnknownValue> {
455         Ok(UnknownValue::int32(v.try_into()?))
456     }
457 
int64( v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>458     fn int64(
459         v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>,
460     ) -> anyhow::Result<UnknownValue> {
461         Ok(UnknownValue::int64(v.try_into()?))
462     }
463 
uint32( v: impl TryInto<u32, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>464     fn uint32(
465         v: impl TryInto<u32, Error = impl std::error::Error + Send + Sync + 'static>,
466     ) -> anyhow::Result<UnknownValue> {
467         Ok(UnknownValue::Varint(v.try_into()? as u64))
468     }
469 
uint64( v: impl TryInto<u64, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>470     fn uint64(
471         v: impl TryInto<u64, Error = impl std::error::Error + Send + Sync + 'static>,
472     ) -> anyhow::Result<UnknownValue> {
473         Ok(UnknownValue::Varint(v.try_into()?))
474     }
475 
sint32( v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>476     fn sint32(
477         v: impl TryInto<i32, Error = impl std::error::Error + Send + Sync + 'static>,
478     ) -> anyhow::Result<UnknownValue> {
479         Ok(UnknownValue::sint32(v.try_into()?))
480     }
481 
sint64( v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>, ) -> anyhow::Result<UnknownValue>482     fn sint64(
483         v: impl TryInto<i64, Error = impl std::error::Error + Send + Sync + 'static>,
484     ) -> anyhow::Result<UnknownValue> {
485         Ok(UnknownValue::sint64(v.try_into()?))
486     }
487 
option_value_message_to_unknown_value( &self, field_type: &TypeResolved, value: &ProtobufConstantMessage, option_name_for_diag: &str, ) -> anyhow::Result<UnknownValue>488     fn option_value_message_to_unknown_value(
489         &self,
490         field_type: &TypeResolved,
491         value: &ProtobufConstantMessage,
492         option_name_for_diag: &str,
493     ) -> anyhow::Result<UnknownValue> {
494         match &field_type {
495             TypeResolved::Message(ma) => {
496                 let m = self
497                     .resolver
498                     .find_message_by_abs_name(ma)
499                     .map_err(OptionResolverError::OtherError)?
500                     .t;
501                 let mut unknown_fields = UnknownFields::new();
502                 for (n, v) in &value.fields {
503                     match n {
504                         ProtobufConstantMessageFieldName::Regular(n) => {
505                             let f = match m.field_by_name(n.as_str()) {
506                                 Some(f) => f,
507                                 None => {
508                                     return Err(
509                                         OptionResolverError::UnknownFieldName(n.clone()).into()
510                                     )
511                                 }
512                             };
513                             let u = self
514                                 .option_value_field_to_unknown_value(
515                                     ma,
516                                     v,
517                                     n,
518                                     &f.typ,
519                                     option_name_for_diag,
520                                 )
521                                 .map_err(OptionResolverError::OtherError)?;
522                             unknown_fields.add_value(f.number as u32, u);
523                         }
524                         ProtobufConstantMessageFieldName::Extension(..) => {
525                             // TODO: implement extension fields in constants
526                         }
527                         ProtobufConstantMessageFieldName::AnyTypeUrl(..) => {
528                             // TODO: implement any type url in constants
529                         }
530                     }
531                 }
532                 Ok(UnknownValue::LengthDelimited(
533                     unknown_fields.write_to_bytes(),
534                 ))
535             }
536             _ => Err(OptionResolverError::MessageFieldRequiresMessageConstant.into()),
537         }
538     }
539 
option_value_to_unknown_value( &self, field_type: &TypeResolved, value: &model::ProtobufConstant, option_name_for_diag: &str, ) -> anyhow::Result<UnknownValue>540     fn option_value_to_unknown_value(
541         &self,
542         field_type: &TypeResolved,
543         value: &model::ProtobufConstant,
544         option_name_for_diag: &str,
545     ) -> anyhow::Result<UnknownValue> {
546         match value {
547             &model::ProtobufConstant::Bool(b) => {
548                 if field_type != &TypeResolved::Bool {
549                     {}
550                 } else {
551                     return Ok(UnknownValue::Varint(if b { 1 } else { 0 }));
552                 }
553             }
554             &model::ProtobufConstant::U64(v) => match field_type {
555                 TypeResolved::Fixed64 => return Self::fixed64(v),
556                 TypeResolved::Sfixed64 => return Self::sfixed64(v),
557                 TypeResolved::Fixed32 => return Self::fixed32(v),
558                 TypeResolved::Sfixed32 => return Self::sfixed32(v),
559                 TypeResolved::Int32 => return Self::int32(v),
560                 TypeResolved::Int64 => return Self::int64(v),
561                 TypeResolved::Uint64 => return Self::uint64(v),
562                 TypeResolved::Uint32 => return Self::uint32(v),
563                 TypeResolved::Sint64 => return Self::sint64(v),
564                 TypeResolved::Sint32 => return Self::sint32(v),
565                 TypeResolved::Float => return Ok(UnknownValue::float(v as f32)),
566                 TypeResolved::Double => return Ok(UnknownValue::double(v as f64)),
567                 _ => {}
568             },
569             &model::ProtobufConstant::I64(v) => match field_type {
570                 TypeResolved::Fixed64 => return Self::fixed64(v),
571                 TypeResolved::Sfixed64 => return Self::sfixed64(v),
572                 TypeResolved::Fixed32 => return Self::fixed32(v),
573                 TypeResolved::Sfixed32 => return Self::sfixed32(v),
574                 TypeResolved::Int64 => return Self::int64(v),
575                 TypeResolved::Int32 => return Self::int32(v),
576                 TypeResolved::Uint64 => return Self::uint64(v),
577                 TypeResolved::Uint32 => return Self::uint32(v),
578                 TypeResolved::Sint64 => return Self::sint64(v),
579                 TypeResolved::Sint32 => return Self::sint32(v),
580                 TypeResolved::Float => return Ok(UnknownValue::float(v as f32)),
581                 TypeResolved::Double => return Ok(UnknownValue::double(v as f64)),
582                 _ => {}
583             },
584             &model::ProtobufConstant::F64(f) => match field_type {
585                 TypeResolved::Float => return Ok(UnknownValue::float(f as f32)),
586                 TypeResolved::Double => return Ok(UnknownValue::double(f)),
587                 TypeResolved::Fixed32 => return Ok(UnknownValue::Fixed32(f as u32)),
588                 TypeResolved::Fixed64 => return Ok(UnknownValue::Fixed64(f as u64)),
589                 TypeResolved::Sfixed32 => return Ok(UnknownValue::sfixed32(f as i32)),
590                 TypeResolved::Sfixed64 => return Ok(UnknownValue::sfixed64(f as i64)),
591                 TypeResolved::Int32 | TypeResolved::Int64 => {
592                     return Ok(UnknownValue::int64(f as i64))
593                 }
594                 TypeResolved::Uint32 | TypeResolved::Uint64 => {
595                     return Ok(UnknownValue::Varint(f as u64))
596                 }
597                 TypeResolved::Sint64 => return Ok(UnknownValue::sint64(f as i64)),
598                 TypeResolved::Sint32 => return Ok(UnknownValue::sint32(f as i32)),
599                 _ => {}
600             },
601             &model::ProtobufConstant::String(ref s) => match field_type {
602                 TypeResolved::String => {
603                     return Ok(UnknownValue::LengthDelimited(s.decode_utf8()?.into_bytes()))
604                 }
605                 TypeResolved::Bytes => return Ok(UnknownValue::LengthDelimited(s.decode_bytes()?)),
606                 _ => {}
607             },
608             model::ProtobufConstant::Ident(ident) => match &field_type {
609                 TypeResolved::Enum(e) => {
610                     let e = self
611                         .resolver
612                         .find_enum_by_abs_name(e)
613                         .map_err(OptionResolverError::OtherError)?;
614                     let n = match e
615                         .values
616                         .iter()
617                         .find(|v| v.name == format!("{}", ident))
618                         .map(|v| v.number)
619                     {
620                         Some(n) => n,
621                         None => {
622                             return Err(
623                                 OptionResolverError::UnknownEnumValue(ident.to_string()).into()
624                             )
625                         }
626                     };
627                     return Ok(UnknownValue::int32(n));
628                 }
629                 _ => {}
630             },
631             model::ProtobufConstant::Message(mo) => {
632                 return self.option_value_message_to_unknown_value(
633                     &field_type,
634                     mo,
635                     option_name_for_diag,
636                 );
637             }
638         };
639 
640         Err(match field_type {
641             _ => OptionResolverError::UnsupportedExtensionType(
642                 option_name_for_diag.to_owned(),
643                 format!("{:?}", field_type),
644                 value.clone(),
645             )
646             .into(),
647         })
648     }
649 
option_value_field_to_unknown_value( &self, scope: &ProtobufAbsPath, value: &model::ProtobufConstant, name: &str, field_type: &model::FieldType, option_name_for_diag: &str, ) -> anyhow::Result<UnknownValue>650     fn option_value_field_to_unknown_value(
651         &self,
652         scope: &ProtobufAbsPath,
653         value: &model::ProtobufConstant,
654         name: &str,
655         field_type: &model::FieldType,
656         option_name_for_diag: &str,
657     ) -> anyhow::Result<UnknownValue> {
658         let field_type = self.resolver.field_type(&scope, name, field_type)?;
659         Ok(self
660             .option_value_to_unknown_value(&field_type, value, option_name_for_diag)
661             .context("parsing custom option value")?)
662     }
663 
custom_option_builtin<M>( &self, _scope: &ProtobufAbsPathRef, options: &mut M, option: &ProtobufIdent, option_value: &ProtobufConstant, ) -> anyhow::Result<()> where M: MessageFull,664     fn custom_option_builtin<M>(
665         &self,
666         _scope: &ProtobufAbsPathRef,
667         options: &mut M,
668         option: &ProtobufIdent,
669         option_value: &ProtobufConstant,
670     ) -> anyhow::Result<()>
671     where
672         M: MessageFull,
673     {
674         if M::descriptor().full_name() == "google.protobuf.FieldOptions" {
675             if option.get() == "default" || option.get() == "json_name" {
676                 // some options are written to non-options message and handled outside
677                 return Ok(());
678             }
679         }
680         match M::descriptor().field_by_name(option.get()) {
681             Some(field) => {
682                 if field.is_repeated_or_map() {
683                     return Err(OptionResolverError::BuiltinOptionPointsToNonSingularField(
684                         M::descriptor().full_name().to_owned(),
685                         option.get().to_owned(),
686                     )
687                     .into());
688                 }
689 
690                 field.set_singular_field(
691                     options,
692                     option_value.as_type(field.singular_runtime_type())?,
693                 );
694                 return Ok(());
695             }
696             None => {
697                 return Err(OptionResolverError::BuiltinOptionNotFound(
698                     M::descriptor().full_name().to_owned(),
699                     option.get().to_owned(),
700                 )
701                 .into())
702             }
703         }
704     }
705 
custom_option<M>( &self, scope: &ProtobufAbsPathRef, options: &mut M, option: &model::ProtobufOption, ) -> anyhow::Result<()> where M: MessageFull,706     fn custom_option<M>(
707         &self,
708         scope: &ProtobufAbsPathRef,
709         options: &mut M,
710         option: &model::ProtobufOption,
711     ) -> anyhow::Result<()>
712     where
713         M: MessageFull,
714     {
715         match &option.name {
716             ProtobufOptionName::Builtin(simple) => {
717                 self.custom_option_builtin(scope, options, simple, &option.value)
718             }
719             ProtobufOptionName::Ext(e) => self.custom_option_ext(scope, options, e, &option.value),
720         }
721     }
722 
custom_options<M>( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<M>> where M: MessageFull,723     fn custom_options<M>(
724         &self,
725         scope: &ProtobufAbsPathRef,
726         input: &[model::ProtobufOption],
727     ) -> anyhow::Result<Option<M>>
728     where
729         M: MessageFull,
730     {
731         if input.is_empty() {
732             // Empty options do not have to represented to unset message field,
733             // but this is what Google's parser does.
734             return Ok(None);
735         }
736 
737         let mut options = M::new();
738 
739         for option in input {
740             self.custom_option(scope, &mut options, option)?;
741         }
742         Ok(Some(options))
743     }
744 
file_options( &self, scope: &ProtobufAbsPath, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::FileOptions>>745     fn file_options(
746         &self,
747         scope: &ProtobufAbsPath,
748         input: &[model::ProtobufOption],
749     ) -> anyhow::Result<Option<protobuf::descriptor::FileOptions>> {
750         self.custom_options(scope, input)
751     }
752 
enum_options( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::EnumOptions>>753     fn enum_options(
754         &self,
755         scope: &ProtobufAbsPathRef,
756         input: &[model::ProtobufOption],
757     ) -> anyhow::Result<Option<protobuf::descriptor::EnumOptions>> {
758         self.custom_options(scope, input)
759     }
760 
enum_value_options( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::EnumValueOptions>>761     fn enum_value_options(
762         &self,
763         scope: &ProtobufAbsPathRef,
764         input: &[model::ProtobufOption],
765     ) -> anyhow::Result<Option<protobuf::descriptor::EnumValueOptions>> {
766         self.custom_options(scope, input)
767     }
768 
field_options( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::FieldOptions>>769     fn field_options(
770         &self,
771         scope: &ProtobufAbsPathRef,
772         input: &[model::ProtobufOption],
773     ) -> anyhow::Result<Option<protobuf::descriptor::FieldOptions>> {
774         self.custom_options(scope, input)
775     }
776 
message_options( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::MessageOptions>>777     fn message_options(
778         &self,
779         scope: &ProtobufAbsPathRef,
780         input: &[model::ProtobufOption],
781     ) -> anyhow::Result<Option<protobuf::descriptor::MessageOptions>> {
782         self.custom_options(scope, input)
783     }
784 
oneof_options( &self, scope: &ProtobufAbsPathRef, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::OneofOptions>>785     fn oneof_options(
786         &self,
787         scope: &ProtobufAbsPathRef,
788         input: &[model::ProtobufOption],
789     ) -> anyhow::Result<Option<protobuf::descriptor::OneofOptions>> {
790         self.custom_options(scope, input)
791     }
792 
method( &self, method_proto: &mut MethodDescriptorProto, method_model: &model::Method, ) -> anyhow::Result<()>793     fn method(
794         &self,
795         method_proto: &mut MethodDescriptorProto,
796         method_model: &model::Method,
797     ) -> anyhow::Result<()> {
798         method_proto.options = self.service_method_options(&method_model.options)?.into();
799         Ok(())
800     }
801 
service_options( &self, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::ServiceOptions>>802     fn service_options(
803         &self,
804         input: &[model::ProtobufOption],
805     ) -> anyhow::Result<Option<protobuf::descriptor::ServiceOptions>> {
806         self.custom_options(&self.resolver.current_file.package, input)
807     }
808 
service_method_options( &self, input: &[model::ProtobufOption], ) -> anyhow::Result<Option<protobuf::descriptor::MethodOptions>>809     fn service_method_options(
810         &self,
811         input: &[model::ProtobufOption],
812     ) -> anyhow::Result<Option<protobuf::descriptor::MethodOptions>> {
813         self.custom_options(&self.resolver.current_file.package, input)
814     }
815 
service( &self, service_proto: &mut ServiceDescriptorProto, service_model: &WithLoc<model::Service>, ) -> anyhow::Result<()>816     fn service(
817         &self,
818         service_proto: &mut ServiceDescriptorProto,
819         service_model: &WithLoc<model::Service>,
820     ) -> anyhow::Result<()> {
821         service_proto.options = self.service_options(&service_model.options)?.into();
822 
823         for service_method_model in &service_model.methods {
824             let mut method_proto = service_proto
825                 .method
826                 .iter_mut()
827                 .find(|method| method.name() == service_method_model.name)
828                 .unwrap();
829             self.method(&mut method_proto, service_method_model)?;
830         }
831 
832         Ok(())
833     }
834 
enum_value( &self, scope: &ProtobufAbsPathRef, enum_value_proto: &mut EnumValueDescriptorProto, enum_value_model: &model::EnumValue, ) -> anyhow::Result<()>835     fn enum_value(
836         &self,
837         scope: &ProtobufAbsPathRef,
838         enum_value_proto: &mut EnumValueDescriptorProto,
839         enum_value_model: &model::EnumValue,
840     ) -> anyhow::Result<()> {
841         enum_value_proto.options = self
842             .enum_value_options(scope, &enum_value_model.options)?
843             .into();
844         Ok(())
845     }
846 
enumeration( &self, scope: &ProtobufAbsPathRef, enum_proto: &mut EnumDescriptorProto, enum_model: &WithLoc<model::Enumeration>, ) -> anyhow::Result<()>847     fn enumeration(
848         &self,
849         scope: &ProtobufAbsPathRef,
850         enum_proto: &mut EnumDescriptorProto,
851         enum_model: &WithLoc<model::Enumeration>,
852     ) -> anyhow::Result<()> {
853         enum_proto.options = self.enum_options(scope, &enum_model.options)?.into();
854 
855         for enum_value_model in &enum_model.values {
856             let mut enum_value_proto = enum_proto
857                 .value
858                 .iter_mut()
859                 .find(|v| v.name() == enum_value_model.name)
860                 .unwrap();
861             self.enum_value(scope, &mut enum_value_proto, enum_value_model)?;
862         }
863 
864         Ok(())
865     }
866 
oneof( &self, scope: &ProtobufAbsPathRef, oneof_proto: &mut OneofDescriptorProto, oneof_model: &model::OneOf, ) -> anyhow::Result<()>867     fn oneof(
868         &self,
869         scope: &ProtobufAbsPathRef,
870         oneof_proto: &mut OneofDescriptorProto,
871         oneof_model: &model::OneOf,
872     ) -> anyhow::Result<()> {
873         oneof_proto.options = self.oneof_options(scope, &oneof_model.options)?.into();
874         Ok(())
875     }
876 
field( &self, scope: &ProtobufAbsPathRef, field_proto: &mut FieldDescriptorProto, field_model: &model::Field, ) -> anyhow::Result<()>877     fn field(
878         &self,
879         scope: &ProtobufAbsPathRef,
880         field_proto: &mut FieldDescriptorProto,
881         field_model: &model::Field,
882     ) -> anyhow::Result<()> {
883         field_proto.options = self.field_options(scope, &field_model.options)?.into();
884         Ok(())
885     }
886 
message( &self, scope: &ProtobufAbsPathRef, message_proto: &mut DescriptorProto, message_model: &WithLoc<model::Message>, ) -> anyhow::Result<()>887     fn message(
888         &self,
889         scope: &ProtobufAbsPathRef,
890         message_proto: &mut DescriptorProto,
891         message_model: &WithLoc<model::Message>,
892     ) -> anyhow::Result<()> {
893         message_proto.options = self.message_options(scope, &message_model.options)?.into();
894 
895         let mut nested_scope = scope.to_owned();
896         nested_scope.push_simple(ProtobufIdentRef::new(&message_proto.name()));
897 
898         for field_model in &message_model.regular_fields_including_in_oneofs() {
899             let mut field_proto = message_proto
900                 .field
901                 .iter_mut()
902                 .find(|field| field.name() == field_model.name)
903                 .unwrap();
904             self.field(&nested_scope, &mut field_proto, field_model)?;
905         }
906         for field_model in &message_model.extensions {
907             let field_proto = message_proto
908                 .extension
909                 .iter_mut()
910                 .find(|field| field.name() == field_model.field.name)
911                 .unwrap();
912             self.field(&nested_scope, field_proto, &field_model.field)?;
913         }
914 
915         for nested_message_model in &message_model.messages {
916             let nested_message_proto = message_proto
917                 .nested_type
918                 .iter_mut()
919                 .find(|nested_message_proto| {
920                     nested_message_proto.name() == nested_message_model.name
921                 })
922                 .unwrap();
923             self.message(&nested_scope, nested_message_proto, nested_message_model)?;
924         }
925 
926         for nested_enum_model in &message_model.enums {
927             let nested_enum_proto = message_proto
928                 .enum_type
929                 .iter_mut()
930                 .find(|nested_enum_proto| nested_enum_proto.name() == nested_enum_model.name)
931                 .unwrap();
932             self.enumeration(&nested_scope, nested_enum_proto, nested_enum_model)?;
933         }
934 
935         for oneof_model in &message_model.oneofs() {
936             let oneof_proto = message_proto
937                 .oneof_decl
938                 .iter_mut()
939                 .find(|oneof_proto| oneof_proto.name() == oneof_model.name)
940                 .unwrap();
941             self.oneof(&nested_scope, oneof_proto, oneof_model)?;
942         }
943 
944         Ok(())
945     }
946 
file(&self, output: &mut FileDescriptorProto) -> anyhow::Result<()>947     pub(crate) fn file(&self, output: &mut FileDescriptorProto) -> anyhow::Result<()> {
948         // TODO: use it to resolve messages.
949         let _ = &self.descriptor_without_options;
950 
951         for message_model in &self.resolver.current_file.messages {
952             let message_proto = output
953                 .message_type
954                 .iter_mut()
955                 .find(|m| m.name() == message_model.name)
956                 .unwrap();
957             self.message(
958                 &self.resolver.current_file.package,
959                 message_proto,
960                 message_model,
961             )?;
962         }
963 
964         for enum_model in &self.resolver.current_file.enums {
965             let enum_proto = output
966                 .enum_type
967                 .iter_mut()
968                 .find(|e| e.name() == enum_model.name)
969                 .unwrap();
970             self.enumeration(&self.resolver.current_file.package, enum_proto, enum_model)?;
971         }
972 
973         for service_proto in &mut output.service {
974             let service_model = self
975                 .resolver
976                 .current_file
977                 .services
978                 .iter()
979                 .find(|s| s.name == service_proto.name())
980                 .unwrap();
981             self.service(service_proto, service_model)?;
982         }
983 
984         for extension_model in &self.resolver.current_file.extensions {
985             let extension_proto = output
986                 .extension
987                 .iter_mut()
988                 .find(|e| e.name() == extension_model.field.name)
989                 .unwrap();
990             self.field(
991                 &self.resolver.current_file.package,
992                 extension_proto,
993                 &extension_model.field,
994             )?;
995         }
996 
997         output.options = self
998             .file_options(
999                 &self.resolver.current_file.package,
1000                 &self.resolver.current_file.options,
1001             )?
1002             .into();
1003 
1004         Ok(())
1005     }
1006 }
1007