protobuf_parse/pure/convert/
option_resolver.rs

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