1use buffa_descriptor::generated::descriptor::{MethodDescriptorProto, ServiceDescriptorProto};
9
10use crate::{
11 file::FileDescriptor,
12 message::MessageDescriptor,
13 pool::{DescriptorPool, FileIndex, MessageIndex},
14};
15
16pub(crate) type ServiceIndex = u32;
18
19#[derive(Clone)]
21pub(crate) struct ServiceEntry {
22 pub(crate) full_name: Box<str>,
23 pub(crate) name: Box<str>,
24 pub(crate) file: FileIndex,
25 pub(crate) proto_index: u32,
26 pub(crate) methods: Vec<MethodEntry>,
27}
28
29#[derive(Clone)]
30pub(crate) struct MethodEntry {
31 pub(crate) name: Box<str>,
32 pub(crate) full_name: Box<str>,
33 pub(crate) input: MessageIndex,
34 pub(crate) output: MessageIndex,
35 pub(crate) is_client_streaming: bool,
36 pub(crate) is_server_streaming: bool,
37 pub(crate) proto_index: u32,
38}
39
40#[derive(Clone, Debug)]
42pub struct ServiceDescriptor {
43 pub(crate) pool: DescriptorPool,
44 pub(crate) index: ServiceIndex,
45}
46
47impl ServiceDescriptor {
48 fn entry(&self) -> &ServiceEntry {
49 &self.pool.inner.services[self.index as usize]
50 }
51
52 #[must_use]
54 pub fn name(&self) -> &str {
55 &self.entry().name
56 }
57
58 #[must_use]
60 pub fn full_name(&self) -> &str {
61 &self.entry().full_name
62 }
63
64 #[must_use]
66 pub fn parent_file(&self) -> FileDescriptor {
67 FileDescriptor {
68 pool: self.pool.clone(),
69 index: self.entry().file,
70 }
71 }
72
73 pub fn methods(&self) -> impl ExactSizeIterator<Item = MethodDescriptor> + '_ {
75 let len = self.entry().methods.len() as u32;
76 let pool = self.pool.clone();
77 let svc = self.index;
78 (0..len).map(move |idx| MethodDescriptor {
79 pool: pool.clone(),
80 service: svc,
81 index: idx,
82 })
83 }
84
85 #[must_use]
87 pub fn descriptor_proto(&self) -> &ServiceDescriptorProto {
88 let entry = self.entry();
89 let file = &self.pool.inner.files[entry.file as usize];
90 &file.proto.service[entry.proto_index as usize]
91 }
92}
93
94impl PartialEq for ServiceDescriptor {
95 fn eq(&self, other: &Self) -> bool {
96 std::sync::Arc::ptr_eq(&self.pool.inner, &other.pool.inner) && self.index == other.index
97 }
98}
99
100impl Eq for ServiceDescriptor {}
101
102#[derive(Clone, Debug)]
104pub struct MethodDescriptor {
105 pub(crate) pool: DescriptorPool,
106 pub(crate) service: ServiceIndex,
107 pub(crate) index: u32,
108}
109
110impl MethodDescriptor {
111 fn entry(&self) -> &MethodEntry {
112 &self.pool.inner.services[self.service as usize].methods[self.index as usize]
113 }
114
115 #[must_use]
117 pub fn name(&self) -> &str {
118 &self.entry().name
119 }
120
121 #[must_use]
123 pub fn full_name(&self) -> &str {
124 &self.entry().full_name
125 }
126
127 #[must_use]
129 pub fn input(&self) -> MessageDescriptor {
130 MessageDescriptor {
131 pool: self.pool.clone(),
132 index: self.entry().input,
133 }
134 }
135
136 #[must_use]
138 pub fn output(&self) -> MessageDescriptor {
139 MessageDescriptor {
140 pool: self.pool.clone(),
141 index: self.entry().output,
142 }
143 }
144
145 #[must_use]
147 pub fn is_client_streaming(&self) -> bool {
148 self.entry().is_client_streaming
149 }
150
151 #[must_use]
153 pub fn is_server_streaming(&self) -> bool {
154 self.entry().is_server_streaming
155 }
156
157 #[must_use]
159 pub fn parent_service(&self) -> ServiceDescriptor {
160 ServiceDescriptor {
161 pool: self.pool.clone(),
162 index: self.service,
163 }
164 }
165
166 #[must_use]
168 pub fn descriptor_proto(&self) -> &MethodDescriptorProto {
169 let svc_entry = &self.pool.inner.services[self.service as usize];
170 let file = &self.pool.inner.files[svc_entry.file as usize];
171 &file.proto.service[svc_entry.proto_index as usize].method
172 [self.entry().proto_index as usize]
173 }
174}
175
176impl PartialEq for MethodDescriptor {
177 fn eq(&self, other: &Self) -> bool {
178 std::sync::Arc::ptr_eq(&self.pool.inner, &other.pool.inner)
179 && self.service == other.service
180 && self.index == other.index
181 }
182}
183
184impl Eq for MethodDescriptor {}
185
186impl DescriptorPool {
187 pub fn services(&self) -> impl ExactSizeIterator<Item = ServiceDescriptor> + '_ {
189 let pool = self.clone();
190 (0..self.inner.services.len() as u32).map(move |idx| ServiceDescriptor {
191 pool: pool.clone(),
192 index: idx,
193 })
194 }
195
196 #[must_use]
198 pub fn get_service_by_name(&self, full_name: &str) -> Option<ServiceDescriptor> {
199 let key = full_name.strip_prefix('.').unwrap_or(full_name);
200 self.inner
201 .service_names
202 .get(key)
203 .map(|idx| ServiceDescriptor {
204 pool: self.clone(),
205 index: *idx,
206 })
207 }
208}
209
210impl FileDescriptor {
211 pub fn services(&self) -> impl ExactSizeIterator<Item = ServiceDescriptor> + '_ {
213 let pool = self.pool.clone();
214 let entry = &self.pool.inner.files[self.index as usize];
215 entry
216 .service_indices
217 .clone()
218 .into_iter()
219 .map(move |idx| ServiceDescriptor {
220 pool: pool.clone(),
221 index: idx,
222 })
223 }
224}