juno_rust_proto/
traits.rs1pub use prost::Message;
4
5use crate::Any;
6use prost::{DecodeError, EncodeError};
7use std::str::FromStr;
8
9pub trait TypeUrl: Message {
11 const TYPE_URL: &'static str;
13}
14
15pub trait MessageExt: Message {
17 fn from_any(any: &Any) -> Result<Self, DecodeError>
19 where
20 Self: Default + Sized + TypeUrl,
21 {
22 if any.type_url == Self::TYPE_URL {
23 Ok(Self::decode(&*any.value)?)
24 } else {
25 let mut err = DecodeError::new(format!(
26 "expected type URL: \"{}\" (got: \"{}\")",
27 Self::TYPE_URL,
28 &any.type_url
29 ));
30 err.push("unexpected type URL", "type_url");
31 Err(err)
32 }
33 }
34
35 fn to_any(&self) -> Result<Any, EncodeError>
37 where
38 Self: TypeUrl,
39 {
40 self.to_bytes().map(|bytes| Any {
41 type_url: Self::TYPE_URL.to_owned(),
42 value: bytes,
43 })
44 }
45
46 fn to_bytes(&self) -> Result<Vec<u8>, EncodeError>;
48}
49
50impl<M> MessageExt for M
51where
52 M: prost::Message,
53{
54 fn to_bytes(&self) -> Result<Vec<u8>, EncodeError> {
55 let mut bytes = Vec::new();
56 Message::encode(self, &mut bytes)?;
57 Ok(bytes)
58 }
59}
60
61pub trait ParseOptional: AsRef<str> {
65 fn parse_optional<T: FromStr>(&self) -> Result<Option<T>, T::Err> {
67 if self.as_ref().is_empty() {
68 Ok(None)
69 } else {
70 Ok(Some(self.as_ref().parse()?))
71 }
72 }
73}
74
75impl ParseOptional for str {}
76impl ParseOptional for String {}