Skip to main content

rustbridge_transport/
codec.rs

1//! Codec trait and JSON implementation
2
3use rustbridge_core::PluginError;
4use serde::{Serialize, de::DeserializeOwned};
5use thiserror::Error;
6
7/// Errors that can occur during encoding/decoding
8#[derive(Error, Debug)]
9pub enum CodecError {
10    #[error("serialization error: {0}")]
11    Serialization(String),
12
13    #[error("deserialization error: {0}")]
14    Deserialization(String),
15
16    #[error("invalid format: {0}")]
17    InvalidFormat(String),
18}
19
20impl From<serde_json::Error> for CodecError {
21    fn from(err: serde_json::Error) -> Self {
22        if err.is_data() || err.is_syntax() || err.is_eof() {
23            CodecError::Deserialization(err.to_string())
24        } else {
25            CodecError::Serialization(err.to_string())
26        }
27    }
28}
29
30impl From<CodecError> for PluginError {
31    fn from(err: CodecError) -> Self {
32        PluginError::SerializationError(err.to_string())
33    }
34}
35
36/// Trait for message encoding and decoding
37pub trait Codec: Send + Sync {
38    /// Encode a value to bytes
39    fn encode<T: Serialize>(&self, value: &T) -> Result<Vec<u8>, CodecError>;
40
41    /// Decode bytes to a value
42    fn decode<T: DeserializeOwned>(&self, data: &[u8]) -> Result<T, CodecError>;
43
44    /// Get the content type for this codec
45    fn content_type(&self) -> &'static str;
46}
47
48/// JSON codec implementation using serde_json
49#[derive(Debug, Clone, Default)]
50pub struct JsonCodec {
51    /// Whether to pretty-print output (default: false for efficiency)
52    pretty: bool,
53}
54
55impl JsonCodec {
56    /// Create a new JSON codec
57    pub fn new() -> Self {
58        Self { pretty: false }
59    }
60
61    /// Create a JSON codec that pretty-prints output
62    pub fn pretty() -> Self {
63        Self { pretty: true }
64    }
65
66    /// Encode a value directly to a JSON string
67    pub fn encode_string<T: Serialize>(&self, value: &T) -> Result<String, CodecError> {
68        if self.pretty {
69            serde_json::to_string_pretty(value).map_err(Into::into)
70        } else {
71            serde_json::to_string(value).map_err(Into::into)
72        }
73    }
74
75    /// Decode a JSON string to a value
76    pub fn decode_str<T: DeserializeOwned>(&self, data: &str) -> Result<T, CodecError> {
77        serde_json::from_str(data).map_err(Into::into)
78    }
79}
80
81impl Codec for JsonCodec {
82    fn encode<T: Serialize>(&self, value: &T) -> Result<Vec<u8>, CodecError> {
83        if self.pretty {
84            serde_json::to_vec_pretty(value).map_err(Into::into)
85        } else {
86            serde_json::to_vec(value).map_err(Into::into)
87        }
88    }
89
90    fn decode<T: DeserializeOwned>(&self, data: &[u8]) -> Result<T, CodecError> {
91        serde_json::from_slice(data).map_err(Into::into)
92    }
93
94    fn content_type(&self) -> &'static str {
95        "application/json"
96    }
97}
98
99#[cfg(test)]
100#[path = "codec/codec_tests.rs"]
101mod codec_tests;