codee/binary/
rkyv.rs

1use crate::{Decoder, Encoder};
2use rkyv::api::high::{HighSerializer, HighValidator};
3use rkyv::de::Pool;
4use rkyv::rancor::Strategy;
5use rkyv::ser::allocator::ArenaHandle;
6pub use rkyv::util::AlignedVec;
7use rkyv::{bytecheck, rancor, Archive, Deserialize, Serialize};
8use std::error::Error;
9use std::sync::Arc;
10
11/// A codec that relies on `rkyv` to encode data in the msgpack format.
12///
13/// This is only available with the **`rkyv` feature** enabled.
14pub struct RkyvCodec;
15
16impl<T> Encoder<T> for RkyvCodec
17where
18    T: for<'a> Serialize<HighSerializer<Vec<u8>, ArenaHandle<'a>, rancor::Error>>,
19{
20    type Error = rancor::Error;
21    type Encoded = Vec<u8>;
22
23    fn encode(val: &T) -> Result<Self::Encoded, Self::Error> {
24        rkyv::api::high::to_bytes_in(val, Vec::new())
25    }
26}
27
28impl<T> Decoder<T> for RkyvCodec
29where
30    T: Archive,
31    for<'a> T::Archived: 'a
32        + bytecheck::CheckBytes<HighValidator<'a, rancor::Error>>
33        + Deserialize<T, Strategy<Pool, rancor::Error>>,
34{
35    type Error = Arc<dyn Error>;
36    type Encoded = [u8];
37
38    fn decode(val: &Self::Encoded) -> Result<T, Self::Error> {
39        let mut aligned = AlignedVec::<16>::with_capacity(val.len());
40        aligned.extend_from_slice(val);
41        rkyv::from_bytes::<T, rancor::Error>(&aligned).map_err(|e| Arc::new(e) as Arc<dyn Error>)
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn test_rkyv_codec() {
51        #[derive(Clone, Debug, PartialEq, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
52        struct Test {
53            s: String,
54            i: i32,
55        }
56        let t = Test {
57            s: String::from("party time 🎉"),
58            i: 42,
59        };
60        let enc = RkyvCodec::encode(&t).unwrap();
61        let dec: Test = RkyvCodec::decode(&enc).unwrap();
62        assert_eq!(dec, t);
63    }
64}