use prost::{Message, Name};
use crate::extensions::registry::ExtensionError;
#[derive(Debug, Clone, PartialEq)]
pub struct Any {
pub type_url: String,
pub value: Vec<u8>,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct AnyRef<'a> {
pub type_url: &'a str,
pub value: &'a [u8],
}
impl<'a> AnyRef<'a> {
pub fn new(type_url: &'a str, value: &'a [u8]) -> Self {
Self { type_url, value }
}
pub fn decode<M>(&self) -> Result<M, ExtensionError>
where
M: prost::Message + Name + Default,
{
if self.type_url != M::type_url() {
return Err(ExtensionError::TypeUrlMismatch {
expected: M::type_url(),
actual: self.type_url.to_string(),
});
}
let message = M::decode(self.value).map_err(ExtensionError::DecodeFailed)?;
Ok(message)
}
}
impl<'a> From<&'a Any> for AnyRef<'a> {
fn from(any: &'a Any) -> Self {
Self {
type_url: &any.type_url,
value: &any.value,
}
}
}
impl<'a> From<&'a prost_types::Any> for AnyRef<'a> {
fn from(any: &'a prost_types::Any) -> Self {
Self {
type_url: &any.type_url,
value: &any.value,
}
}
}
#[cfg(feature = "serde")]
impl<'a> From<&'a pbjson_types::Any> for AnyRef<'a> {
fn from(any: &'a pbjson_types::Any) -> Self {
Self {
type_url: &any.type_url,
value: &any.value,
}
}
}
impl Any {
pub fn new(type_url: String, value: Vec<u8>) -> Self {
Self { type_url, value }
}
pub fn as_ref(&self) -> AnyRef<'_> {
AnyRef::from(self)
}
pub fn decode<M>(&self) -> Result<M, ExtensionError>
where
M: prost::Message + Name + Default,
{
self.as_ref().decode()
}
pub fn encode<M: Message + Name + Default>(message: &M) -> Result<Self, ExtensionError> {
let mut buf = Vec::new();
message
.encode(&mut buf)
.map_err(ExtensionError::EncodeFailed)?;
Ok(Any {
type_url: M::type_url(),
value: buf,
})
}
}
impl From<prost_types::Any> for Any {
fn from(any: prost_types::Any) -> Self {
Self {
type_url: any.type_url,
value: any.value.to_vec(),
}
}
}
impl From<Any> for prost_types::Any {
fn from(any: Any) -> Self {
Self {
type_url: any.type_url,
value: any.value,
}
}
}
#[cfg(feature = "serde")]
impl From<pbjson_types::Any> for Any {
fn from(any: pbjson_types::Any) -> Self {
Self {
type_url: any.type_url,
value: any.value.to_vec(),
}
}
}
#[cfg(feature = "serde")]
impl From<Any> for pbjson_types::Any {
fn from(any: Any) -> Self {
Self {
type_url: any.type_url,
value: any.value.into(),
}
}
}