1use buffa_descriptor::generated::descriptor::DescriptorProto;
4
5use crate::{
6 field::FieldDescriptor,
7 file::FileDescriptor,
8 oneof::OneofDescriptor,
9 pool::{DescriptorPool, MessageIndex},
10};
11
12#[derive(Clone, Debug)]
14pub struct MessageDescriptor {
15 pub(crate) pool: DescriptorPool,
16 pub(crate) index: MessageIndex,
17}
18
19impl MessageDescriptor {
20 #[must_use]
23 pub fn full_name(&self) -> &str {
24 &self.pool.inner.messages[self.index as usize].full_name
25 }
26
27 #[must_use]
29 pub fn name(&self) -> &str {
30 &self.pool.inner.messages[self.index as usize].name
31 }
32
33 #[must_use]
35 pub fn parent_file(&self) -> FileDescriptor {
36 let entry = &self.pool.inner.messages[self.index as usize];
37 FileDescriptor {
38 pool: self.pool.clone(),
39 index: entry.file,
40 }
41 }
42
43 #[must_use]
45 pub fn parent_message(&self) -> Option<MessageDescriptor> {
46 let entry = &self.pool.inner.messages[self.index as usize];
47 entry.parent.map(|idx| MessageDescriptor {
48 pool: self.pool.clone(),
49 index: idx,
50 })
51 }
52
53 pub fn fields(&self) -> impl ExactSizeIterator<Item = FieldDescriptor> + '_ {
55 let pool = self.pool.clone();
56 let owner = self.index;
57 let len = self.pool.inner.messages[owner as usize].fields.len() as u32;
58 (0..len).map(move |fi| FieldDescriptor {
59 pool: pool.clone(),
60 message: owner,
61 index: fi,
62 })
63 }
64
65 pub fn oneofs(&self) -> impl ExactSizeIterator<Item = OneofDescriptor> + '_ {
70 let pool = self.pool.clone();
71 let owner = self.index;
72 let len = self.pool.inner.messages[owner as usize].oneofs.len() as u32;
73 (0..len).map(move |oi| OneofDescriptor {
74 pool: pool.clone(),
75 message: owner,
76 index: oi,
77 })
78 }
79
80 #[must_use]
82 pub fn get_field_by_name(&self, name: &str) -> Option<FieldDescriptor> {
83 let entry = &self.pool.inner.messages[self.index as usize];
84 entry.by_name.get(name).map(|fi| FieldDescriptor {
85 pool: self.pool.clone(),
86 message: self.index,
87 index: *fi,
88 })
89 }
90
91 #[must_use]
93 pub fn get_field_by_json_name(&self, name: &str) -> Option<FieldDescriptor> {
94 let entry = &self.pool.inner.messages[self.index as usize];
95 entry.by_json_name.get(name).map(|fi| FieldDescriptor {
96 pool: self.pool.clone(),
97 message: self.index,
98 index: *fi,
99 })
100 }
101
102 #[must_use]
104 pub fn get_field_by_number(&self, number: u32) -> Option<FieldDescriptor> {
105 let entry = &self.pool.inner.messages[self.index as usize];
106 entry.by_number.get(&number).map(|fi| FieldDescriptor {
107 pool: self.pool.clone(),
108 message: self.index,
109 index: *fi,
110 })
111 }
112
113 #[must_use]
115 pub fn is_map_entry(&self) -> bool {
116 self.pool.inner.messages[self.index as usize].is_map_entry
117 }
118
119 #[must_use]
122 pub fn descriptor_proto(&self) -> &DescriptorProto {
123 let entry = &self.pool.inner.messages[self.index as usize];
124 let file = &self.pool.inner.files[entry.file as usize];
125 crate::pool_build::resolve_message_proto(&file.proto, &entry.proto_path)
126 }
127}
128
129impl PartialEq for MessageDescriptor {
130 fn eq(&self, other: &Self) -> bool {
131 std::sync::Arc::ptr_eq(&self.pool.inner, &other.pool.inner) && self.index == other.index
132 }
133}
134
135impl Eq for MessageDescriptor {}