Skip to main content

oxiproto_reflect/native/
descriptor.rs

1//! Native protobuf descriptor types.
2//!
3//! These types mirror the surface of `prost_reflect`'s descriptors but are
4//! built natively from a [`prost_types::FileDescriptorSet`] by
5//! [`DescriptorPool`](super::pool::DescriptorPool). Each descriptor is a cheap
6//! handle holding an [`Arc`] to the shared [`PoolInner`] plus an index, so
7//! cloning is O(1) and circular message references (a field whose type is the
8//! message itself, directly or transitively) are naturally supported.
9
10use std::collections::HashMap;
11use std::sync::Arc;
12
13use super::pool::PoolInner;
14
15/// The resolved type of a field.
16///
17/// Scalar types carry no payload; `Message` and `Enum` carry the index of the
18/// referenced type within the shared [`PoolInner`]. `Group` is recognised but
19/// unsupported on the wire (see the codec's explicit error).
20#[derive(Clone, Copy, Debug, PartialEq, Eq)]
21pub enum Kind {
22    /// `double`
23    Double,
24    /// `float`
25    Float,
26    /// `int32`
27    Int32,
28    /// `int64`
29    Int64,
30    /// `uint32`
31    Uint32,
32    /// `uint64`
33    Uint64,
34    /// `sint32`
35    Sint32,
36    /// `sint64`
37    Sint64,
38    /// `fixed32`
39    Fixed32,
40    /// `fixed64`
41    Fixed64,
42    /// `sfixed32`
43    Sfixed32,
44    /// `sfixed64`
45    Sfixed64,
46    /// `bool`
47    Bool,
48    /// `string`
49    String,
50    /// `bytes`
51    Bytes,
52    /// An embedded message; the index identifies the message in the pool.
53    Message(usize),
54    /// An enum; the index identifies the enum in the pool.
55    Enum(usize),
56    /// A proto2 group (unsupported on the wire); the index identifies the
57    /// synthetic group message in the pool.
58    Group(usize),
59}
60
61impl Kind {
62    /// Returns `true` if this kind is a length-delimited scalar (`string` or
63    /// `bytes`).
64    pub fn is_length_delimited_scalar(self) -> bool {
65        matches!(self, Kind::String | Kind::Bytes)
66    }
67
68    /// Returns `true` if this kind is a 64-bit fixed-width scalar.
69    pub fn is_fixed64(self) -> bool {
70        matches!(self, Kind::Double | Kind::Fixed64 | Kind::Sfixed64)
71    }
72
73    /// Returns `true` if this kind is a 32-bit fixed-width scalar.
74    pub fn is_fixed32(self) -> bool {
75        matches!(self, Kind::Float | Kind::Fixed32 | Kind::Sfixed32)
76    }
77
78    /// Returns `true` if this kind is a varint-encoded scalar (including enums
79    /// and booleans).
80    pub fn is_varint(self) -> bool {
81        matches!(
82            self,
83            Kind::Int32
84                | Kind::Int64
85                | Kind::Uint32
86                | Kind::Uint64
87                | Kind::Sint32
88                | Kind::Sint64
89                | Kind::Bool
90                | Kind::Enum(_)
91        )
92    }
93
94    /// Returns `true` if this kind can be packed in a repeated field (all
95    /// scalar numeric/bool/enum types).
96    pub fn is_packable(self) -> bool {
97        self.is_varint() || self.is_fixed32() || self.is_fixed64()
98    }
99}
100
101/// The cardinality (label) of a field.
102#[derive(Clone, Copy, Debug, PartialEq, Eq)]
103pub enum Cardinality {
104    /// Optional (proto3 singular, or proto2 `optional`).
105    Optional,
106    /// Required (proto2 `required`).
107    Required,
108    /// Repeated.
109    Repeated,
110}
111
112// ---------------------------------------------------------------------------
113// Internal data model (owned by `PoolInner`)
114// ---------------------------------------------------------------------------
115
116/// Owned data for a message type, stored in [`PoolInner::messages`].
117#[derive(Debug)]
118pub(crate) struct MessageData {
119    pub full_name: String,
120    pub name: String,
121    /// Indices into `PoolInner::files` identifying the declaring file.
122    pub file_index: usize,
123    /// Field data in declaration order.
124    pub fields: Vec<FieldData>,
125    /// Map from field number to position in `fields`.
126    pub field_by_number: HashMap<u32, usize>,
127    /// Map from field name to position in `fields`.
128    pub field_by_name: HashMap<String, usize>,
129    /// Map from JSON name to position in `fields`.
130    pub field_by_json_name: HashMap<String, usize>,
131    /// Oneof declarations in declaration order.
132    pub oneofs: Vec<OneofData>,
133    /// Indices (into `PoolInner::messages`) of nested message types.
134    pub nested_messages: Vec<usize>,
135    /// Indices (into `PoolInner::enums`) of nested enum types.
136    pub nested_enums: Vec<usize>,
137    /// Whether this message is a synthetic `map<K, V>` entry type
138    /// (`options.map_entry == true`).
139    pub is_map_entry: bool,
140}
141
142/// Owned data for a single field.
143#[derive(Debug)]
144pub(crate) struct FieldData {
145    pub name: String,
146    pub full_name: String,
147    pub json_name: String,
148    pub number: u32,
149    pub kind: Kind,
150    pub cardinality: Cardinality,
151    /// Whether the field is encoded packed (only meaningful for repeated
152    /// packable scalars). Defaults follow proto3 (packed) / proto2 (unpacked).
153    pub packed: bool,
154    /// Index into the parent message's `oneofs`, if this field is a member of
155    /// a oneof. Synthetic oneofs (proto3 optional) are included.
156    pub oneof_index: Option<usize>,
157    /// `true` if this field is a proto3 `optional` (synthetic-oneof) field.
158    pub proto3_optional: bool,
159}
160
161/// Owned data for a oneof declaration.
162#[derive(Debug)]
163pub(crate) struct OneofData {
164    pub name: String,
165    pub full_name: String,
166    /// Field positions (into the parent message's `fields`) belonging to this
167    /// oneof, in declaration order.
168    pub field_indices: Vec<usize>,
169    /// `true` if this oneof is synthetic (generated for a proto3 `optional`
170    /// field).
171    pub is_synthetic: bool,
172}
173
174/// Owned data for an enum type.
175#[derive(Debug)]
176pub(crate) struct EnumData {
177    pub full_name: String,
178    pub name: String,
179    pub file_index: usize,
180    pub values: Vec<EnumValueData>,
181    pub value_by_number: HashMap<i32, usize>,
182    pub value_by_name: HashMap<String, usize>,
183}
184
185/// Owned data for a single enum value.
186#[derive(Debug)]
187pub(crate) struct EnumValueData {
188    pub name: String,
189    pub full_name: String,
190    pub number: i32,
191}
192
193/// Owned data for a service.
194#[derive(Debug)]
195pub(crate) struct ServiceData {
196    pub full_name: String,
197    pub name: String,
198    pub file_index: usize,
199    pub methods: Vec<MethodData>,
200}
201
202/// Owned data for a single method.
203#[derive(Debug)]
204pub(crate) struct MethodData {
205    pub name: String,
206    pub full_name: String,
207    /// Index into `PoolInner::messages` for the input type.
208    pub input_index: usize,
209    /// Index into `PoolInner::messages` for the output type.
210    pub output_index: usize,
211    pub client_streaming: bool,
212    pub server_streaming: bool,
213}
214
215/// Owned data for a file.
216#[derive(Debug)]
217pub(crate) struct FileData {
218    pub name: String,
219    pub package: String,
220    pub syntax: String,
221    pub dependencies: Vec<String>,
222    /// `java_package` file option, if set.
223    pub java_package: Option<String>,
224    /// `go_package` file option, if set.
225    pub go_package: Option<String>,
226    /// `java_outer_classname` file option, if set.
227    pub java_outer_classname: Option<String>,
228    /// Whether the `deprecated` file option is set.
229    pub deprecated: bool,
230    /// Whether the `optimize_for` option is set to `CODE_SIZE` (2) or
231    /// `LITE_RUNTIME` (3). Stored as the raw integer from the proto enum.
232    pub optimize_for: i32,
233}
234
235// ---------------------------------------------------------------------------
236// Public handle types
237// ---------------------------------------------------------------------------
238
239/// A handle to a file descriptor within a [`DescriptorPool`](super::pool::DescriptorPool).
240#[derive(Clone)]
241pub struct FileDescriptor {
242    pub(crate) pool: Arc<PoolInner>,
243    pub(crate) index: usize,
244}
245
246/// A handle to a message descriptor.
247#[derive(Clone)]
248pub struct MessageDescriptor {
249    pub(crate) pool: Arc<PoolInner>,
250    pub(crate) index: usize,
251}
252
253/// A handle to a single field of a message.
254#[derive(Clone)]
255pub struct FieldDescriptor {
256    pub(crate) pool: Arc<PoolInner>,
257    pub(crate) message_index: usize,
258    pub(crate) field_index: usize,
259}
260
261/// A handle to a oneof declaration of a message.
262#[derive(Clone)]
263pub struct OneofDescriptor {
264    pub(crate) pool: Arc<PoolInner>,
265    pub(crate) message_index: usize,
266    pub(crate) oneof_index: usize,
267}
268
269/// A handle to an enum descriptor.
270#[derive(Clone)]
271pub struct EnumDescriptor {
272    pub(crate) pool: Arc<PoolInner>,
273    pub(crate) index: usize,
274}
275
276/// A handle to a single value of an enum.
277#[derive(Clone)]
278pub struct EnumValueDescriptor {
279    pub(crate) pool: Arc<PoolInner>,
280    pub(crate) enum_index: usize,
281    pub(crate) value_index: usize,
282}
283
284/// A handle to a service descriptor.
285#[derive(Clone)]
286pub struct ServiceDescriptor {
287    pub(crate) pool: Arc<PoolInner>,
288    pub(crate) index: usize,
289}
290
291/// A handle to a single method of a service.
292#[derive(Clone)]
293pub struct MethodDescriptor {
294    pub(crate) pool: Arc<PoolInner>,
295    pub(crate) service_index: usize,
296    pub(crate) method_index: usize,
297}
298
299// ---------------------------------------------------------------------------
300// FileDescriptor impl
301// ---------------------------------------------------------------------------
302
303impl FileDescriptor {
304    /// The file name (path), e.g. `"my/package/file.proto"`.
305    pub fn name(&self) -> &str {
306        &self.pool.files[self.index].name
307    }
308
309    /// The protobuf package, e.g. `"my.package"` (empty if none).
310    pub fn package_name(&self) -> &str {
311        &self.pool.files[self.index].package
312    }
313
314    /// The declared syntax (`"proto2"` or `"proto3"`).
315    pub fn syntax(&self) -> &str {
316        &self.pool.files[self.index].syntax
317    }
318
319    /// The names of imported (dependency) files.
320    pub fn dependencies(&self) -> impl Iterator<Item = &str> + '_ {
321        self.pool.files[self.index]
322            .dependencies
323            .iter()
324            .map(String::as_str)
325    }
326
327    /// The `java_package` file option, if set.
328    pub fn java_package(&self) -> Option<&str> {
329        self.pool.files[self.index].java_package.as_deref()
330    }
331
332    /// The `go_package` file option, if set.
333    pub fn go_package(&self) -> Option<&str> {
334        self.pool.files[self.index].go_package.as_deref()
335    }
336
337    /// The `java_outer_classname` file option, if set.
338    pub fn java_outer_classname(&self) -> Option<&str> {
339        self.pool.files[self.index].java_outer_classname.as_deref()
340    }
341
342    /// Returns `true` if the `deprecated` file option is set to `true`.
343    pub fn is_deprecated(&self) -> bool {
344        self.pool.files[self.index].deprecated
345    }
346
347    /// The raw `optimize_for` option value (0 = SPEED, 2 = CODE_SIZE, 3 =
348    /// LITE_RUNTIME; 0 is the default when unset).
349    pub fn optimize_for(&self) -> i32 {
350        self.pool.files[self.index].optimize_for
351    }
352}
353
354impl std::fmt::Debug for FileDescriptor {
355    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
356        f.debug_struct("FileDescriptor")
357            .field("name", &self.name())
358            .field("package", &self.package_name())
359            .finish()
360    }
361}
362
363impl PartialEq for FileDescriptor {
364    fn eq(&self, other: &Self) -> bool {
365        Arc::ptr_eq(&self.pool, &other.pool) && self.index == other.index
366    }
367}
368
369// ---------------------------------------------------------------------------
370// MessageDescriptor impl
371// ---------------------------------------------------------------------------
372
373impl MessageDescriptor {
374    pub(crate) fn data(&self) -> &MessageData {
375        &self.pool.messages[self.index]
376    }
377
378    /// The simple (unqualified) name of the message.
379    pub fn name(&self) -> &str {
380        &self.data().name
381    }
382
383    /// The fully-qualified name, e.g. `"my.package.MyMessage"`.
384    pub fn full_name(&self) -> &str {
385        &self.data().full_name
386    }
387
388    /// The [`FileDescriptor`] that declares this message.
389    pub fn parent_file(&self) -> FileDescriptor {
390        FileDescriptor {
391            pool: Arc::clone(&self.pool),
392            index: self.data().file_index,
393        }
394    }
395
396    /// `true` if this message is a synthetic `map<K, V>` entry type.
397    pub fn is_map_entry(&self) -> bool {
398        self.data().is_map_entry
399    }
400
401    /// Iterate over the message's fields in declaration order.
402    pub fn fields(&self) -> impl ExactSizeIterator<Item = FieldDescriptor> + '_ {
403        let pool = Arc::clone(&self.pool);
404        let message_index = self.index;
405        (0..self.data().fields.len()).map(move |field_index| FieldDescriptor {
406            pool: Arc::clone(&pool),
407            message_index,
408            field_index,
409        })
410    }
411
412    /// Look up a field by its number.
413    pub fn get_field(&self, number: u32) -> Option<FieldDescriptor> {
414        self.data()
415            .field_by_number
416            .get(&number)
417            .map(|&field_index| FieldDescriptor {
418                pool: Arc::clone(&self.pool),
419                message_index: self.index,
420                field_index,
421            })
422    }
423
424    /// Look up a field by its name.
425    pub fn get_field_by_name(&self, name: &str) -> Option<FieldDescriptor> {
426        self.data()
427            .field_by_name
428            .get(name)
429            .map(|&field_index| FieldDescriptor {
430                pool: Arc::clone(&self.pool),
431                message_index: self.index,
432                field_index,
433            })
434    }
435
436    /// Look up a field by its JSON name.
437    pub fn get_field_by_json_name(&self, json_name: &str) -> Option<FieldDescriptor> {
438        self.data()
439            .field_by_json_name
440            .get(json_name)
441            .map(|&field_index| FieldDescriptor {
442                pool: Arc::clone(&self.pool),
443                message_index: self.index,
444                field_index,
445            })
446    }
447
448    /// Iterate over the message's oneof declarations (including synthetic
449    /// proto3-optional oneofs) in declaration order.
450    pub fn oneofs(&self) -> impl ExactSizeIterator<Item = OneofDescriptor> + '_ {
451        let pool = Arc::clone(&self.pool);
452        let message_index = self.index;
453        (0..self.data().oneofs.len()).map(move |oneof_index| OneofDescriptor {
454            pool: Arc::clone(&pool),
455            message_index,
456            oneof_index,
457        })
458    }
459
460    /// Iterate over nested message types declared inside this message.
461    pub fn nested_messages(&self) -> impl ExactSizeIterator<Item = MessageDescriptor> + '_ {
462        let pool = Arc::clone(&self.pool);
463        self.data()
464            .nested_messages
465            .iter()
466            .map(move |&index| MessageDescriptor {
467                pool: Arc::clone(&pool),
468                index,
469            })
470    }
471
472    /// Iterate over nested enum types declared inside this message.
473    pub fn nested_enums(&self) -> impl ExactSizeIterator<Item = EnumDescriptor> + '_ {
474        let pool = Arc::clone(&self.pool);
475        self.data()
476            .nested_enums
477            .iter()
478            .map(move |&index| EnumDescriptor {
479                pool: Arc::clone(&pool),
480                index,
481            })
482    }
483}
484
485impl std::fmt::Debug for MessageDescriptor {
486    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
487        f.debug_struct("MessageDescriptor")
488            .field("full_name", &self.full_name())
489            .finish()
490    }
491}
492
493impl PartialEq for MessageDescriptor {
494    fn eq(&self, other: &Self) -> bool {
495        Arc::ptr_eq(&self.pool, &other.pool) && self.index == other.index
496    }
497}
498
499// ---------------------------------------------------------------------------
500// FieldDescriptor impl
501// ---------------------------------------------------------------------------
502
503impl FieldDescriptor {
504    pub(crate) fn data(&self) -> &FieldData {
505        &self.pool.messages[self.message_index].fields[self.field_index]
506    }
507
508    /// The simple field name.
509    pub fn name(&self) -> &str {
510        &self.data().name
511    }
512
513    /// The fully-qualified field name, e.g. `"my.package.MyMessage.my_field"`.
514    pub fn full_name(&self) -> &str {
515        &self.data().full_name
516    }
517
518    /// The JSON name of the field (camelCase by default).
519    pub fn json_name(&self) -> &str {
520        &self.data().json_name
521    }
522
523    /// The field number.
524    pub fn number(&self) -> u32 {
525        self.data().number
526    }
527
528    /// The resolved [`Kind`] of the field.
529    pub fn kind(&self) -> Kind {
530        self.data().kind
531    }
532
533    /// The [`Cardinality`] (label) of the field.
534    pub fn cardinality(&self) -> Cardinality {
535        self.data().cardinality
536    }
537
538    /// `true` if this is a `repeated` field.
539    pub fn is_list(&self) -> bool {
540        // A map field is repeated at the descriptor level, but is treated as a
541        // map; callers should consult `is_map`.
542        matches!(self.data().cardinality, Cardinality::Repeated) && !self.is_map()
543    }
544
545    /// `true` if this field is a `map<K, V>` (its element type is a synthetic
546    /// map-entry message and the label is repeated).
547    pub fn is_map(&self) -> bool {
548        if !matches!(self.data().cardinality, Cardinality::Repeated) {
549            return false;
550        }
551        match self.data().kind {
552            Kind::Message(idx) => self.pool.messages[idx].is_map_entry,
553            _ => false,
554        }
555    }
556
557    /// `true` if this repeated scalar field is encoded packed.
558    pub fn is_packed(&self) -> bool {
559        self.data().packed
560    }
561
562    /// `true` if this field is a proto3 `optional`.
563    pub fn is_proto3_optional(&self) -> bool {
564        self.data().proto3_optional
565    }
566
567    /// The [`OneofDescriptor`] this field belongs to, if any.
568    pub fn containing_oneof(&self) -> Option<OneofDescriptor> {
569        self.data().oneof_index.map(|oneof_index| OneofDescriptor {
570            pool: Arc::clone(&self.pool),
571            message_index: self.message_index,
572            oneof_index,
573        })
574    }
575
576    /// The message that declares this field.
577    pub fn parent_message(&self) -> MessageDescriptor {
578        MessageDescriptor {
579            pool: Arc::clone(&self.pool),
580            index: self.message_index,
581        }
582    }
583
584    /// If this field is of message kind, the referenced [`MessageDescriptor`].
585    pub fn message_type(&self) -> Option<MessageDescriptor> {
586        match self.data().kind {
587            Kind::Message(index) | Kind::Group(index) => Some(MessageDescriptor {
588                pool: Arc::clone(&self.pool),
589                index,
590            }),
591            _ => None,
592        }
593    }
594
595    /// If this field is of enum kind, the referenced [`EnumDescriptor`].
596    pub fn enum_type(&self) -> Option<EnumDescriptor> {
597        match self.data().kind {
598            Kind::Enum(index) => Some(EnumDescriptor {
599                pool: Arc::clone(&self.pool),
600                index,
601            }),
602            _ => None,
603        }
604    }
605
606    /// For a map field, the key field descriptor of the synthetic entry.
607    pub(crate) fn map_entry_key_field(&self) -> Option<FieldDescriptor> {
608        match self.data().kind {
609            Kind::Message(idx) if self.pool.messages[idx].is_map_entry => Some(FieldDescriptor {
610                pool: Arc::clone(&self.pool),
611                message_index: idx,
612                field_index: self.pool.messages[idx].field_by_number.get(&1).copied()?,
613            }),
614            _ => None,
615        }
616    }
617
618    /// For a map field, the value field descriptor of the synthetic entry.
619    pub(crate) fn map_entry_value_field(&self) -> Option<FieldDescriptor> {
620        match self.data().kind {
621            Kind::Message(idx) if self.pool.messages[idx].is_map_entry => Some(FieldDescriptor {
622                pool: Arc::clone(&self.pool),
623                message_index: idx,
624                field_index: self.pool.messages[idx].field_by_number.get(&2).copied()?,
625            }),
626            _ => None,
627        }
628    }
629}
630
631impl std::fmt::Debug for FieldDescriptor {
632    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
633        f.debug_struct("FieldDescriptor")
634            .field("name", &self.name())
635            .field("number", &self.number())
636            .field("kind", &self.kind())
637            .field("cardinality", &self.cardinality())
638            .finish()
639    }
640}
641
642impl PartialEq for FieldDescriptor {
643    fn eq(&self, other: &Self) -> bool {
644        Arc::ptr_eq(&self.pool, &other.pool)
645            && self.message_index == other.message_index
646            && self.field_index == other.field_index
647    }
648}
649
650// ---------------------------------------------------------------------------
651// OneofDescriptor impl
652// ---------------------------------------------------------------------------
653
654impl OneofDescriptor {
655    pub(crate) fn data(&self) -> &OneofData {
656        &self.pool.messages[self.message_index].oneofs[self.oneof_index]
657    }
658
659    /// The simple oneof name.
660    pub fn name(&self) -> &str {
661        &self.data().name
662    }
663
664    /// The fully-qualified oneof name.
665    pub fn full_name(&self) -> &str {
666        &self.data().full_name
667    }
668
669    /// `true` if this oneof is synthetic (generated for a proto3 `optional`).
670    pub fn is_synthetic(&self) -> bool {
671        self.data().is_synthetic
672    }
673
674    /// Iterate over the fields belonging to this oneof.
675    pub fn fields(&self) -> impl ExactSizeIterator<Item = FieldDescriptor> + '_ {
676        let pool = Arc::clone(&self.pool);
677        let message_index = self.message_index;
678        self.data()
679            .field_indices
680            .iter()
681            .map(move |&field_index| FieldDescriptor {
682                pool: Arc::clone(&pool),
683                message_index,
684                field_index,
685            })
686    }
687}
688
689impl std::fmt::Debug for OneofDescriptor {
690    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
691        f.debug_struct("OneofDescriptor")
692            .field("full_name", &self.full_name())
693            .finish()
694    }
695}
696
697impl PartialEq for OneofDescriptor {
698    fn eq(&self, other: &Self) -> bool {
699        Arc::ptr_eq(&self.pool, &other.pool)
700            && self.message_index == other.message_index
701            && self.oneof_index == other.oneof_index
702    }
703}
704
705// ---------------------------------------------------------------------------
706// EnumDescriptor impl
707// ---------------------------------------------------------------------------
708
709impl EnumDescriptor {
710    pub(crate) fn data(&self) -> &EnumData {
711        &self.pool.enums[self.index]
712    }
713
714    /// The simple enum name.
715    pub fn name(&self) -> &str {
716        &self.data().name
717    }
718
719    /// The fully-qualified enum name.
720    pub fn full_name(&self) -> &str {
721        &self.data().full_name
722    }
723
724    /// The file that declares this enum.
725    pub fn parent_file(&self) -> FileDescriptor {
726        FileDescriptor {
727            pool: Arc::clone(&self.pool),
728            index: self.data().file_index,
729        }
730    }
731
732    /// Iterate over the enum values in declaration order.
733    pub fn values(&self) -> impl ExactSizeIterator<Item = EnumValueDescriptor> + '_ {
734        let pool = Arc::clone(&self.pool);
735        let enum_index = self.index;
736        (0..self.data().values.len()).map(move |value_index| EnumValueDescriptor {
737            pool: Arc::clone(&pool),
738            enum_index,
739            value_index,
740        })
741    }
742
743    /// Look up an enum value by its number.
744    pub fn get_value(&self, number: i32) -> Option<EnumValueDescriptor> {
745        self.data()
746            .value_by_number
747            .get(&number)
748            .map(|&value_index| EnumValueDescriptor {
749                pool: Arc::clone(&self.pool),
750                enum_index: self.index,
751                value_index,
752            })
753    }
754
755    /// Look up an enum value by its name.
756    pub fn get_value_by_name(&self, name: &str) -> Option<EnumValueDescriptor> {
757        self.data()
758            .value_by_name
759            .get(name)
760            .map(|&value_index| EnumValueDescriptor {
761                pool: Arc::clone(&self.pool),
762                enum_index: self.index,
763                value_index,
764            })
765    }
766
767    /// The default value of this enum (the value with number 0, or the first
768    /// declared value if 0 is absent — proto2 semantics).
769    pub fn default_value(&self) -> Option<EnumValueDescriptor> {
770        self.get_value(0).or_else(|| {
771            if self.data().values.is_empty() {
772                None
773            } else {
774                Some(EnumValueDescriptor {
775                    pool: Arc::clone(&self.pool),
776                    enum_index: self.index,
777                    value_index: 0,
778                })
779            }
780        })
781    }
782}
783
784impl std::fmt::Debug for EnumDescriptor {
785    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
786        f.debug_struct("EnumDescriptor")
787            .field("full_name", &self.full_name())
788            .finish()
789    }
790}
791
792impl PartialEq for EnumDescriptor {
793    fn eq(&self, other: &Self) -> bool {
794        Arc::ptr_eq(&self.pool, &other.pool) && self.index == other.index
795    }
796}
797
798// ---------------------------------------------------------------------------
799// EnumValueDescriptor impl
800// ---------------------------------------------------------------------------
801
802impl EnumValueDescriptor {
803    pub(crate) fn data(&self) -> &EnumValueData {
804        &self.pool.enums[self.enum_index].values[self.value_index]
805    }
806
807    /// The simple value name.
808    pub fn name(&self) -> &str {
809        &self.data().name
810    }
811
812    /// The fully-qualified value name.
813    pub fn full_name(&self) -> &str {
814        &self.data().full_name
815    }
816
817    /// The integer number of this value.
818    pub fn number(&self) -> i32 {
819        self.data().number
820    }
821
822    /// The enum that declares this value.
823    pub fn parent_enum(&self) -> EnumDescriptor {
824        EnumDescriptor {
825            pool: Arc::clone(&self.pool),
826            index: self.enum_index,
827        }
828    }
829}
830
831impl std::fmt::Debug for EnumValueDescriptor {
832    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
833        f.debug_struct("EnumValueDescriptor")
834            .field("full_name", &self.full_name())
835            .field("number", &self.number())
836            .finish()
837    }
838}
839
840impl PartialEq for EnumValueDescriptor {
841    fn eq(&self, other: &Self) -> bool {
842        Arc::ptr_eq(&self.pool, &other.pool)
843            && self.enum_index == other.enum_index
844            && self.value_index == other.value_index
845    }
846}
847
848// ---------------------------------------------------------------------------
849// ServiceDescriptor impl
850// ---------------------------------------------------------------------------
851
852impl ServiceDescriptor {
853    pub(crate) fn data(&self) -> &ServiceData {
854        &self.pool.services[self.index]
855    }
856
857    /// The simple service name.
858    pub fn name(&self) -> &str {
859        &self.data().name
860    }
861
862    /// The fully-qualified service name.
863    pub fn full_name(&self) -> &str {
864        &self.data().full_name
865    }
866
867    /// The file that declares this service.
868    pub fn parent_file(&self) -> FileDescriptor {
869        FileDescriptor {
870            pool: Arc::clone(&self.pool),
871            index: self.data().file_index,
872        }
873    }
874
875    /// Iterate over the methods of this service in declaration order.
876    pub fn methods(&self) -> impl ExactSizeIterator<Item = MethodDescriptor> + '_ {
877        let pool = Arc::clone(&self.pool);
878        let service_index = self.index;
879        (0..self.data().methods.len()).map(move |method_index| MethodDescriptor {
880            pool: Arc::clone(&pool),
881            service_index,
882            method_index,
883        })
884    }
885}
886
887impl std::fmt::Debug for ServiceDescriptor {
888    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
889        f.debug_struct("ServiceDescriptor")
890            .field("full_name", &self.full_name())
891            .finish()
892    }
893}
894
895impl PartialEq for ServiceDescriptor {
896    fn eq(&self, other: &Self) -> bool {
897        Arc::ptr_eq(&self.pool, &other.pool) && self.index == other.index
898    }
899}
900
901// ---------------------------------------------------------------------------
902// MethodDescriptor impl
903// ---------------------------------------------------------------------------
904
905impl MethodDescriptor {
906    pub(crate) fn data(&self) -> &MethodData {
907        &self.pool.services[self.service_index].methods[self.method_index]
908    }
909
910    /// The simple method name.
911    pub fn name(&self) -> &str {
912        &self.data().name
913    }
914
915    /// The fully-qualified method name.
916    pub fn full_name(&self) -> &str {
917        &self.data().full_name
918    }
919
920    /// The input (request) message type.
921    pub fn input(&self) -> MessageDescriptor {
922        MessageDescriptor {
923            pool: Arc::clone(&self.pool),
924            index: self.data().input_index,
925        }
926    }
927
928    /// The output (response) message type.
929    pub fn output(&self) -> MessageDescriptor {
930        MessageDescriptor {
931            pool: Arc::clone(&self.pool),
932            index: self.data().output_index,
933        }
934    }
935
936    /// `true` if the client streams multiple request messages.
937    pub fn is_client_streaming(&self) -> bool {
938        self.data().client_streaming
939    }
940
941    /// `true` if the server streams multiple response messages.
942    pub fn is_server_streaming(&self) -> bool {
943        self.data().server_streaming
944    }
945
946    /// The service that declares this method.
947    pub fn parent_service(&self) -> ServiceDescriptor {
948        ServiceDescriptor {
949            pool: Arc::clone(&self.pool),
950            index: self.service_index,
951        }
952    }
953}
954
955impl std::fmt::Debug for MethodDescriptor {
956    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
957        f.debug_struct("MethodDescriptor")
958            .field("full_name", &self.full_name())
959            .field("client_streaming", &self.is_client_streaming())
960            .field("server_streaming", &self.is_server_streaming())
961            .finish()
962    }
963}
964
965impl PartialEq for MethodDescriptor {
966    fn eq(&self, other: &Self) -> bool {
967        Arc::ptr_eq(&self.pool, &other.pool)
968            && self.service_index == other.service_index
969            && self.method_index == other.method_index
970    }
971}