informalsystems_malachitebft_proto/
lib.rs

1use std::convert::Infallible;
2
3use prost::bytes::Bytes;
4use prost_types::Any;
5use thiserror::Error;
6
7use prost::{DecodeError, EncodeError, Message, Name};
8
9#[derive(Debug, Error)]
10pub enum Error {
11    #[error("Failed to decode Protobuf message")]
12    Decode(#[from] DecodeError),
13
14    #[error("Failed to encode Protobuf message")]
15    Encode(#[from] EncodeError),
16
17    #[error("Unable to decode Protobuf message `{type_url}`: missing field `{field}`")]
18    MissingField {
19        type_url: String,
20        field: &'static str,
21    },
22
23    #[error("Unable to decode Protobuf message `{type_url}`: invalid data in field `{field}`")]
24    InvalidData {
25        type_url: String,
26        field: &'static str,
27    },
28
29    #[error("Unknown message type: `{type_url}`")]
30    UnknownMessageType { type_url: String },
31
32    #[error("{0}")]
33    Other(String),
34}
35
36impl Error {
37    pub fn missing_field<N: prost::Name>(field: &'static str) -> Self {
38        let type_url = N::full_name();
39        Self::MissingField { type_url, field }
40    }
41
42    pub fn invalid_data<N: prost::Name>(field: &'static str) -> Self {
43        let type_url = N::full_name();
44        Self::InvalidData { type_url, field }
45    }
46}
47
48impl From<String> for Error {
49    fn from(s: String) -> Self {
50        Self::Other(s)
51    }
52}
53
54impl From<Infallible> for Error {
55    fn from(_: Infallible) -> Self {
56        unreachable!()
57    }
58}
59
60pub trait Protobuf: Sized {
61    type Proto: Name + Message + Default;
62
63    fn from_proto(proto: Self::Proto) -> Result<Self, Error>;
64
65    fn to_proto(&self) -> Result<Self::Proto, Error>;
66
67    fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
68        let proto = Self::Proto::decode(bytes)?;
69        let result = Self::from_proto(proto)?;
70        Ok(result)
71    }
72
73    fn to_bytes(&self) -> Result<Bytes, Error> {
74        let proto = self.to_proto()?;
75        Ok(Bytes::from(proto.encode_to_vec()))
76    }
77
78    fn from_any(any: &Any) -> Result<Self, Error> {
79        Self::from_proto(any.to_msg::<Self::Proto>()?)
80    }
81
82    fn to_any(&self) -> Result<Any, Error> {
83        Ok(Any::from_msg(&self.to_proto()?)?)
84    }
85}