Skip to main content

buffa_reflect/
oneof.rs

1//! [`OneofDescriptor`] — handle to a oneof declaration on a message.
2
3use buffa_descriptor::generated::descriptor::OneofDescriptorProto;
4
5use crate::{
6    field::FieldDescriptor,
7    message::MessageDescriptor,
8    pool::{DescriptorPool, MessageIndex},
9};
10
11/// Handle to one oneof declaration in a [`MessageDescriptor`].
12#[derive(Clone, Debug)]
13pub struct OneofDescriptor {
14    pub(crate) pool: DescriptorPool,
15    pub(crate) message: MessageIndex,
16    pub(crate) index: u32,
17}
18
19impl OneofDescriptor {
20    fn entry(&self) -> &crate::pool::OneofEntry {
21        &self.pool.inner.messages[self.message as usize].oneofs[self.index as usize]
22    }
23
24    /// Oneof name.
25    #[must_use]
26    pub fn name(&self) -> &str {
27        &self.entry().name
28    }
29
30    /// `<message.full_name>.<oneof_name>`, no leading dot.
31    #[must_use]
32    pub fn full_name(&self) -> &str {
33        &self.entry().full_name
34    }
35
36    /// True iff this oneof was synthesized for a proto3 `optional` field.
37    /// Synthetic oneofs are part of the descriptor model but do not generate
38    /// any user-facing oneof Rust enum.
39    #[must_use]
40    pub fn is_synthetic(&self) -> bool {
41        self.entry().is_synthetic
42    }
43
44    /// Owning message.
45    #[must_use]
46    pub fn parent_message(&self) -> MessageDescriptor {
47        MessageDescriptor {
48            pool: self.pool.clone(),
49            index: self.message,
50        }
51    }
52
53    /// Iterate over the fields belonging to this oneof.
54    pub fn fields(&self) -> impl ExactSizeIterator<Item = FieldDescriptor> + '_ {
55        let pool = self.pool.clone();
56        let owner = self.message;
57        let entry = self.entry();
58        entry
59            .field_indices
60            .clone()
61            .into_iter()
62            .map(move |fi| FieldDescriptor {
63                pool: pool.clone(),
64                message: owner,
65                index: fi,
66            })
67    }
68
69    /// Raw [`OneofDescriptorProto`] for advanced use.
70    #[must_use]
71    pub fn descriptor_proto(&self) -> &OneofDescriptorProto {
72        let msg_entry = &self.pool.inner.messages[self.message as usize];
73        let file = &self.pool.inner.files[msg_entry.file as usize];
74        let msg_proto =
75            crate::pool_build::resolve_message_proto(&file.proto, &msg_entry.proto_path);
76        &msg_proto.oneof_decl[self.entry().proto_index as usize]
77    }
78}
79
80impl PartialEq for OneofDescriptor {
81    fn eq(&self, other: &Self) -> bool {
82        std::sync::Arc::ptr_eq(&self.pool.inner, &other.pool.inner)
83            && self.message == other.message
84            && self.index == other.index
85    }
86}
87
88impl Eq for OneofDescriptor {}