Skip to main content

server_fn/codec/
rkyv.rs

1use crate::{
2    codec::{Patch, Post, Put},
3    ContentType, Decodes, Encodes, Format, FormatType,
4};
5use bytes::Bytes;
6use rkyv::{
7    api::high::{HighDeserializer, HighSerializer, HighValidator},
8    bytecheck::CheckBytes,
9    rancor,
10    ser::allocator::ArenaHandle,
11    util::AlignedVec,
12    Archive, Deserialize, Serialize,
13};
14
15type RkyvSerializer<'a> =
16    HighSerializer<AlignedVec, ArenaHandle<'a>, rancor::Error>;
17type RkyvDeserializer = HighDeserializer<rancor::Error>;
18type RkyvValidator<'a> = HighValidator<'a, rancor::Error>;
19
20/// Pass arguments and receive responses using `rkyv` in a `POST` request.
21pub struct RkyvEncoding;
22
23impl ContentType for RkyvEncoding {
24    const CONTENT_TYPE: &'static str = "application/rkyv";
25}
26
27impl FormatType for RkyvEncoding {
28    const FORMAT_TYPE: Format = Format::Binary;
29}
30
31impl<T> Encodes<T> for RkyvEncoding
32where
33    T: Archive + for<'a> Serialize<RkyvSerializer<'a>>,
34    T::Archived: Deserialize<T, RkyvDeserializer>
35        + for<'a> CheckBytes<RkyvValidator<'a>>,
36{
37    type Error = rancor::Error;
38
39    fn encode(value: &T) -> Result<Bytes, Self::Error> {
40        let encoded = rkyv::to_bytes::<rancor::Error>(value)?;
41        Ok(Bytes::copy_from_slice(encoded.as_ref()))
42    }
43}
44
45impl<T> Decodes<T> for RkyvEncoding
46where
47    T: Archive + for<'a> Serialize<RkyvSerializer<'a>>,
48    T::Archived: Deserialize<T, RkyvDeserializer>
49        + for<'a> CheckBytes<RkyvValidator<'a>>,
50{
51    type Error = rancor::Error;
52
53    fn decode(bytes: Bytes) -> Result<T, Self::Error> {
54        let mut aligned = AlignedVec::<1024>::new();
55        aligned.extend_from_slice(bytes.as_ref());
56        rkyv::from_bytes::<T, rancor::Error>(aligned.as_ref())
57    }
58}
59
60/// Pass arguments and receive responses as `rkyv` in a `POST` request.
61pub type Rkyv = Post<RkyvEncoding>;
62
63/// Pass arguments and receive responses as `rkyv` in a `PATCH` request.
64/// **Note**: Browser support for `PATCH` requests without JS/WASM may be poor.
65/// Consider using a `POST` request if functionality without JS/WASM is required.
66pub type PatchRkyv = Patch<RkyvEncoding>;
67
68/// Pass arguments and receive responses as `rkyv` in a `PUT` request.
69/// **Note**: Browser support for `PUT` requests without JS/WASM may be poor.
70/// Consider using a `POST` request if functionality without JS/WASM is required.
71pub type PutRkyv = Put<RkyvEncoding>;