Skip to main content

serde_protobuf/
descriptor.rs

1//! Dynamic descriptors for protocol buffer schemata.
2//!
3//! The descriptors are optimized for read performance, i.e. to be used by a parser to parse actual
4//! protocol buffer data.
5//!
6//! They can be constructed either from pre-compiled protocol buffer-serialized descriptors as
7//! defined in [`descriptor.proto`][1], or manually by incrementally building a custom protocol
8//! buffer schema.
9//!
10//! ## Pre-compiled schemas
11//!
12//! Given a protocol buffer schema `schema.proto`, it can be compiled into a binary file descriptor
13//! set using the `protoc` tool:
14//!
15//! ```text
16//! protoc schema.proto -o testdata/descriptors.pb
17//! ```
18//!
19//! The binary file descriptor set can then be parsed into a `Descriptors` instance:
20//!
21//! ```
22//! extern crate serde_protobuf;
23//! extern crate protobuf;
24//!
25//! use std::fs;
26//! use serde_protobuf::descriptor::Descriptors;
27//!
28//! # use std::io;
29//! # #[derive(Debug)] struct Error;
30//! # impl From<protobuf::ProtobufError> for Error {
31//! #   fn from(a: protobuf::ProtobufError) -> Error {
32//! #     Error
33//! #   }
34//! # }
35//! # impl From<io::Error> for Error {
36//! #   fn from(a: io::Error) -> Error {
37//! #     Error
38//! #   }
39//! # }
40//! # fn foo() -> Result<(), Error> {
41//! let mut file = fs::File::open("testdata/descriptors.pb")?;
42//! let proto = protobuf::parse_from_reader(&mut file)?;
43//! let descriptors = Descriptors::from_proto(&proto);
44//! # Ok(())
45//! # }
46//! # fn main() {
47//! #   foo().unwrap();
48//! # }
49//! ```
50//!
51//! ## Manually built schemas
52//!
53//! A descriptor can be built at run-time by incrementally adding new message types and fields:
54//!
55//! ```
56//! use serde_protobuf::descriptor::*;
57//!
58//! // Create a new message type
59//! let mut m = MessageDescriptor::new(".mypackage.Person");
60//! m.add_field(FieldDescriptor::new("name", 1, FieldLabel::Optional,
61//!                                  InternalFieldType::String, None));
62//! m.add_field(FieldDescriptor::new("age", 2, FieldLabel::Optional,
63//!                                  InternalFieldType::Int32, None));
64//!
65//! // Create a new enum type
66//! let mut e = EnumDescriptor::new(".mypackage.Color");
67//! e.add_value(EnumValueDescriptor::new("BLUE", 1));
68//! e.add_value(EnumValueDescriptor::new("RED", 2));
69//!
70//! // Add the generated types to a descriptor registry
71//! let mut descriptors = Descriptors::new();
72//! descriptors.add_message(m);
73//! descriptors.add_enum(e);
74//! ```
75//!
76//! ## Exploring descriptors
77//!
78//! The descriptors contain various indices that can be used to quickly look up information:
79//!
80//! ```
81//! # extern crate serde_protobuf;
82//! # extern crate protobuf;
83//! # use std::fs;
84//! # use serde_protobuf::descriptor::Descriptors;
85//! # fn main() {
86//! # let mut file = fs::File::open("testdata/descriptors.pb").unwrap();
87//! # let proto = protobuf::parse_from_reader(&mut file).unwrap();
88//! // Given a set of descriptors using one of the above methods:
89//! let descriptors = Descriptors::from_proto(&proto);
90//! assert_eq!(7, descriptors.message_by_name(".protobuf_unittest.TestAllTypes").unwrap()
91//!                          .field_by_name("optional_fixed32").unwrap()
92//!                          .number());
93//! # }
94//! ```
95//!
96//! ## Optimizing reference look-ups
97//!
98//! Certain descriptor look-ups require following references that can be quite expensive to look up.
99//! Instead, a one-time cost can be payed to resolve these references and make all following
100//! look-ups cheaper.  This should be done after all needed descriptors have been loaded:
101//!
102//! ```
103//! # extern crate serde_protobuf;
104//! # extern crate protobuf;
105//! # use std::fs;
106//! # use serde_protobuf::descriptor::*;
107//! # fn main() {
108//! # let mut file = fs::File::open("testdata/descriptors.pb").unwrap();
109//! # let proto = protobuf::parse_from_reader(&mut file).unwrap();
110//! // Load some descriptors as usual:
111//! let mut descriptors = Descriptors::from_proto(&proto);
112//!
113//! // Resolve references internally to speed up lookups:
114//! descriptors.resolve_refs();
115//!
116//! // This should now be faster
117//! match descriptors.message_by_name(".protobuf_unittest.TestAllTypes").unwrap()
118//!                  .field_by_name("optional_nested_message").unwrap()
119//!                  .field_type(&descriptors) {
120//!   FieldType::Message(m) =>
121//!     assert_eq!(1, m.field_by_name("bb").unwrap()
122//!                    .number()),
123//!   _ => unreachable!(),
124//! }
125//! # }
126//! ```
127//!
128//! [1]: https://github.com/google/protobuf/blob/master/src/google/protobuf/descriptor.proto
129use std::f32;
130use std::f64;
131
132use linked_hash_map;
133use protobuf::descriptor;
134
135use crate::error;
136use crate::value;
137
138/// An ID used for internal tracking of resolved message descriptors.
139///
140/// It is not possible to construct a value of this type from outside this module.
141#[derive(Clone, Copy, Debug, Eq, PartialEq)]
142pub struct MessageId(usize);
143
144/// An ID used for internal tracking of resolved enum descriptors.
145///
146/// It is not possible to construct a value of this type from outside this module.
147#[derive(Clone, Copy, Debug, Eq, PartialEq)]
148pub struct EnumId(usize);
149
150/// An ID used for internal tracking of resolved enum values.
151#[derive(Clone, Copy, Debug, Eq, PartialEq)]
152struct EnumValueId(usize);
153
154/// An ID used for internal tracking of resolved fields.
155#[derive(Clone, Copy, Debug, Eq, PartialEq)]
156struct FieldId(usize);
157
158/// A registry for any number of protocol buffer descriptors.
159#[derive(Debug, Default)]
160pub struct Descriptors {
161    // All found descriptors
162    messages: Vec<MessageDescriptor>,
163    enums: Vec<EnumDescriptor>,
164
165    // Indices
166    messages_by_name: linked_hash_map::LinkedHashMap<String, MessageId>,
167    enums_by_name: linked_hash_map::LinkedHashMap<String, EnumId>,
168}
169
170/// A descriptor for a single protocol buffer message type.
171// TODO: Support oneof?
172#[derive(Debug)]
173pub struct MessageDescriptor {
174    name: String,
175
176    // All found descriptors
177    fields: Vec<FieldDescriptor>,
178
179    // Indices
180    fields_by_name: linked_hash_map::LinkedHashMap<String, FieldId>,
181    fields_by_number: linked_hash_map::LinkedHashMap<i32, FieldId>,
182}
183
184/// A descriptor for a single protocol buffer enum type.
185#[derive(Debug)]
186pub struct EnumDescriptor {
187    name: String,
188
189    // All found descriptors
190    values: Vec<EnumValueDescriptor>,
191
192    // Indices
193    values_by_name: linked_hash_map::LinkedHashMap<String, EnumValueId>,
194    values_by_number: linked_hash_map::LinkedHashMap<i32, EnumValueId>,
195}
196
197/// A descriptor for a single protocol buffer enum value.
198#[derive(Debug)]
199pub struct EnumValueDescriptor {
200    name: String,
201    number: i32,
202}
203
204/// A label that a field can be given to indicate its cardinality.
205#[derive(Clone, Copy, Debug, Eq, PartialEq)]
206pub enum FieldLabel {
207    /// There can be zero or one value.
208    Optional,
209    /// There must be exactly one value.
210    Required,
211    /// There can be any number of values.
212    Repeated,
213}
214
215/// The externally visible type of a field.
216///
217/// This type representation borrows references to any referenced descriptors.
218#[derive(Debug)]
219pub enum FieldType<'a> {
220    /// A message that is yet to be resolved.
221    UnresolvedMessage(&'a str),
222    /// An enum that is yet to be resolved.
223    UnresolvedEnum(&'a str),
224    /// The `double` type.
225    Double,
226    /// The `float` type.
227    Float,
228    /// The `int64` type.
229    Int64,
230    /// The `uint64` type.
231    UInt64,
232    /// The `int32` type.
233    Int32,
234    /// The `fixed64` type.
235    Fixed64,
236    /// The `fixed32` type.
237    Fixed32,
238    /// The `bool` type.
239    Bool,
240    /// The `string` type.
241    String,
242    /// The `group` type.
243    Group,
244    /// A resolved message type.
245    Message(&'a MessageDescriptor),
246    /// The `bytes` type.
247    Bytes,
248    /// The `uint32` type.
249    UInt32,
250    /// A resolved enum type.
251    Enum(&'a EnumDescriptor),
252    /// The `sfixed32` type.
253    SFixed32,
254    /// The `sfixed64` type.
255    SFixed64,
256    /// The `sint32` type.
257    SInt32,
258    /// The `sint64` type.
259    SInt64,
260}
261
262/// The internally tracked type of a field.
263///
264/// The type owns all of its data, and can refer to an internally tracked ID for resolved type
265/// references.  It's by design not possible to construct those IDs from outside this module.
266#[derive(Debug, Eq, PartialEq)]
267pub enum InternalFieldType {
268    /// A message that is yet to be resolved.
269    UnresolvedMessage(String),
270    /// An enum that is yet to be resolved.
271    UnresolvedEnum(String),
272    /// The `double` type.
273    Double,
274    /// The `float` type.
275    Float,
276    /// The `int64` type.
277    Int64,
278    /// The `uint64` type.
279    UInt64,
280    /// The `int32` type.
281    Int32,
282    /// The `fixed64` type.
283    Fixed64,
284    /// The `fixed32` type.
285    Fixed32,
286    /// The `bool` type.
287    Bool,
288    /// The `string` type.
289    String,
290    /// The `group` type.
291    Group,
292    /// A resolved message type.
293    Message(MessageId),
294    /// The `bytes` type.
295    Bytes,
296    /// The `uint32` type.
297    UInt32,
298    /// A resolved enum type.
299    Enum(EnumId),
300    /// The `sfixed32` type.
301    SFixed32,
302    /// The `sfixed64` type.
303    SFixed64,
304    /// The `sint32` type.
305    SInt32,
306    /// The `sint64` type.
307    SInt64,
308}
309
310/// A descriptor for a single protocol buffer message field.
311#[derive(Debug)]
312pub struct FieldDescriptor {
313    name: String,
314    number: i32,
315    field_label: FieldLabel,
316    field_type: InternalFieldType,
317    default_value: Option<value::Value>,
318}
319
320impl Descriptors {
321    /// Creates a new empty descriptor set.
322    pub fn new() -> Descriptors {
323        Descriptors {
324            messages: Vec::new(),
325            enums: Vec::new(),
326
327            messages_by_name: linked_hash_map::LinkedHashMap::new(),
328            enums_by_name: linked_hash_map::LinkedHashMap::new(),
329        }
330    }
331
332    /// Builds a descriptor set from the specified protocol buffer file descriptor set.
333    pub fn from_proto(file_set_proto: &descriptor::FileDescriptorSet) -> Descriptors {
334        let mut descriptors = Descriptors::new();
335        descriptors.add_file_set_proto(file_set_proto);
336        descriptors
337    }
338
339    /// Looks up a message by its fully qualified name (i.e. `.foo.package.Message`).
340    #[inline]
341    pub fn message_by_name(&self, name: &str) -> Option<&MessageDescriptor> {
342        self.messages_by_name.get(name).map(|m| &self.messages[m.0])
343    }
344
345    /// Looks up an enum by its fully qualified name (i.e. `.foo.package.Enum`).
346    #[inline]
347    pub fn enum_by_name(&self, name: &str) -> Option<&EnumDescriptor> {
348        self.enums_by_name.get(name).map(|e| &self.enums[e.0])
349    }
350
351    /// Adds all types defined in the specified protocol buffer file descriptor set to this
352    /// registry.
353    pub fn add_file_set_proto(&mut self, file_set_proto: &descriptor::FileDescriptorSet) {
354        for file_proto in file_set_proto.get_file().iter() {
355            self.add_file_proto(file_proto);
356        }
357    }
358
359    /// Adds all types defined in the specified protocol buffer file descriptor to this registry.
360    pub fn add_file_proto(&mut self, file_proto: &descriptor::FileDescriptorProto) {
361        let path = if file_proto.has_package() {
362            format!(".{}", file_proto.get_package())
363        } else {
364            "".to_owned()
365        };
366
367        for message_proto in file_proto.get_message_type().iter() {
368            self.add_message_proto(&path, message_proto);
369        }
370
371        for enum_proto in file_proto.get_enum_type().iter() {
372            self.add_enum(EnumDescriptor::from_proto(&path, enum_proto));
373        }
374    }
375
376    /// Adds a message and all nested types within that message from the specified protocol buffer
377    /// descriptor.
378    pub fn add_message_proto(&mut self, path: &str, message_proto: &descriptor::DescriptorProto) {
379        let message_descriptor = MessageDescriptor::from_proto(path, message_proto);
380
381        for nested_message_proto in message_proto.get_nested_type().iter() {
382            self.add_message_proto(message_descriptor.name(), nested_message_proto);
383        }
384
385        for nested_enum_proto in message_proto.get_enum_type().iter() {
386            self.add_enum(EnumDescriptor::from_proto(
387                message_descriptor.name(),
388                nested_enum_proto,
389            ));
390        }
391
392        self.add_message(message_descriptor);
393    }
394
395    /// Adds a single custom built message descriptor.
396    pub fn add_message(&mut self, descriptor: MessageDescriptor) {
397        let name = descriptor.name.clone();
398        let message_id = MessageId(store(&mut self.messages, descriptor));
399        self.messages_by_name.insert(name, message_id);
400    }
401
402    /// Adds a single custom built enum descriptor.
403    pub fn add_enum(&mut self, descriptor: EnumDescriptor) {
404        let name = descriptor.name.clone();
405        let enum_id = EnumId(store(&mut self.enums, descriptor));
406        self.enums_by_name.insert(name, enum_id);
407    }
408
409    /// Resolves all internal descriptor type references, making them cheaper to follow.
410    pub fn resolve_refs(&mut self) {
411        for m in &mut self.messages {
412            for f in &mut m.fields {
413                let field_type = &mut f.field_type;
414                let new = match *field_type {
415                    InternalFieldType::UnresolvedMessage(ref name) => {
416                        if let Some(res) = self.messages_by_name.get(name) {
417                            Some(InternalFieldType::Message(*res))
418                        } else {
419                            warn!("Inconsistent schema; unknown message type {}", name);
420                            None
421                        }
422                    }
423                    InternalFieldType::UnresolvedEnum(ref name) => {
424                        if let Some(res) = self.enums_by_name.get(name) {
425                            Some(InternalFieldType::Enum(*res))
426                        } else {
427                            warn!("Inconsistent schema; unknown enum type {}", name);
428                            None
429                        }
430                    }
431                    _ => None,
432                };
433
434                if let Some(t) = new {
435                    *field_type = t;
436                }
437            }
438        }
439    }
440}
441
442impl MessageDescriptor {
443    /// Creates a new message descriptor with the specified message name.
444    pub fn new<S>(name: S) -> MessageDescriptor
445    where
446        S: Into<String>,
447    {
448        MessageDescriptor {
449            name: name.into(),
450            fields: Vec::new(),
451            fields_by_name: linked_hash_map::LinkedHashMap::new(),
452            fields_by_number: linked_hash_map::LinkedHashMap::new(),
453        }
454    }
455
456    /// Reads a message descriptor from a parsed Protobuf descriptor.
457    pub fn from_proto(path: &str, proto: &descriptor::DescriptorProto) -> MessageDescriptor {
458        let name = format!("{}.{}", path, proto.get_name());
459        let mut message_descriptor = MessageDescriptor::new(name);
460
461        for field_proto in proto.get_field().iter() {
462            message_descriptor.add_field(FieldDescriptor::from_proto(field_proto));
463        }
464
465        message_descriptor
466    }
467
468    /// All of the fields in the descriptor.
469    pub fn fields(&self) -> &[FieldDescriptor] {
470        &self.fields
471    }
472
473    /// The name of the message.
474    #[inline]
475    pub fn name(&self) -> &str {
476        &self.name
477    }
478
479    /// Finds a field by field name.
480    #[inline]
481    pub fn field_by_name(&self, name: &str) -> Option<&FieldDescriptor> {
482        self.fields_by_name.get(name).map(|f| &self.fields[f.0])
483    }
484
485    /// Finds a field by field number.
486    #[inline]
487    pub fn field_by_number(&self, number: i32) -> Option<&FieldDescriptor> {
488        self.fields_by_number
489            .get(&number)
490            .map(|f| &self.fields[f.0])
491    }
492
493    /// Adds a new field to the descriptor.
494    pub fn add_field(&mut self, descriptor: FieldDescriptor) {
495        let name = descriptor.name.clone();
496        let number = descriptor.number;
497
498        let field_id = FieldId(store(&mut self.fields, descriptor));
499
500        self.fields_by_name.insert(name, field_id);
501        self.fields_by_number.insert(number, field_id);
502    }
503}
504
505impl EnumDescriptor {
506    /// Creates a new enum descriptor with the specified enum name.
507    pub fn new<S>(name: S) -> EnumDescriptor
508    where
509        S: Into<String>,
510    {
511        EnumDescriptor {
512            name: name.into(),
513            values: Vec::new(),
514            values_by_name: linked_hash_map::LinkedHashMap::new(),
515            values_by_number: linked_hash_map::LinkedHashMap::new(),
516        }
517    }
518
519    /// Reads an enum descriptor from a parsed Protobuf descriptor.
520    pub fn from_proto(path: &str, proto: &descriptor::EnumDescriptorProto) -> EnumDescriptor {
521        let enum_name = format!("{}.{}", path, proto.get_name());
522
523        let mut enum_descriptor = EnumDescriptor::new(enum_name);
524
525        for value_proto in proto.get_value().iter() {
526            enum_descriptor.add_value(EnumValueDescriptor::from_proto(value_proto));
527        }
528
529        enum_descriptor
530    }
531
532    /// The name of the enum.
533    #[inline]
534    pub fn name(&self) -> &str {
535        &self.name
536    }
537
538    /// Adds an enum value to the enum.
539    pub fn add_value(&mut self, descriptor: EnumValueDescriptor) {
540        let name = descriptor.name.clone();
541        let number = descriptor.number;
542
543        let value_id = EnumValueId(store(&mut self.values, descriptor));
544
545        self.values_by_name.insert(name, value_id);
546        self.values_by_number.insert(number, value_id);
547    }
548
549    /// Finds a value by name.
550    #[inline]
551    pub fn value_by_name(&self, name: &str) -> Option<&EnumValueDescriptor> {
552        self.values_by_name.get(name).map(|v| &self.values[v.0])
553    }
554
555    /// Finds a value by number.
556    #[inline]
557    pub fn value_by_number(&self, number: i32) -> Option<&EnumValueDescriptor> {
558        self.values_by_number
559            .get(&number)
560            .map(|v| &self.values[v.0])
561    }
562}
563
564impl EnumValueDescriptor {
565    /// Creates a new enum value descriptor with the given number.
566    pub fn new<S>(name: S, number: i32) -> EnumValueDescriptor
567    where
568        S: Into<String>,
569    {
570        let name = name.into();
571        EnumValueDescriptor { name, number }
572    }
573
574    /// Reads an enum value descriptor from a parsed Protobuf descriptor.
575    pub fn from_proto(proto: &descriptor::EnumValueDescriptorProto) -> EnumValueDescriptor {
576        EnumValueDescriptor::new(proto.get_name().to_owned(), proto.get_number())
577    }
578
579    /// The name of the enum value.
580    #[inline]
581    pub fn name(&self) -> &str {
582        &self.name
583    }
584
585    /// The number of the enum value.
586    #[inline]
587    pub fn number(&self) -> i32 {
588        self.number
589    }
590}
591
592impl FieldLabel {
593    /// Converts a proto field label into a native field label.
594    pub fn from_proto(proto: descriptor::FieldDescriptorProto_Label) -> FieldLabel {
595        use protobuf::descriptor::FieldDescriptorProto_Label::*;
596
597        match proto {
598            LABEL_OPTIONAL => FieldLabel::Optional,
599            LABEL_REQUIRED => FieldLabel::Required,
600            LABEL_REPEATED => FieldLabel::Repeated,
601        }
602    }
603
604    /// Whether the label is repeated.
605    #[inline]
606    pub fn is_repeated(self) -> bool {
607        self == FieldLabel::Repeated
608    }
609}
610
611impl InternalFieldType {
612    /// Converts a proto field type into a native field type.
613    pub fn from_proto(
614        proto: descriptor::FieldDescriptorProto_Type,
615        type_name: &str,
616    ) -> InternalFieldType {
617        use protobuf::descriptor::FieldDescriptorProto_Type::*;
618        match proto {
619            TYPE_DOUBLE => InternalFieldType::Double,
620            TYPE_FLOAT => InternalFieldType::Float,
621            TYPE_INT64 => InternalFieldType::Int64,
622            TYPE_UINT64 => InternalFieldType::UInt64,
623            TYPE_INT32 => InternalFieldType::Int32,
624            TYPE_FIXED64 => InternalFieldType::Fixed64,
625            TYPE_FIXED32 => InternalFieldType::Fixed32,
626            TYPE_BOOL => InternalFieldType::Bool,
627            TYPE_STRING => InternalFieldType::String,
628            TYPE_GROUP => InternalFieldType::Group,
629            TYPE_MESSAGE => InternalFieldType::UnresolvedMessage(type_name.to_owned()),
630            TYPE_BYTES => InternalFieldType::Bytes,
631            TYPE_UINT32 => InternalFieldType::UInt32,
632            TYPE_ENUM => InternalFieldType::UnresolvedEnum(type_name.to_owned()),
633            TYPE_SFIXED32 => InternalFieldType::SFixed32,
634            TYPE_SFIXED64 => InternalFieldType::SFixed64,
635            TYPE_SINT32 => InternalFieldType::SInt32,
636            TYPE_SINT64 => InternalFieldType::SInt64,
637        }
638    }
639
640    #[inline]
641    fn resolve<'a>(&'a self, descriptors: &'a Descriptors) -> FieldType<'a> {
642        match *self {
643            InternalFieldType::UnresolvedMessage(ref n) => {
644                if let Some(m) = descriptors.message_by_name(n) {
645                    FieldType::Message(m)
646                } else {
647                    FieldType::UnresolvedMessage(n)
648                }
649            }
650            InternalFieldType::UnresolvedEnum(ref n) => {
651                if let Some(e) = descriptors.enum_by_name(n) {
652                    FieldType::Enum(e)
653                } else {
654                    FieldType::UnresolvedEnum(n)
655                }
656            }
657            InternalFieldType::Double => FieldType::Double,
658            InternalFieldType::Float => FieldType::Float,
659            InternalFieldType::Int64 => FieldType::Int64,
660            InternalFieldType::UInt64 => FieldType::UInt64,
661            InternalFieldType::Int32 => FieldType::Int32,
662            InternalFieldType::Fixed64 => FieldType::Fixed64,
663            InternalFieldType::Fixed32 => FieldType::Fixed32,
664            InternalFieldType::Bool => FieldType::Bool,
665            InternalFieldType::String => FieldType::String,
666            InternalFieldType::Group => FieldType::Group,
667            InternalFieldType::Message(m) => FieldType::Message(&descriptors.messages[m.0]),
668            InternalFieldType::Bytes => FieldType::Bytes,
669            InternalFieldType::UInt32 => FieldType::UInt32,
670            InternalFieldType::Enum(e) => FieldType::Enum(&descriptors.enums[e.0]),
671            InternalFieldType::SFixed32 => FieldType::SFixed32,
672            InternalFieldType::SFixed64 => FieldType::SFixed64,
673            InternalFieldType::SInt32 => FieldType::SInt32,
674            InternalFieldType::SInt64 => FieldType::SInt64,
675        }
676    }
677}
678
679impl FieldDescriptor {
680    /// Creates a new field descriptor.
681    pub fn new<S>(
682        name: S,
683        number: i32,
684        field_label: FieldLabel,
685        field_type: InternalFieldType,
686        default_value: Option<value::Value>,
687    ) -> FieldDescriptor
688    where
689        S: Into<String>,
690    {
691        let name = name.into();
692        FieldDescriptor {
693            name,
694            number,
695            field_label,
696            field_type,
697            default_value,
698        }
699    }
700
701    /// Reads a field descriptor from a parsed Protobuf descriptor.
702    pub fn from_proto(proto: &descriptor::FieldDescriptorProto) -> FieldDescriptor {
703        let name = proto.get_name().to_owned();
704        let number = proto.get_number();
705        let field_label = FieldLabel::from_proto(proto.get_label());
706        let field_type =
707            InternalFieldType::from_proto(proto.get_field_type(), proto.get_type_name());
708        let default_value = if proto.has_default_value() {
709            // TODO: report error?
710            parse_default_value(proto.get_default_value(), &field_type).ok()
711        } else {
712            None
713        };
714
715        FieldDescriptor::new(name, number, field_label, field_type, default_value)
716    }
717
718    /// The name of the field.
719    #[inline]
720    pub fn name(&self) -> &str {
721        &self.name
722    }
723
724    /// The number of the field.
725    #[inline]
726    pub fn number(&self) -> i32 {
727        self.number
728    }
729
730    /// The label of the field.
731    #[inline]
732    pub fn field_label(&self) -> FieldLabel {
733        self.field_label
734    }
735
736    /// Whether the field is repeated.
737    #[inline]
738    pub fn is_repeated(&self) -> bool {
739        self.field_label == FieldLabel::Repeated
740    }
741
742    /// The type of the field.
743    #[inline]
744    pub fn field_type<'a>(&'a self, descriptors: &'a Descriptors) -> FieldType<'a> {
745        self.field_type.resolve(descriptors)
746    }
747
748    /// The default value of the field.
749    #[inline]
750    pub fn default_value(&self) -> Option<&value::Value> {
751        self.default_value.as_ref()
752    }
753}
754
755fn store<A>(vec: &mut Vec<A>, elem: A) -> usize {
756    let idx = vec.len();
757    vec.push(elem);
758    idx
759}
760
761fn parse_default_value(value: &str, field_type: &InternalFieldType) -> error::Result<value::Value> {
762    use std::str::FromStr;
763
764    fn bad(v: &str) -> error::Error {
765        error::Error::BadDefaultValue {
766            default_value: v.to_owned(),
767        }
768    }
769
770    match *field_type {
771        InternalFieldType::UnresolvedMessage(_)
772        | InternalFieldType::UnresolvedEnum(_)
773        | InternalFieldType::Message(_)
774        | InternalFieldType::Enum(_) => Err(bad(value)),
775        InternalFieldType::Bool => bool::from_str(value)
776            .map(value::Value::Bool)
777            .map_err(|_| bad(value)),
778        InternalFieldType::Double => match value {
779            "inf" => Ok(value::Value::F64(f64::INFINITY)),
780            "-inf" => Ok(value::Value::F64(f64::NEG_INFINITY)),
781            "nan" => Ok(value::Value::F64(f64::NAN)),
782            _ => f64::from_str(value)
783                .map(value::Value::F64)
784                .map_err(|_| bad(value)),
785        },
786        InternalFieldType::Float => match value {
787            "inf" => Ok(value::Value::F32(f32::INFINITY)),
788            "-inf" => Ok(value::Value::F32(f32::NEG_INFINITY)),
789            "nan" => Ok(value::Value::F32(f32::NAN)),
790            _ => f32::from_str(value)
791                .map(value::Value::F32)
792                .map_err(|_| bad(value)),
793        },
794        InternalFieldType::Int32 | InternalFieldType::SFixed32 | InternalFieldType::SInt32 => {
795            i32::from_str(value)
796                .map(value::Value::I32)
797                .map_err(|_| bad(value))
798        }
799        InternalFieldType::Int64 | InternalFieldType::SFixed64 | InternalFieldType::SInt64 => {
800            i64::from_str(value)
801                .map(value::Value::I64)
802                .map_err(|_| bad(value))
803        }
804        InternalFieldType::UInt32 | InternalFieldType::Fixed32 => u32::from_str(value)
805            .map(value::Value::U32)
806            .map_err(|_| bad(value)),
807        InternalFieldType::UInt64 | InternalFieldType::Fixed64 => u64::from_str(value)
808            .map(value::Value::U64)
809            .map_err(|_| bad(value)),
810        InternalFieldType::String => Ok(value::Value::String(value.to_owned())),
811        InternalFieldType::Group => unimplemented!(),
812        InternalFieldType::Bytes => Ok(value::Value::Bytes(
813            value.chars().map(|c| c as u8).collect(),
814        )),
815    }
816}
817
818#[cfg(test)]
819mod test {
820    use std::fs;
821
822    use protobuf::{self, descriptor::FileDescriptorSet, Message};
823
824    use super::FieldLabel::*;
825    use super::FieldType::*;
826    use super::*;
827
828    fn load_descriptors() -> Descriptors {
829        let mut file = fs::File::open("testdata/descriptors.pb").unwrap();
830        let proto = FileDescriptorSet::parse_from_reader(&mut file).unwrap();
831
832        Descriptors::from_proto(&proto)
833    }
834
835    macro_rules! check_field {
836        ($id:ident, $msg:expr, $field:expr, $t:pat, $label:expr, $num:expr) => {
837            #[test]
838            fn $id() {
839                let mut d = load_descriptors();
840                d.resolve_refs();
841                let msg = d.message_by_name($msg).unwrap();
842                let field_by_name = msg.field_by_name($field).unwrap();
843                match field_by_name.field_type(&d) {
844                    $t => (),
845                    t => panic!("Expected type {}, got {:?}", stringify!($t), t),
846                }
847                assert_eq!(field_by_name.name(), $field);
848                assert_eq!(field_by_name.number(), $num);
849                assert_eq!(field_by_name.field_label(), $label);
850
851                let field_by_number = msg.field_by_number($num).unwrap();
852                match field_by_number.field_type(&d) {
853                    $t => (),
854                    t => panic!("Expected type {}, got {:?}", stringify!($t), t),
855                }
856                assert_eq!(field_by_number.name(), $field);
857                assert_eq!(field_by_number.number(), $num);
858                assert_eq!(field_by_number.field_label(), $label);
859            }
860        };
861    }
862
863    macro_rules! check_enum_value {
864        ($id:ident, $enu:expr, $value:expr, $num:expr) => {
865            #[test]
866            fn $id() {
867                let mut d = load_descriptors();
868                d.resolve_refs();
869                let enu = d.enum_by_name($enu).unwrap();
870                let value_by_name = enu.value_by_name($value).unwrap();
871                assert_eq!(value_by_name.name(), $value);
872                assert_eq!(value_by_name.number(), $num);
873
874                let value_by_number = enu.value_by_number($num).unwrap();
875                assert_eq!(value_by_number.name(), $value);
876                assert_eq!(value_by_number.number(), $num);
877            }
878        };
879    }
880
881    check_field!(
882        optional_int32_field,
883        ".protobuf_unittest.TestAllTypes",
884        "optional_int32",
885        Int32,
886        Optional,
887        1
888    );
889
890    check_field!(
891        optional_int64_field,
892        ".protobuf_unittest.TestAllTypes",
893        "optional_int64",
894        Int64,
895        Optional,
896        2
897    );
898
899    check_field!(
900        optional_uint32_field,
901        ".protobuf_unittest.TestAllTypes",
902        "optional_uint32",
903        UInt32,
904        Optional,
905        3
906    );
907
908    check_field!(
909        optional_uint64_field,
910        ".protobuf_unittest.TestAllTypes",
911        "optional_uint64",
912        UInt64,
913        Optional,
914        4
915    );
916
917    check_field!(
918        optional_sint32_field,
919        ".protobuf_unittest.TestAllTypes",
920        "optional_sint32",
921        SInt32,
922        Optional,
923        5
924    );
925
926    check_field!(
927        optional_sint64_field,
928        ".protobuf_unittest.TestAllTypes",
929        "optional_sint64",
930        SInt64,
931        Optional,
932        6
933    );
934
935    check_field!(
936        optional_fixed32_field,
937        ".protobuf_unittest.TestAllTypes",
938        "optional_fixed32",
939        Fixed32,
940        Optional,
941        7
942    );
943
944    check_field!(
945        optional_fixed64_field,
946        ".protobuf_unittest.TestAllTypes",
947        "optional_fixed64",
948        Fixed64,
949        Optional,
950        8
951    );
952
953    check_field!(
954        optional_sfixed32_field,
955        ".protobuf_unittest.TestAllTypes",
956        "optional_sfixed32",
957        SFixed32,
958        Optional,
959        9
960    );
961
962    check_field!(
963        optional_sfixed64_field,
964        ".protobuf_unittest.TestAllTypes",
965        "optional_sfixed64",
966        SFixed64,
967        Optional,
968        10
969    );
970
971    check_field!(
972        optional_float_field,
973        ".protobuf_unittest.TestAllTypes",
974        "optional_float",
975        Float,
976        Optional,
977        11
978    );
979
980    check_field!(
981        optional_double_field,
982        ".protobuf_unittest.TestAllTypes",
983        "optional_double",
984        Double,
985        Optional,
986        12
987    );
988
989    check_field!(
990        optional_bool_field,
991        ".protobuf_unittest.TestAllTypes",
992        "optional_bool",
993        Bool,
994        Optional,
995        13
996    );
997
998    check_field!(
999        optional_string_field,
1000        ".protobuf_unittest.TestAllTypes",
1001        "optional_string",
1002        String,
1003        Optional,
1004        14
1005    );
1006
1007    check_field!(
1008        optional_bytes_field,
1009        ".protobuf_unittest.TestAllTypes",
1010        "optional_bytes",
1011        Bytes,
1012        Optional,
1013        15
1014    );
1015
1016    check_field!(
1017        repeated_int32_field,
1018        ".protobuf_unittest.TestAllTypes",
1019        "repeated_int32",
1020        Int32,
1021        Repeated,
1022        31
1023    );
1024
1025    check_field!(
1026        repeated_int64_field,
1027        ".protobuf_unittest.TestAllTypes",
1028        "repeated_int64",
1029        Int64,
1030        Repeated,
1031        32
1032    );
1033
1034    check_field!(
1035        repeated_uint32_field,
1036        ".protobuf_unittest.TestAllTypes",
1037        "repeated_uint32",
1038        UInt32,
1039        Repeated,
1040        33
1041    );
1042
1043    check_field!(
1044        repeated_uint64_field,
1045        ".protobuf_unittest.TestAllTypes",
1046        "repeated_uint64",
1047        UInt64,
1048        Repeated,
1049        34
1050    );
1051
1052    check_field!(
1053        repeated_sint32_field,
1054        ".protobuf_unittest.TestAllTypes",
1055        "repeated_sint32",
1056        SInt32,
1057        Repeated,
1058        35
1059    );
1060
1061    check_field!(
1062        repeated_sint64_field,
1063        ".protobuf_unittest.TestAllTypes",
1064        "repeated_sint64",
1065        SInt64,
1066        Repeated,
1067        36
1068    );
1069
1070    check_field!(
1071        repeated_fixed32_field,
1072        ".protobuf_unittest.TestAllTypes",
1073        "repeated_fixed32",
1074        Fixed32,
1075        Repeated,
1076        37
1077    );
1078
1079    check_field!(
1080        repeated_fixed64_field,
1081        ".protobuf_unittest.TestAllTypes",
1082        "repeated_fixed64",
1083        Fixed64,
1084        Repeated,
1085        38
1086    );
1087
1088    check_field!(
1089        repeated_sfixed32_field,
1090        ".protobuf_unittest.TestAllTypes",
1091        "repeated_sfixed32",
1092        SFixed32,
1093        Repeated,
1094        39
1095    );
1096
1097    check_field!(
1098        repeated_sfixed64_field,
1099        ".protobuf_unittest.TestAllTypes",
1100        "repeated_sfixed64",
1101        SFixed64,
1102        Repeated,
1103        40
1104    );
1105
1106    check_field!(
1107        repeated_float_field,
1108        ".protobuf_unittest.TestAllTypes",
1109        "repeated_float",
1110        Float,
1111        Repeated,
1112        41
1113    );
1114
1115    check_field!(
1116        repeated_double_field,
1117        ".protobuf_unittest.TestAllTypes",
1118        "repeated_double",
1119        Double,
1120        Repeated,
1121        42
1122    );
1123
1124    check_field!(
1125        repeated_bool_field,
1126        ".protobuf_unittest.TestAllTypes",
1127        "repeated_bool",
1128        Bool,
1129        Repeated,
1130        43
1131    );
1132
1133    check_field!(
1134        repeated_string_field,
1135        ".protobuf_unittest.TestAllTypes",
1136        "repeated_string",
1137        String,
1138        Repeated,
1139        44
1140    );
1141
1142    check_field!(
1143        repeated_bytes_field,
1144        ".protobuf_unittest.TestAllTypes",
1145        "repeated_bytes",
1146        Bytes,
1147        Repeated,
1148        45
1149    );
1150
1151    check_field!(
1152        repppeated_message_field,
1153        ".protobuf_unittest.TestAllTypes",
1154        "repeated_foreign_message",
1155        Message(..),
1156        Repeated,
1157        49
1158    );
1159
1160    check_field!(
1161        repeated_enum_field,
1162        ".protobuf_unittest.TestAllTypes",
1163        "repeated_foreign_enum",
1164        Enum(..),
1165        Repeated,
1166        52
1167    );
1168
1169    check_field!(
1170        required_field_a,
1171        ".protobuf_unittest.TestRequired",
1172        "a",
1173        Int32,
1174        Required,
1175        1
1176    );
1177
1178    check_field!(
1179        required_field_b,
1180        ".protobuf_unittest.TestRequired",
1181        "b",
1182        Int32,
1183        Required,
1184        3
1185    );
1186
1187    check_enum_value!(
1188        enum_value_foo,
1189        ".protobuf_unittest.ForeignEnum",
1190        "FOREIGN_FOO",
1191        4
1192    );
1193
1194    check_enum_value!(
1195        enum_value_bar,
1196        ".protobuf_unittest.ForeignEnum",
1197        "FOREIGN_BAR",
1198        5
1199    );
1200
1201    check_enum_value!(
1202        enum_value_baz,
1203        ".protobuf_unittest.ForeignEnum",
1204        "FOREIGN_BAZ",
1205        6
1206    );
1207}