use std::sync::RwLock;
pub use once_cell::sync::Lazy;
pub use prost;
use prost::Message as _;
pub use prost_reflect;
use prost_reflect::prost_types;
pub use serde;
static POOL: Lazy<RwLock<prost_reflect::DescriptorPool>> = Lazy::new(RwLock::default);
#[derive(Debug)]
pub struct Descriptor(());
impl Descriptor {
pub fn new(_dependencies: &[&'static Self], descriptor_bytes: &[u8]) -> Self {
let descriptor = prost_types::FileDescriptorSet::decode(descriptor_bytes).unwrap();
let pool = &mut POOL.write().unwrap();
Self::load(pool, descriptor).expect("failed loading descriptor into global pool");
Self(())
}
fn load(
pool: &mut prost_reflect::DescriptorPool,
descriptor: prost_types::FileDescriptorSet,
) -> anyhow::Result<()> {
let pool_has_all_files = descriptor
.file
.iter()
.all(|file| pool.get_file_by_name(file.name()).is_some());
if pool_has_all_files {
return Ok(());
}
pool.add_file_descriptor_set(descriptor)?;
Ok(())
}
pub fn get_message_by_name(&self, name: &str) -> Option<prost_reflect::MessageDescriptor> {
POOL.read().unwrap().get_message_by_name(name)
}
}
#[macro_export]
macro_rules! declare_descriptor {
($name:ident => $descriptor_path:expr, $($rust_deps:path),*) => {
pub static $name: $crate::build::Lazy<$crate::build::Descriptor> =
$crate::build::Lazy::new(|| {
$crate::build::Descriptor::new(
&[$({ use $rust_deps as dep; &dep::DESCRIPTOR }),*],
::std::include_bytes!($descriptor_path),
)
});
}
}
#[macro_export]
macro_rules! impl_reflect_message {
($ty:ty, $descriptor:expr, $proto_name:expr) => {
impl $crate::build::prost_reflect::ReflectMessage for $ty {
fn descriptor(&self) -> $crate::build::prost_reflect::MessageDescriptor {
static INIT: $crate::build::Lazy<$crate::build::prost_reflect::MessageDescriptor> =
$crate::build::Lazy::new(|| {
$crate::build::Descriptor::get_message_by_name($descriptor, $proto_name)
.unwrap()
});
INIT.clone()
}
}
};
}
#[macro_export]
macro_rules! impl_serde_serialize {
($ty:ty) => {
impl $crate::build::serde::Serialize for $ty {
fn serialize<S: $crate::build::serde::Serializer>(
&self,
s: S,
) -> Result<S::Ok, S::Error> {
$crate::serde_serialize(self, s)
}
}
};
}
#[macro_export]
macro_rules! impl_serde_deserialize {
($ty:ty) => {
impl<'de> $crate::build::serde::Deserialize<'de> for $ty {
fn deserialize<D: $crate::build::serde::Deserializer<'de>>(
d: D,
) -> Result<Self, D::Error> {
$crate::serde_deserialize(d)
}
}
};
}
pub use declare_descriptor;
pub use impl_reflect_message;
pub use impl_serde_deserialize;
pub use impl_serde_serialize;