use cosmwasm_std::CosmosMsg;
pub use prost::Message;
use prost::{DecodeError, EncodeError};
use prost_types::Any;
use std::str::FromStr;
pub trait TypeUrl: Message {
const TYPE_URL: &'static str;
}
pub trait MessageExt: Message {
fn from_any(any: &Any) -> Result<Self, DecodeError>
where
Self: Default + Sized + TypeUrl,
{
if any.type_url == Self::TYPE_URL {
Ok(Self::decode(&*any.value)?)
} else {
let mut err = DecodeError::new(format!(
"expected type URL: \"{}\" (got: \"{}\")",
Self::TYPE_URL,
&any.type_url
));
err.push("unexpected type URL", "type_url");
Err(err)
}
}
fn to_any(&self) -> Result<Any, EncodeError>
where
Self: TypeUrl,
{
self.to_bytes().map(|bytes| Any {
type_url: Self::TYPE_URL.to_owned(),
value: bytes,
})
}
fn to_bytes(&self) -> Result<Vec<u8>, EncodeError>;
fn to_stargate_msg(&self) -> Result<CosmosMsg, EncodeError>
where
Self: TypeUrl,
{
Ok(CosmosMsg::Stargate {
type_url: Self::TYPE_URL.to_string(),
value: self.to_bytes()?.into(),
})
}
fn type_url(&self) -> String
where
Self: TypeUrl,
{
Self::TYPE_URL.to_string()
}
}
impl<M> MessageExt for M
where
M: prost::Message,
{
fn to_bytes(&self) -> Result<Vec<u8>, EncodeError> {
let mut bytes = Vec::new();
Message::encode(self, &mut bytes)?;
Ok(bytes)
}
}
pub trait ParseOptional: AsRef<str> {
fn parse_optional<T: FromStr>(&self) -> Result<Option<T>, T::Err> {
if self.as_ref().is_empty() {
Ok(None)
} else {
Ok(Some(self.as_ref().parse()?))
}
}
}
impl ParseOptional for str {}
impl ParseOptional for String {}