Skip to main content

buffa_reflect/
file.rs

1//! [`FileDescriptor`] — handle to one `FileDescriptorProto` in a pool.
2
3use buffa_descriptor::generated::descriptor::FileDescriptorProto;
4
5use crate::{
6    enumeration::EnumDescriptor,
7    message::MessageDescriptor,
8    pool::{DescriptorPool, FileIndex},
9};
10
11/// Handle to a single proto file inside a [`DescriptorPool`].
12#[derive(Clone, Debug)]
13pub struct FileDescriptor {
14    pub(crate) pool: DescriptorPool,
15    pub(crate) index: FileIndex,
16}
17
18impl FileDescriptor {
19    /// File name as it appears in the descriptor (e.g.
20    /// `acme/api/v1/user.proto`).
21    #[must_use]
22    pub fn name(&self) -> &str {
23        let entry = &self.pool.inner.files[self.index as usize];
24        entry.proto.name.as_deref().unwrap_or("")
25    }
26
27    /// Proto package declared by the file (`acme.api.v1` for the example
28    /// above), or the empty string if the file declares none.
29    #[must_use]
30    pub fn package(&self) -> &str {
31        let entry = &self.pool.inner.files[self.index as usize];
32        entry.proto.package.as_deref().unwrap_or("")
33    }
34
35    /// Proto syntax (`proto2`, `proto3`, or `editions`).
36    ///
37    /// Defaults to `"proto2"` when unset, matching the protoc convention.
38    #[must_use]
39    pub fn syntax(&self) -> &str {
40        let entry = &self.pool.inner.files[self.index as usize];
41        entry.proto.syntax.as_deref().unwrap_or("proto2")
42    }
43
44    /// Top-level messages declared in this file.
45    pub fn messages(&self) -> impl ExactSizeIterator<Item = MessageDescriptor> + '_ {
46        let pool = self.pool.clone();
47        let entry = &self.pool.inner.files[self.index as usize];
48        entry
49            .messages
50            .clone()
51            .into_iter()
52            .map(move |idx| MessageDescriptor {
53                pool: pool.clone(),
54                index: idx,
55            })
56    }
57
58    /// Top-level enums declared in this file.
59    pub fn enums(&self) -> impl ExactSizeIterator<Item = EnumDescriptor> + '_ {
60        let pool = self.pool.clone();
61        let entry = &self.pool.inner.files[self.index as usize];
62        entry
63            .enums
64            .clone()
65            .into_iter()
66            .map(move |idx| EnumDescriptor {
67                pool: pool.clone(),
68                index: idx,
69            })
70    }
71
72    /// Owning [`DescriptorPool`].
73    #[must_use]
74    pub fn parent_pool(&self) -> DescriptorPool {
75        self.pool.clone()
76    }
77
78    /// Raw [`FileDescriptorProto`] for advanced use.
79    #[must_use]
80    pub fn descriptor_proto(&self) -> &FileDescriptorProto {
81        &self.pool.inner.files[self.index as usize].proto
82    }
83}
84
85impl PartialEq for FileDescriptor {
86    fn eq(&self, other: &Self) -> bool {
87        std::sync::Arc::ptr_eq(&self.pool.inner, &other.pool.inner) && self.index == other.index
88    }
89}
90
91impl Eq for FileDescriptor {}