codee/binary/
from_to_bytes.rs

1use crate::{Decoder, Encoder};
2use thiserror::Error;
3
4/// A binary codec that uses rust own binary encoding functions to encode and decode data.
5/// This can be used if you want to encode only primitives and don't want to rely on third party
6/// crates like `bincode` or `rmp-serde`. If you have more complex data check out
7/// [`BincodeSerdeCodec`] or [`MsgpackSerdeCodec`].
8pub struct FromToBytesCodec;
9
10#[derive(Error, Debug)]
11pub enum FromToBytesCodecError {
12    #[error("failed to convert byte slice to byte array")]
13    InvalidByteSlice(#[from] std::array::TryFromSliceError),
14
15    #[error("failed to convert byte array to string")]
16    InvalidString(#[from] std::string::FromUtf8Error),
17}
18
19macro_rules! impl_bin_codec_for_number {
20    ($num:ty) => {
21        impl Encoder<$num> for FromToBytesCodec {
22            type Error = ();
23            type Encoded = Vec<u8>;
24
25            fn encode(val: &$num) -> Result<Self::Encoded, Self::Error> {
26                Ok(val.to_be_bytes().to_vec())
27            }
28        }
29
30        impl Decoder<$num> for FromToBytesCodec {
31            type Error = FromToBytesCodecError;
32            type Encoded = [u8];
33
34            fn decode(val: &Self::Encoded) -> Result<$num, Self::Error> {
35                Ok(<$num>::from_be_bytes(val.try_into()?))
36            }
37        }
38    };
39}
40
41impl_bin_codec_for_number!(i8);
42impl_bin_codec_for_number!(u8);
43
44impl_bin_codec_for_number!(i16);
45impl_bin_codec_for_number!(u16);
46
47impl_bin_codec_for_number!(i32);
48impl_bin_codec_for_number!(u32);
49
50impl_bin_codec_for_number!(i64);
51impl_bin_codec_for_number!(u64);
52
53impl_bin_codec_for_number!(i128);
54impl_bin_codec_for_number!(u128);
55
56impl_bin_codec_for_number!(isize);
57impl_bin_codec_for_number!(usize);
58
59impl_bin_codec_for_number!(f32);
60impl_bin_codec_for_number!(f64);
61
62impl Encoder<bool> for FromToBytesCodec {
63    type Error = ();
64    type Encoded = Vec<u8>;
65
66    fn encode(val: &bool) -> Result<Self::Encoded, Self::Error> {
67        let num: u8 = if *val { 1 } else { 0 };
68        Self::encode(&num)
69    }
70}
71
72impl Decoder<bool> for FromToBytesCodec {
73    type Error = FromToBytesCodecError;
74    type Encoded = [u8];
75
76    fn decode(val: &Self::Encoded) -> Result<bool, Self::Error> {
77        let num: u8 = Self::decode(val)?;
78        Ok(num != 0)
79    }
80}
81
82impl Encoder<String> for FromToBytesCodec {
83    type Error = ();
84    type Encoded = Vec<u8>;
85
86    fn encode(val: &String) -> Result<Self::Encoded, Self::Error> {
87        Ok(val.as_bytes().to_vec())
88    }
89}
90
91impl Decoder<String> for FromToBytesCodec {
92    type Error = FromToBytesCodecError;
93    type Encoded = [u8];
94
95    fn decode(val: &Self::Encoded) -> Result<String, Self::Error> {
96        Ok(String::from_utf8(val.to_vec())?)
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn test_fromtobytes_codec() {
106        let t = 50;
107
108        let enc: Vec<u8> = FromToBytesCodec::encode(&t).unwrap();
109        let dec: i32 = FromToBytesCodec::decode(enc.as_slice()).unwrap();
110        assert_eq!(dec, t);
111    }
112}