informalsystems_malachitebft_proto/
lib.rs1use 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}