muta_protocol/codec/
mod.rs

1// TODO: change Vec<u8> to Bytes
2// pin: https://github.com/danburkert/prost/pull/190
3
4#[macro_use]
5mod r#macro;
6pub mod epoch;
7pub mod primitive;
8pub mod receipt;
9#[cfg(test)]
10mod tests;
11pub mod transaction;
12
13use std::error::Error;
14
15use async_trait::async_trait;
16use bytes::Bytes;
17use derive_more::{Display, From};
18
19use crate::{ProtocolError, ProtocolErrorKind, ProtocolResult};
20
21pub use serde::{Deserialize, Serialize};
22
23#[async_trait]
24pub trait ProtocolCodec: Sized + Send + ProtocolCodecSync {
25    // Note: We take mut reference so that it can be pinned. This removes Sync
26    // requirement.
27    async fn encode(&mut self) -> ProtocolResult<Bytes>;
28
29    async fn decode<B: Into<Bytes> + Send>(bytes: B) -> ProtocolResult<Self>;
30}
31
32// Sync version is still useful in some cases, for example, use in Stream.
33// This also work around #[async_trait] problem inside macro
34#[doc(hidden)]
35pub trait ProtocolCodecSync: Sized + Send {
36    fn encode_sync(&self) -> ProtocolResult<Bytes>;
37
38    fn decode_sync(bytes: Bytes) -> ProtocolResult<Self>;
39}
40
41#[async_trait]
42impl<T: ProtocolCodecSync + 'static> ProtocolCodec for T {
43    async fn encode(&mut self) -> ProtocolResult<Bytes> {
44        <T as ProtocolCodecSync>::encode_sync(self)
45    }
46
47    async fn decode<B: Into<Bytes> + Send>(bytes: B) -> ProtocolResult<Self> {
48        let bytes: Bytes = bytes.into();
49
50        <T as ProtocolCodecSync>::decode_sync(bytes)
51    }
52}
53
54impl ProtocolCodecSync for Bytes {
55    fn encode_sync(&self) -> ProtocolResult<Bytes> {
56        Ok(self.clone())
57    }
58
59    fn decode_sync(bytes: Bytes) -> ProtocolResult<Self> {
60        Ok(bytes)
61    }
62}
63
64#[derive(Debug, From, Display)]
65pub enum CodecError {
66    #[display(fmt = "prost encode: {}", _0)]
67    ProtobufEncode(prost::EncodeError),
68
69    #[display(fmt = "prost decode: {}", _0)]
70    ProtobufDecode(prost::DecodeError),
71
72    #[display(fmt = "{} missing field {}", r#type, field)]
73    MissingField {
74        r#type: &'static str,
75        field:  &'static str,
76    },
77
78    #[display(fmt = "invalid contract type {}", _0)]
79    InvalidContractType(i32),
80
81    #[display(fmt = "wrong bytes length: {{ expect: {}, got: {} }}", expect, real)]
82    WrongBytesLength { expect: usize, real: usize },
83
84    #[display(fmt = "from string {}", _0)]
85    FromStringUtf8(std::string::FromUtf8Error),
86}
87
88impl Error for CodecError {}
89
90// TODO: derive macro
91impl From<CodecError> for ProtocolError {
92    fn from(err: CodecError) -> ProtocolError {
93        ProtocolError::new(ProtocolErrorKind::Codec, Box::new(err))
94    }
95}