xrpc/
codec.rs

1use crate::error::Result;
2use serde::{Deserialize, Serialize};
3
4/// Trait for encoding and decoding message payloads
5pub trait Codec: Send + Sync + std::fmt::Debug {
6    /// Encode a serializable value into bytes
7    fn encode<T: Serialize>(&self, data: &T) -> Result<Vec<u8>>;
8
9    /// Decode bytes into a deserializable value
10    fn decode<T: for<'de> Deserialize<'de>>(&self, data: &[u8]) -> Result<T>;
11}
12
13/// Default codec (Bincode codec)
14#[derive(Debug, Clone, Copy, Default)]
15pub struct BincodeCodec;
16
17impl Codec for BincodeCodec {
18    fn encode<T: Serialize>(&self, data: &T) -> Result<Vec<u8>> {
19        Ok(bincode::serialize(data)?)
20    }
21
22    fn decode<T: for<'de> Deserialize<'de>>(&self, data: &[u8]) -> Result<T> {
23        Ok(bincode::deserialize(data)?)
24    }
25}
26
27/// JSON codec
28#[derive(Debug, Clone, Copy, Default)]
29pub struct JsonCodec;
30
31impl Codec for JsonCodec {
32    fn encode<T: Serialize>(&self, data: &T) -> Result<Vec<u8>> {
33        Ok(serde_json::to_vec(data)?)
34    }
35
36    fn decode<T: for<'de> Deserialize<'de>>(&self, data: &[u8]) -> Result<T> {
37        Ok(serde_json::from_slice(data)?)
38    }
39}
40
41/// MessagePack codec - compact binary, cross-language compatible
42#[cfg(feature = "codec-messagepack")]
43#[derive(Debug, Clone, Copy, Default)]
44pub struct MessagePackCodec;
45
46#[cfg(feature = "codec-messagepack")]
47impl Codec for MessagePackCodec {
48    fn encode<T: Serialize>(&self, data: &T) -> Result<Vec<u8>> {
49        rmp_serde::to_vec(data).map_err(|e| crate::error::RpcError::Serialization(e.to_string()))
50    }
51
52    fn decode<T: for<'de> Deserialize<'de>>(&self, data: &[u8]) -> Result<T> {
53        rmp_serde::from_slice(data)
54            .map_err(|e| crate::error::RpcError::Serialization(e.to_string()))
55    }
56}
57
58/// CBOR codec - binary JSON (RFC 8949), self-describing
59#[cfg(feature = "codec-cbor")]
60#[derive(Debug, Clone, Copy, Default)]
61pub struct CborCodec;
62
63#[cfg(feature = "codec-cbor")]
64impl Codec for CborCodec {
65    fn encode<T: Serialize>(&self, data: &T) -> Result<Vec<u8>> {
66        let mut buf = Vec::new();
67        ciborium::into_writer(data, &mut buf)
68            .map_err(|e| crate::error::RpcError::Serialization(e.to_string()))?;
69        Ok(buf)
70    }
71
72    fn decode<T: for<'de> Deserialize<'de>>(&self, data: &[u8]) -> Result<T> {
73        ciborium::from_reader(data)
74            .map_err(|e| crate::error::RpcError::Serialization(e.to_string()))
75    }
76}
77
78/// Postcard codec - minimal binary, no_std compatible
79#[cfg(feature = "codec-postcard")]
80#[derive(Debug, Clone, Copy, Default)]
81pub struct PostcardCodec;
82
83#[cfg(feature = "codec-postcard")]
84impl Codec for PostcardCodec {
85    fn encode<T: Serialize>(&self, data: &T) -> Result<Vec<u8>> {
86        postcard::to_allocvec(data)
87            .map_err(|e| crate::error::RpcError::Serialization(e.to_string()))
88    }
89
90    fn decode<T: for<'de> Deserialize<'de>>(&self, data: &[u8]) -> Result<T> {
91        postcard::from_bytes(data).map_err(|e| crate::error::RpcError::Serialization(e.to_string()))
92    }
93}