use std::collections::HashMap;
use std::sync::Arc;
use super::pool::PoolInner;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Kind {
Double,
Float,
Int32,
Int64,
Uint32,
Uint64,
Sint32,
Sint64,
Fixed32,
Fixed64,
Sfixed32,
Sfixed64,
Bool,
String,
Bytes,
Message(usize),
Enum(usize),
Group(usize),
}
impl Kind {
pub fn is_length_delimited_scalar(self) -> bool {
matches!(self, Kind::String | Kind::Bytes)
}
pub fn is_fixed64(self) -> bool {
matches!(self, Kind::Double | Kind::Fixed64 | Kind::Sfixed64)
}
pub fn is_fixed32(self) -> bool {
matches!(self, Kind::Float | Kind::Fixed32 | Kind::Sfixed32)
}
pub fn is_varint(self) -> bool {
matches!(
self,
Kind::Int32
| Kind::Int64
| Kind::Uint32
| Kind::Uint64
| Kind::Sint32
| Kind::Sint64
| Kind::Bool
| Kind::Enum(_)
)
}
pub fn is_packable(self) -> bool {
self.is_varint() || self.is_fixed32() || self.is_fixed64()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Cardinality {
Optional,
Required,
Repeated,
}
#[derive(Debug)]
pub(crate) struct MessageData {
pub full_name: String,
pub name: String,
pub file_index: usize,
pub fields: Vec<FieldData>,
pub field_by_number: HashMap<u32, usize>,
pub field_by_name: HashMap<String, usize>,
pub field_by_json_name: HashMap<String, usize>,
pub oneofs: Vec<OneofData>,
pub nested_messages: Vec<usize>,
pub nested_enums: Vec<usize>,
pub is_map_entry: bool,
}
#[derive(Debug)]
pub(crate) struct FieldData {
pub name: String,
pub full_name: String,
pub json_name: String,
pub number: u32,
pub kind: Kind,
pub cardinality: Cardinality,
pub packed: bool,
pub oneof_index: Option<usize>,
pub proto3_optional: bool,
}
#[derive(Debug)]
pub(crate) struct OneofData {
pub name: String,
pub full_name: String,
pub field_indices: Vec<usize>,
pub is_synthetic: bool,
}
#[derive(Debug)]
pub(crate) struct EnumData {
pub full_name: String,
pub name: String,
pub file_index: usize,
pub values: Vec<EnumValueData>,
pub value_by_number: HashMap<i32, usize>,
pub value_by_name: HashMap<String, usize>,
}
#[derive(Debug)]
pub(crate) struct EnumValueData {
pub name: String,
pub full_name: String,
pub number: i32,
}
#[derive(Debug)]
pub(crate) struct ServiceData {
pub full_name: String,
pub name: String,
pub file_index: usize,
pub methods: Vec<MethodData>,
}
#[derive(Debug)]
pub(crate) struct MethodData {
pub name: String,
pub full_name: String,
pub input_index: usize,
pub output_index: usize,
pub client_streaming: bool,
pub server_streaming: bool,
}
#[derive(Debug)]
pub(crate) struct FileData {
pub name: String,
pub package: String,
pub syntax: String,
pub dependencies: Vec<String>,
pub java_package: Option<String>,
pub go_package: Option<String>,
pub java_outer_classname: Option<String>,
pub deprecated: bool,
pub optimize_for: i32,
}
#[derive(Clone)]
pub struct FileDescriptor {
pub(crate) pool: Arc<PoolInner>,
pub(crate) index: usize,
}
#[derive(Clone)]
pub struct MessageDescriptor {
pub(crate) pool: Arc<PoolInner>,
pub(crate) index: usize,
}
#[derive(Clone)]
pub struct FieldDescriptor {
pub(crate) pool: Arc<PoolInner>,
pub(crate) message_index: usize,
pub(crate) field_index: usize,
}
#[derive(Clone)]
pub struct OneofDescriptor {
pub(crate) pool: Arc<PoolInner>,
pub(crate) message_index: usize,
pub(crate) oneof_index: usize,
}
#[derive(Clone)]
pub struct EnumDescriptor {
pub(crate) pool: Arc<PoolInner>,
pub(crate) index: usize,
}
#[derive(Clone)]
pub struct EnumValueDescriptor {
pub(crate) pool: Arc<PoolInner>,
pub(crate) enum_index: usize,
pub(crate) value_index: usize,
}
#[derive(Clone)]
pub struct ServiceDescriptor {
pub(crate) pool: Arc<PoolInner>,
pub(crate) index: usize,
}
#[derive(Clone)]
pub struct MethodDescriptor {
pub(crate) pool: Arc<PoolInner>,
pub(crate) service_index: usize,
pub(crate) method_index: usize,
}
impl FileDescriptor {
pub fn name(&self) -> &str {
&self.pool.files[self.index].name
}
pub fn package_name(&self) -> &str {
&self.pool.files[self.index].package
}
pub fn syntax(&self) -> &str {
&self.pool.files[self.index].syntax
}
pub fn dependencies(&self) -> impl Iterator<Item = &str> + '_ {
self.pool.files[self.index]
.dependencies
.iter()
.map(String::as_str)
}
pub fn java_package(&self) -> Option<&str> {
self.pool.files[self.index].java_package.as_deref()
}
pub fn go_package(&self) -> Option<&str> {
self.pool.files[self.index].go_package.as_deref()
}
pub fn java_outer_classname(&self) -> Option<&str> {
self.pool.files[self.index].java_outer_classname.as_deref()
}
pub fn is_deprecated(&self) -> bool {
self.pool.files[self.index].deprecated
}
pub fn optimize_for(&self) -> i32 {
self.pool.files[self.index].optimize_for
}
}
impl std::fmt::Debug for FileDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FileDescriptor")
.field("name", &self.name())
.field("package", &self.package_name())
.finish()
}
}
impl PartialEq for FileDescriptor {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.pool, &other.pool) && self.index == other.index
}
}
impl MessageDescriptor {
pub(crate) fn data(&self) -> &MessageData {
&self.pool.messages[self.index]
}
pub fn name(&self) -> &str {
&self.data().name
}
pub fn full_name(&self) -> &str {
&self.data().full_name
}
pub fn parent_file(&self) -> FileDescriptor {
FileDescriptor {
pool: Arc::clone(&self.pool),
index: self.data().file_index,
}
}
pub fn is_map_entry(&self) -> bool {
self.data().is_map_entry
}
pub fn fields(&self) -> impl ExactSizeIterator<Item = FieldDescriptor> + '_ {
let pool = Arc::clone(&self.pool);
let message_index = self.index;
(0..self.data().fields.len()).map(move |field_index| FieldDescriptor {
pool: Arc::clone(&pool),
message_index,
field_index,
})
}
pub fn get_field(&self, number: u32) -> Option<FieldDescriptor> {
self.data()
.field_by_number
.get(&number)
.map(|&field_index| FieldDescriptor {
pool: Arc::clone(&self.pool),
message_index: self.index,
field_index,
})
}
pub fn get_field_by_name(&self, name: &str) -> Option<FieldDescriptor> {
self.data()
.field_by_name
.get(name)
.map(|&field_index| FieldDescriptor {
pool: Arc::clone(&self.pool),
message_index: self.index,
field_index,
})
}
pub fn get_field_by_json_name(&self, json_name: &str) -> Option<FieldDescriptor> {
self.data()
.field_by_json_name
.get(json_name)
.map(|&field_index| FieldDescriptor {
pool: Arc::clone(&self.pool),
message_index: self.index,
field_index,
})
}
pub fn oneofs(&self) -> impl ExactSizeIterator<Item = OneofDescriptor> + '_ {
let pool = Arc::clone(&self.pool);
let message_index = self.index;
(0..self.data().oneofs.len()).map(move |oneof_index| OneofDescriptor {
pool: Arc::clone(&pool),
message_index,
oneof_index,
})
}
pub fn nested_messages(&self) -> impl ExactSizeIterator<Item = MessageDescriptor> + '_ {
let pool = Arc::clone(&self.pool);
self.data()
.nested_messages
.iter()
.map(move |&index| MessageDescriptor {
pool: Arc::clone(&pool),
index,
})
}
pub fn nested_enums(&self) -> impl ExactSizeIterator<Item = EnumDescriptor> + '_ {
let pool = Arc::clone(&self.pool);
self.data()
.nested_enums
.iter()
.map(move |&index| EnumDescriptor {
pool: Arc::clone(&pool),
index,
})
}
}
impl std::fmt::Debug for MessageDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MessageDescriptor")
.field("full_name", &self.full_name())
.finish()
}
}
impl PartialEq for MessageDescriptor {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.pool, &other.pool) && self.index == other.index
}
}
impl FieldDescriptor {
pub(crate) fn data(&self) -> &FieldData {
&self.pool.messages[self.message_index].fields[self.field_index]
}
pub fn name(&self) -> &str {
&self.data().name
}
pub fn full_name(&self) -> &str {
&self.data().full_name
}
pub fn json_name(&self) -> &str {
&self.data().json_name
}
pub fn number(&self) -> u32 {
self.data().number
}
pub fn kind(&self) -> Kind {
self.data().kind
}
pub fn cardinality(&self) -> Cardinality {
self.data().cardinality
}
pub fn is_list(&self) -> bool {
matches!(self.data().cardinality, Cardinality::Repeated) && !self.is_map()
}
pub fn is_map(&self) -> bool {
if !matches!(self.data().cardinality, Cardinality::Repeated) {
return false;
}
match self.data().kind {
Kind::Message(idx) => self.pool.messages[idx].is_map_entry,
_ => false,
}
}
pub fn is_packed(&self) -> bool {
self.data().packed
}
pub fn is_proto3_optional(&self) -> bool {
self.data().proto3_optional
}
pub fn containing_oneof(&self) -> Option<OneofDescriptor> {
self.data().oneof_index.map(|oneof_index| OneofDescriptor {
pool: Arc::clone(&self.pool),
message_index: self.message_index,
oneof_index,
})
}
pub fn parent_message(&self) -> MessageDescriptor {
MessageDescriptor {
pool: Arc::clone(&self.pool),
index: self.message_index,
}
}
pub fn message_type(&self) -> Option<MessageDescriptor> {
match self.data().kind {
Kind::Message(index) | Kind::Group(index) => Some(MessageDescriptor {
pool: Arc::clone(&self.pool),
index,
}),
_ => None,
}
}
pub fn enum_type(&self) -> Option<EnumDescriptor> {
match self.data().kind {
Kind::Enum(index) => Some(EnumDescriptor {
pool: Arc::clone(&self.pool),
index,
}),
_ => None,
}
}
pub(crate) fn map_entry_key_field(&self) -> Option<FieldDescriptor> {
match self.data().kind {
Kind::Message(idx) if self.pool.messages[idx].is_map_entry => Some(FieldDescriptor {
pool: Arc::clone(&self.pool),
message_index: idx,
field_index: self.pool.messages[idx].field_by_number.get(&1).copied()?,
}),
_ => None,
}
}
pub(crate) fn map_entry_value_field(&self) -> Option<FieldDescriptor> {
match self.data().kind {
Kind::Message(idx) if self.pool.messages[idx].is_map_entry => Some(FieldDescriptor {
pool: Arc::clone(&self.pool),
message_index: idx,
field_index: self.pool.messages[idx].field_by_number.get(&2).copied()?,
}),
_ => None,
}
}
}
impl std::fmt::Debug for FieldDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FieldDescriptor")
.field("name", &self.name())
.field("number", &self.number())
.field("kind", &self.kind())
.field("cardinality", &self.cardinality())
.finish()
}
}
impl PartialEq for FieldDescriptor {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.pool, &other.pool)
&& self.message_index == other.message_index
&& self.field_index == other.field_index
}
}
impl OneofDescriptor {
pub(crate) fn data(&self) -> &OneofData {
&self.pool.messages[self.message_index].oneofs[self.oneof_index]
}
pub fn name(&self) -> &str {
&self.data().name
}
pub fn full_name(&self) -> &str {
&self.data().full_name
}
pub fn is_synthetic(&self) -> bool {
self.data().is_synthetic
}
pub fn fields(&self) -> impl ExactSizeIterator<Item = FieldDescriptor> + '_ {
let pool = Arc::clone(&self.pool);
let message_index = self.message_index;
self.data()
.field_indices
.iter()
.map(move |&field_index| FieldDescriptor {
pool: Arc::clone(&pool),
message_index,
field_index,
})
}
}
impl std::fmt::Debug for OneofDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OneofDescriptor")
.field("full_name", &self.full_name())
.finish()
}
}
impl PartialEq for OneofDescriptor {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.pool, &other.pool)
&& self.message_index == other.message_index
&& self.oneof_index == other.oneof_index
}
}
impl EnumDescriptor {
pub(crate) fn data(&self) -> &EnumData {
&self.pool.enums[self.index]
}
pub fn name(&self) -> &str {
&self.data().name
}
pub fn full_name(&self) -> &str {
&self.data().full_name
}
pub fn parent_file(&self) -> FileDescriptor {
FileDescriptor {
pool: Arc::clone(&self.pool),
index: self.data().file_index,
}
}
pub fn values(&self) -> impl ExactSizeIterator<Item = EnumValueDescriptor> + '_ {
let pool = Arc::clone(&self.pool);
let enum_index = self.index;
(0..self.data().values.len()).map(move |value_index| EnumValueDescriptor {
pool: Arc::clone(&pool),
enum_index,
value_index,
})
}
pub fn get_value(&self, number: i32) -> Option<EnumValueDescriptor> {
self.data()
.value_by_number
.get(&number)
.map(|&value_index| EnumValueDescriptor {
pool: Arc::clone(&self.pool),
enum_index: self.index,
value_index,
})
}
pub fn get_value_by_name(&self, name: &str) -> Option<EnumValueDescriptor> {
self.data()
.value_by_name
.get(name)
.map(|&value_index| EnumValueDescriptor {
pool: Arc::clone(&self.pool),
enum_index: self.index,
value_index,
})
}
pub fn default_value(&self) -> Option<EnumValueDescriptor> {
self.get_value(0).or_else(|| {
if self.data().values.is_empty() {
None
} else {
Some(EnumValueDescriptor {
pool: Arc::clone(&self.pool),
enum_index: self.index,
value_index: 0,
})
}
})
}
}
impl std::fmt::Debug for EnumDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EnumDescriptor")
.field("full_name", &self.full_name())
.finish()
}
}
impl PartialEq for EnumDescriptor {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.pool, &other.pool) && self.index == other.index
}
}
impl EnumValueDescriptor {
pub(crate) fn data(&self) -> &EnumValueData {
&self.pool.enums[self.enum_index].values[self.value_index]
}
pub fn name(&self) -> &str {
&self.data().name
}
pub fn full_name(&self) -> &str {
&self.data().full_name
}
pub fn number(&self) -> i32 {
self.data().number
}
pub fn parent_enum(&self) -> EnumDescriptor {
EnumDescriptor {
pool: Arc::clone(&self.pool),
index: self.enum_index,
}
}
}
impl std::fmt::Debug for EnumValueDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EnumValueDescriptor")
.field("full_name", &self.full_name())
.field("number", &self.number())
.finish()
}
}
impl PartialEq for EnumValueDescriptor {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.pool, &other.pool)
&& self.enum_index == other.enum_index
&& self.value_index == other.value_index
}
}
impl ServiceDescriptor {
pub(crate) fn data(&self) -> &ServiceData {
&self.pool.services[self.index]
}
pub fn name(&self) -> &str {
&self.data().name
}
pub fn full_name(&self) -> &str {
&self.data().full_name
}
pub fn parent_file(&self) -> FileDescriptor {
FileDescriptor {
pool: Arc::clone(&self.pool),
index: self.data().file_index,
}
}
pub fn methods(&self) -> impl ExactSizeIterator<Item = MethodDescriptor> + '_ {
let pool = Arc::clone(&self.pool);
let service_index = self.index;
(0..self.data().methods.len()).map(move |method_index| MethodDescriptor {
pool: Arc::clone(&pool),
service_index,
method_index,
})
}
}
impl std::fmt::Debug for ServiceDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ServiceDescriptor")
.field("full_name", &self.full_name())
.finish()
}
}
impl PartialEq for ServiceDescriptor {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.pool, &other.pool) && self.index == other.index
}
}
impl MethodDescriptor {
pub(crate) fn data(&self) -> &MethodData {
&self.pool.services[self.service_index].methods[self.method_index]
}
pub fn name(&self) -> &str {
&self.data().name
}
pub fn full_name(&self) -> &str {
&self.data().full_name
}
pub fn input(&self) -> MessageDescriptor {
MessageDescriptor {
pool: Arc::clone(&self.pool),
index: self.data().input_index,
}
}
pub fn output(&self) -> MessageDescriptor {
MessageDescriptor {
pool: Arc::clone(&self.pool),
index: self.data().output_index,
}
}
pub fn is_client_streaming(&self) -> bool {
self.data().client_streaming
}
pub fn is_server_streaming(&self) -> bool {
self.data().server_streaming
}
pub fn parent_service(&self) -> ServiceDescriptor {
ServiceDescriptor {
pool: Arc::clone(&self.pool),
index: self.service_index,
}
}
}
impl std::fmt::Debug for MethodDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MethodDescriptor")
.field("full_name", &self.full_name())
.field("client_streaming", &self.is_client_streaming())
.field("server_streaming", &self.is_server_streaming())
.finish()
}
}
impl PartialEq for MethodDescriptor {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.pool, &other.pool)
&& self.service_index == other.service_index
&& self.method_index == other.method_index
}
}