1use std::collections::HashMap;
26use std::fmt::{Display, Formatter};
27use std::sync::Arc;
28
29use prost::encoding::{WireType, decode_key, decode_varint};
30use prost::{DecodeError, Message};
31use prost_types::{
32 DescriptorProto, EnumDescriptorProto, FieldDescriptorProto, FileDescriptorProto,
33 FileDescriptorSet,
34};
35use tonic::Status;
36
37pub mod v1;
39pub mod v1alpha;
41
42#[derive(Debug)]
44pub struct Builder<'b> {
45 file_descriptor_sets: Vec<FileDescriptorSet>,
46 encoded_file_descriptor_sets: Vec<&'b [u8]>,
47 include_reflection_service: bool,
48
49 service_names: Vec<String>,
50 use_all_service_names: bool,
51}
52
53impl<'b> Builder<'b> {
54 pub fn configure() -> Self {
56 Builder {
57 file_descriptor_sets: Vec::new(),
58 encoded_file_descriptor_sets: Vec::new(),
59 include_reflection_service: true,
60
61 service_names: Vec::new(),
62 use_all_service_names: true,
63 }
64 }
65
66 pub fn register_file_descriptor_set(mut self, file_descriptor_set: FileDescriptorSet) -> Self {
69 self.file_descriptor_sets.push(file_descriptor_set);
70 self
71 }
72
73 pub fn register_encoded_file_descriptor_set(
76 mut self,
77 encoded_file_descriptor_set: &'b [u8],
78 ) -> Self {
79 self.encoded_file_descriptor_sets
80 .push(encoded_file_descriptor_set);
81 self
82 }
83
84 pub fn include_reflection_service(mut self, include: bool) -> Self {
87 self.include_reflection_service = include;
88 self
89 }
90
91 pub fn with_service_name(mut self, name: impl Into<String>) -> Self {
96 self.use_all_service_names = false;
97 self.service_names.push(name.into());
98 self
99 }
100
101 pub fn build_v1(
103 mut self,
104 ) -> Result<v1::ServerReflectionServer<impl v1::ServerReflection>, Error> {
105 if self.include_reflection_service {
106 self = self.register_encoded_file_descriptor_set(crate::pb::v1::FILE_DESCRIPTOR_SET);
107 }
108
109 Ok(v1::ServerReflectionServer::new(
110 v1::ReflectionService::from(ReflectionServiceState::new(
111 self.service_names,
112 self.encoded_file_descriptor_sets,
113 self.file_descriptor_sets,
114 self.use_all_service_names,
115 )?),
116 ))
117 }
118
119 pub fn build_v1alpha(
121 mut self,
122 ) -> Result<v1alpha::ServerReflectionServer<impl v1alpha::ServerReflection>, Error> {
123 if self.include_reflection_service {
124 self =
125 self.register_encoded_file_descriptor_set(crate::pb::v1alpha::FILE_DESCRIPTOR_SET);
126 }
127
128 Ok(v1alpha::ServerReflectionServer::new(
129 v1alpha::ReflectionService::from(ReflectionServiceState::new(
130 self.service_names,
131 self.encoded_file_descriptor_sets,
132 self.file_descriptor_sets,
133 self.use_all_service_names,
134 )?),
135 ))
136 }
137}
138
139#[derive(Debug)]
140struct ReflectionServiceState {
141 service_names: Vec<String>,
142 files: HashMap<String, Arc<[u8]>>,
148 symbols: HashMap<String, Arc<[u8]>>,
149}
150
151impl ReflectionServiceState {
152 fn new(
153 service_names: Vec<String>,
154 encoded_file_descriptor_sets: Vec<&[u8]>,
155 file_descriptor_sets: Vec<FileDescriptorSet>,
156 use_all_service_names: bool,
157 ) -> Result<Self, Error> {
158 let mut state = ReflectionServiceState {
159 service_names,
160 files: HashMap::new(),
161 symbols: HashMap::new(),
162 };
163
164 for encoded in encoded_file_descriptor_sets {
177 for raw in split_file_descriptor_set(encoded)? {
178 let fd = FileDescriptorProto::decode(raw.as_slice())?;
179 state.register_file(&fd, Arc::from(raw), use_all_service_names)?;
180 }
181 }
182
183 for fds in file_descriptor_sets {
191 for fd in fds.file {
192 let raw = fd.encode_to_vec();
193 state.register_file(&fd, Arc::from(raw), use_all_service_names)?;
194 }
195 }
196
197 Ok(state)
198 }
199
200 fn register_file(
201 &mut self,
202 fd: &FileDescriptorProto,
203 raw: Arc<[u8]>,
204 use_all_service_names: bool,
205 ) -> Result<(), Error> {
206 let name = match fd.name.clone() {
207 None => {
208 return Err(Error::InvalidFileDescriptorSet("missing name".to_string()));
209 }
210 Some(n) => n,
211 };
212
213 if self.files.contains_key(&name) {
217 return Ok(());
218 }
219
220 self.files.insert(name, raw.clone());
221 self.process_file(fd, &raw, use_all_service_names)
222 }
223
224 fn process_file(
225 &mut self,
226 fd: &FileDescriptorProto,
227 raw: &Arc<[u8]>,
228 use_all_service_names: bool,
229 ) -> Result<(), Error> {
230 let prefix = &fd.package.clone().unwrap_or_default();
231
232 for msg in &fd.message_type {
233 self.process_message(raw, prefix, msg)?;
234 }
235
236 for en in &fd.enum_type {
237 self.process_enum(raw, prefix, en)?;
238 }
239
240 for service in &fd.service {
241 let service_name = extract_name(prefix, "service", service.name.as_ref())?;
242 if use_all_service_names {
243 self.service_names.push(service_name.clone());
244 }
245 self.symbols.insert(service_name.clone(), raw.clone());
246
247 for method in &service.method {
248 let method_name = extract_name(&service_name, "method", method.name.as_ref())?;
249 self.symbols.insert(method_name, raw.clone());
250 }
251 }
252
253 Ok(())
254 }
255
256 fn process_message(
257 &mut self,
258 raw: &Arc<[u8]>,
259 prefix: &str,
260 msg: &DescriptorProto,
261 ) -> Result<(), Error> {
262 let message_name = extract_name(prefix, "message", msg.name.as_ref())?;
263 self.symbols.insert(message_name.clone(), raw.clone());
264
265 for nested in &msg.nested_type {
266 self.process_message(raw, &message_name, nested)?;
267 }
268
269 for en in &msg.enum_type {
270 self.process_enum(raw, &message_name, en)?;
271 }
272
273 for field in &msg.field {
274 self.process_field(raw, &message_name, field)?;
275 }
276
277 for oneof in &msg.oneof_decl {
278 let oneof_name = extract_name(&message_name, "oneof", oneof.name.as_ref())?;
279 self.symbols.insert(oneof_name, raw.clone());
280 }
281
282 Ok(())
283 }
284
285 fn process_enum(
286 &mut self,
287 raw: &Arc<[u8]>,
288 prefix: &str,
289 en: &EnumDescriptorProto,
290 ) -> Result<(), Error> {
291 let enum_name = extract_name(prefix, "enum", en.name.as_ref())?;
292 self.symbols.insert(enum_name.clone(), raw.clone());
293
294 for value in &en.value {
295 let value_name = extract_name(&enum_name, "enum value", value.name.as_ref())?;
296 self.symbols.insert(value_name, raw.clone());
297 }
298
299 Ok(())
300 }
301
302 fn process_field(
303 &mut self,
304 raw: &Arc<[u8]>,
305 prefix: &str,
306 field: &FieldDescriptorProto,
307 ) -> Result<(), Error> {
308 let field_name = extract_name(prefix, "field", field.name.as_ref())?;
309 self.symbols.insert(field_name, raw.clone());
310 Ok(())
311 }
312
313 fn list_services(&self) -> &[String] {
314 &self.service_names
315 }
316
317 fn symbol_by_name(&self, symbol: &str) -> Result<Vec<u8>, Status> {
318 match self.symbols.get(symbol) {
319 None => Err(Status::not_found(format!("symbol '{symbol}' not found"))),
320 Some(raw) => Ok(raw.to_vec()),
321 }
322 }
323
324 fn file_by_filename(&self, filename: &str) -> Result<Vec<u8>, Status> {
325 match self.files.get(filename) {
326 None => Err(Status::not_found(format!("file '{filename}' not found"))),
327 Some(raw) => Ok(raw.to_vec()),
328 }
329 }
330}
331
332fn split_file_descriptor_set(mut buf: &[u8]) -> Result<Vec<Vec<u8>>, Error> {
340 const FILE_FIELD_TAG: u32 = 1;
342
343 let truncated = || {
344 Error::InvalidFileDescriptorSet("unexpected end of FileDescriptorSet buffer".to_string())
345 };
346
347 let mut files = Vec::new();
348 while !buf.is_empty() {
349 let (tag, wire_type) = decode_key(&mut buf)?;
350 match wire_type {
351 WireType::LengthDelimited => {
352 let len = decode_varint(&mut buf)? as usize;
353 if len > buf.len() {
354 return Err(truncated());
355 }
356 let (field, rest) = buf.split_at(len);
357 if tag == FILE_FIELD_TAG {
358 files.push(field.to_vec());
359 }
360 buf = rest;
361 }
362 WireType::Varint => {
363 decode_varint(&mut buf)?;
364 }
365 WireType::ThirtyTwoBit => {
366 if buf.len() < 4 {
367 return Err(truncated());
368 }
369 buf = &buf[4..];
370 }
371 WireType::SixtyFourBit => {
372 if buf.len() < 8 {
373 return Err(truncated());
374 }
375 buf = &buf[8..];
376 }
377 WireType::StartGroup | WireType::EndGroup => {
378 return Err(Error::InvalidFileDescriptorSet(
379 "unexpected group wire type in FileDescriptorSet".to_string(),
380 ));
381 }
382 }
383 }
384
385 Ok(files)
386}
387
388fn extract_name(
389 prefix: &str,
390 name_type: &str,
391 maybe_name: Option<&String>,
392) -> Result<String, Error> {
393 match maybe_name {
394 None => Err(Error::InvalidFileDescriptorSet(format!(
395 "missing {name_type} name"
396 ))),
397 Some(name) => {
398 if prefix.is_empty() {
399 Ok(name.to_string())
400 } else {
401 Ok(format!("{prefix}.{name}"))
402 }
403 }
404 }
405}
406
407#[derive(Debug)]
409pub enum Error {
410 DecodeError(prost::DecodeError),
412 InvalidFileDescriptorSet(String),
414}
415
416impl From<DecodeError> for Error {
417 fn from(e: DecodeError) -> Self {
418 Error::DecodeError(e)
419 }
420}
421
422impl std::error::Error for Error {}
423
424impl Display for Error {
425 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
426 match self {
427 Error::DecodeError(_) => f.write_str("error decoding FileDescriptorSet from buffer"),
428 Error::InvalidFileDescriptorSet(s) => {
429 write!(f, "invalid FileDescriptorSet - {s}")
430 }
431 }
432 }
433}