use buffa_descriptor::generated::descriptor::FieldDescriptorProto;
use crate::{
enumeration::EnumDescriptor,
message::MessageDescriptor,
oneof::OneofDescriptor,
pool::{DescriptorPool, KindRef, MessageIndex},
};
#[derive(Clone, Debug)]
pub struct FieldDescriptor {
pub(crate) pool: DescriptorPool,
pub(crate) message: MessageIndex,
pub(crate) index: u32,
}
impl FieldDescriptor {
fn entry(&self) -> &crate::pool::FieldEntry {
&self.pool.inner.messages[self.message as usize].fields[self.index as usize]
}
#[must_use]
pub fn name(&self) -> &str {
&self.entry().name
}
#[must_use]
pub fn full_name(&self) -> &str {
&self.entry().full_name
}
#[must_use]
pub fn json_name(&self) -> &str {
&self.entry().json_name
}
#[must_use]
pub fn number(&self) -> u32 {
self.entry().number
}
#[must_use]
pub fn kind(&self) -> Kind {
match self.entry().kind {
KindRef::Double => Kind::Double,
KindRef::Float => Kind::Float,
KindRef::Int32 => Kind::Int32,
KindRef::Int64 => Kind::Int64,
KindRef::Uint32 => Kind::Uint32,
KindRef::Uint64 => Kind::Uint64,
KindRef::Sint32 => Kind::Sint32,
KindRef::Sint64 => Kind::Sint64,
KindRef::Fixed32 => Kind::Fixed32,
KindRef::Fixed64 => Kind::Fixed64,
KindRef::Sfixed32 => Kind::Sfixed32,
KindRef::Sfixed64 => Kind::Sfixed64,
KindRef::Bool => Kind::Bool,
KindRef::String => Kind::String,
KindRef::Bytes => Kind::Bytes,
KindRef::Message(idx) => Kind::Message(MessageDescriptor {
pool: self.pool.clone(),
index: idx,
}),
KindRef::Enum(idx) => Kind::Enum(EnumDescriptor {
pool: self.pool.clone(),
index: idx,
}),
}
}
#[must_use]
pub fn cardinality(&self) -> Cardinality {
self.entry().cardinality
}
#[must_use]
pub fn supports_presence(&self) -> bool {
self.entry().supports_presence
}
#[must_use]
pub fn is_packed(&self) -> bool {
self.entry().is_packed
}
#[must_use]
pub fn is_packable(&self) -> bool {
matches!(
self.entry().kind,
KindRef::Double
| KindRef::Float
| KindRef::Int32
| KindRef::Int64
| KindRef::Uint32
| KindRef::Uint64
| KindRef::Sint32
| KindRef::Sint64
| KindRef::Fixed32
| KindRef::Fixed64
| KindRef::Sfixed32
| KindRef::Sfixed64
| KindRef::Bool
| KindRef::Enum(_)
)
}
#[must_use]
pub fn is_list(&self) -> bool {
matches!(self.entry().cardinality, Cardinality::Repeated) && !self.is_map()
}
#[cfg(feature = "dynamic")]
#[must_use]
pub fn parsed_default_value(&self) -> Option<crate::dynamic::Value> {
self.entry().parsed_default.clone()
}
#[must_use]
pub fn is_map(&self) -> bool {
match self.entry().kind {
KindRef::Message(idx) => self.pool.inner.messages[idx as usize].is_map_entry,
_ => false,
}
}
#[must_use]
pub fn containing_oneof(&self) -> Option<OneofDescriptor> {
self.entry().oneof_index.map(|oi| OneofDescriptor {
pool: self.pool.clone(),
message: self.message,
index: oi,
})
}
#[must_use]
pub fn parent_message(&self) -> MessageDescriptor {
MessageDescriptor {
pool: self.pool.clone(),
index: self.message,
}
}
#[must_use]
pub fn descriptor_proto(&self) -> &FieldDescriptorProto {
let msg_entry = &self.pool.inner.messages[self.message as usize];
let file = &self.pool.inner.files[msg_entry.file as usize];
let msg_proto =
crate::pool_build::resolve_message_proto(&file.proto, &msg_entry.proto_path);
&msg_proto.field[self.entry().proto_field_index as usize]
}
}
impl PartialEq for FieldDescriptor {
fn eq(&self, other: &Self) -> bool {
std::sync::Arc::ptr_eq(&self.pool.inner, &other.pool.inner)
&& self.message == other.message
&& self.index == other.index
}
}
impl Eq for FieldDescriptor {}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum Kind {
Double,
Float,
Int32,
Int64,
Uint32,
Uint64,
Sint32,
Sint64,
Fixed32,
Fixed64,
Sfixed32,
Sfixed64,
Bool,
String,
Bytes,
Message(MessageDescriptor),
Enum(EnumDescriptor),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum Cardinality {
Optional,
Required,
Repeated,
}