protobuf/reflect/enums/
mod.rsuse std::any::TypeId;
use std::fmt;
use std::fmt::Formatter;
use std::hash::Hash;
use crate::descriptor::EnumDescriptorProto;
use crate::descriptor::EnumValueDescriptorProto;
use crate::enums::Enum;
use crate::reflect::enums::generated::GeneratedEnumDescriptor;
use crate::reflect::file::index::EnumIndices;
use crate::reflect::file::FileDescriptorImpl;
use crate::reflect::FileDescriptor;
use crate::reflect::MessageDescriptor;
use crate::EnumFull;
pub(crate) mod generated;
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct EnumValueDescriptor {
pub(crate) enum_descriptor: EnumDescriptor,
pub(crate) index: usize,
}
fn _assert_send_sync() {
fn _assert_send_sync<T: Send + Sync>() {}
_assert_send_sync::<EnumValueDescriptor>();
}
impl fmt::Debug for EnumValueDescriptor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("EnumValueDescriptor")
.field("enum_descriptor", &self.enum_descriptor)
.field("name", &self.name())
.finish()
}
}
impl fmt::Display for EnumValueDescriptor {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}.{}", self.enum_descriptor, self.name())
}
}
impl EnumValueDescriptor {
pub(crate) fn new(enum_descriptor: EnumDescriptor, index: usize) -> EnumValueDescriptor {
EnumValueDescriptor {
enum_descriptor,
index,
}
}
pub fn proto(&self) -> &EnumValueDescriptorProto {
&self.enum_descriptor.proto().value[self.index]
}
pub fn name(&self) -> &str {
self.proto().name()
}
pub fn full_name(&self) -> String {
self.to_string()
}
pub fn value(&self) -> i32 {
self.proto().number()
}
pub fn enum_descriptor(&self) -> &EnumDescriptor {
&self.enum_descriptor
}
pub fn cast<E: EnumFull>(&self) -> Option<E> {
if self.enum_descriptor != E::enum_descriptor() {
return None;
}
E::from_i32(self.value())
}
}
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct EnumDescriptor {
file_descriptor: FileDescriptor,
index: usize,
}
impl fmt::Display for EnumDescriptor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.full_name())
}
}
impl fmt::Debug for EnumDescriptor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("EnumDescriptor")
.field("full_name", &self.full_name())
.finish_non_exhaustive()
}
}
impl EnumDescriptor {
pub(crate) fn new(file_descriptor: FileDescriptor, index: usize) -> EnumDescriptor {
EnumDescriptor {
file_descriptor,
index,
}
}
fn get_impl(&self) -> EnumDescriptorImplRef {
match &self.file_descriptor.imp {
FileDescriptorImpl::Generated(g) => {
EnumDescriptorImplRef::Generated(&g.enums[self.index])
}
FileDescriptorImpl::Dynamic(..) => EnumDescriptorImplRef::Dynamic,
}
}
pub fn proto(&self) -> &EnumDescriptorProto {
&self.index_entry().proto
}
pub fn name(&self) -> &str {
self.proto().name()
}
fn index_entry(&self) -> &EnumIndices {
self.file_descriptor.enum_indices(self.index)
}
pub fn full_name(&self) -> &str {
&self.index_entry().full_name
}
pub fn name_to_package(&self) -> &str {
&self.index_entry().name_to_package
}
pub fn for_type<E: EnumFull>() -> EnumDescriptor {
E::enum_descriptor()
}
pub fn enclosing_message(&self) -> Option<MessageDescriptor> {
self.index_entry()
.enclosing_message
.map(|i| MessageDescriptor::new(self.file_descriptor.clone(), i))
}
pub fn values<'a>(&'a self) -> impl Iterator<Item = EnumValueDescriptor> + 'a {
let value_len = self.proto().value.len();
(0..value_len).map(move |index| EnumValueDescriptor {
enum_descriptor: self.clone(),
index,
})
}
pub fn value_by_name(&self, name: &str) -> Option<EnumValueDescriptor> {
let index = *self.file_descriptor.common().enums[self.index]
.index_by_name
.get(name)?;
Some(EnumValueDescriptor {
enum_descriptor: self.clone(),
index,
})
}
pub fn value_by_number(&self, number: i32) -> Option<EnumValueDescriptor> {
let index = *self.file_descriptor.common().enums[self.index]
.index_by_number
.get(&number)?;
Some(self.value_by_index(index))
}
pub fn value_by_index(&self, index: usize) -> EnumValueDescriptor {
assert!(index < self.proto().value.len());
EnumValueDescriptor {
enum_descriptor: self.clone(),
index,
}
}
pub fn default_value(&self) -> EnumValueDescriptor {
EnumValueDescriptor {
enum_descriptor: self.clone(),
index: 0,
}
}
pub fn value_by_number_or_default(&self, number: i32) -> EnumValueDescriptor {
self.value_by_number(number)
.unwrap_or_else(|| self.default_value())
}
pub fn is<E: Enum>(&self) -> bool {
match self.get_impl() {
EnumDescriptorImplRef::Generated(g) => g.type_id == TypeId::of::<E>(),
EnumDescriptorImplRef::Dynamic => false,
}
}
}
enum EnumDescriptorImplRef {
Generated(&'static GeneratedEnumDescriptor),
Dynamic,
}
#[cfg(test)]
mod test {
use crate::descriptor::field_descriptor_proto::Label;
use crate::descriptor::field_descriptor_proto::Type;
use crate::descriptor::FieldDescriptorProto;
use crate::well_known_types::struct_::NullValue;
use crate::EnumFull;
use crate::MessageFull;
#[test]
#[cfg_attr(miri, ignore)] fn enclosing_message() {
assert_eq!(
Some(FieldDescriptorProto::descriptor()),
Type::enum_descriptor().enclosing_message()
);
assert_eq!(None, NullValue::enum_descriptor().enclosing_message());
}
#[test]
#[cfg_attr(miri, ignore)] fn to_string() {
assert_eq!(
"google.protobuf.FieldDescriptorProto.Label",
Label::enum_descriptor().to_string()
);
assert_eq!(
"google.protobuf.FieldDescriptorProto.Label",
Label::enum_descriptor().full_name()
);
assert_eq!(
"google.protobuf.FieldDescriptorProto.Label.LABEL_REPEATED",
Label::LABEL_REPEATED.descriptor().to_string()
);
assert_eq!(
"google.protobuf.FieldDescriptorProto.Label.LABEL_REPEATED",
Label::LABEL_REPEATED.descriptor().full_name()
);
}
}