Skip to main content

karyon_jsonrpc/
codec.rs

1//! JSON codec for JSON-RPC message framing.
2//!
3//! Provides `JsonCodec` which encodes/decodes `serde_json::Value`
4//! messages with a configurable max payload size (default 4MB).
5
6use std::io;
7
8pub use karyon_net::codec::Codec;
9pub use karyon_net::ByteBuffer;
10
11#[cfg(feature = "ws")]
12use karyon_net::layers::ws::Message as WsMessage;
13
14const DEFAULT_MAX_BUFFER_SIZE: usize = 4 * 1024 * 1024; // 4MB
15
16/// Byte-stream codec used for TCP, TLS, Unix, QUIC, and HTTP.
17pub trait JsonRpcCodec:
18    Codec<ByteBuffer, Message = serde_json::Value, Error = karyon_net::Error>
19    + Clone
20    + Send
21    + Sync
22    + 'static
23{
24}
25
26impl<T> JsonRpcCodec for T where
27    T: Codec<ByteBuffer, Message = serde_json::Value, Error = karyon_net::Error>
28        + Clone
29        + Send
30        + Sync
31        + 'static
32{
33}
34
35/// WebSocket-message codec used for `ws://` and `wss://` endpoints.
36#[cfg(feature = "ws")]
37pub trait JsonRpcWsCodec:
38    Codec<WsMessage, Message = serde_json::Value, Error = karyon_net::Error>
39    + Clone
40    + Send
41    + Sync
42    + 'static
43{
44}
45
46#[cfg(feature = "ws")]
47impl<T> JsonRpcWsCodec for T where
48    T: Codec<WsMessage, Message = serde_json::Value, Error = karyon_net::Error>
49        + Clone
50        + Send
51        + Sync
52        + 'static
53{
54}
55
56/// Default JSON codec with configurable max payload size.
57#[derive(Clone)]
58pub struct JsonCodec {
59    max_size: usize,
60}
61
62impl Default for JsonCodec {
63    fn default() -> Self {
64        Self {
65            max_size: DEFAULT_MAX_BUFFER_SIZE,
66        }
67    }
68}
69
70impl JsonCodec {
71    pub fn new(max_payload_size: usize) -> Self {
72        Self {
73            max_size: max_payload_size,
74        }
75    }
76}
77
78impl Codec<ByteBuffer> for JsonCodec {
79    type Message = serde_json::Value;
80    type Error = karyon_net::Error;
81
82    fn encode(
83        &self,
84        src: &serde_json::Value,
85        dst: &mut ByteBuffer,
86    ) -> std::result::Result<usize, karyon_net::Error> {
87        let msg =
88            serde_json::to_string(src).map_err(|e| karyon_net::Error::IO(io::Error::other(e)))?;
89        let buf = msg.as_bytes();
90
91        if buf.len() > self.max_size {
92            return Err(karyon_net::Error::BufferFull(format!(
93                "Buffer size {} exceeds maximum {}",
94                buf.len(),
95                self.max_size
96            )));
97        }
98
99        dst.extend_from_slice(buf);
100        Ok(buf.len())
101    }
102
103    fn decode(
104        &self,
105        src: &mut ByteBuffer,
106    ) -> std::result::Result<Option<(usize, serde_json::Value)>, karyon_net::Error> {
107        if src.len() > self.max_size {
108            return Err(karyon_net::Error::BufferFull(format!(
109                "Buffer size {} exceeds maximum {}",
110                src.len(),
111                self.max_size
112            )));
113        }
114
115        let de = serde_json::Deserializer::from_slice(src.as_ref());
116        let mut iter = de.into_iter::<serde_json::Value>();
117
118        let item = match iter.next() {
119            Some(Ok(item)) => item,
120            Some(Err(ref e)) if e.is_eof() => return Ok(None),
121            Some(Err(e)) => return Err(karyon_net::Error::IO(io::Error::other(e))),
122            None => return Ok(None),
123        };
124
125        Ok(Some((iter.byte_offset(), item)))
126    }
127}
128
129/// WS codec for JSON values over WebSocket text messages.
130#[cfg(feature = "ws")]
131impl Codec<WsMessage> for JsonCodec {
132    type Message = serde_json::Value;
133    type Error = karyon_net::Error;
134
135    fn encode(
136        &self,
137        src: &serde_json::Value,
138        dst: &mut WsMessage,
139    ) -> std::result::Result<usize, karyon_net::Error> {
140        let json =
141            serde_json::to_string(src).map_err(|e| karyon_net::Error::IO(io::Error::other(e)))?;
142        let len = json.len();
143        *dst = WsMessage::Text(json);
144        Ok(len)
145    }
146
147    fn decode(
148        &self,
149        src: &mut WsMessage,
150    ) -> std::result::Result<Option<(usize, serde_json::Value)>, karyon_net::Error> {
151        match src {
152            WsMessage::Text(text) => {
153                let len = text.len();
154                if len > self.max_size {
155                    return Err(karyon_net::Error::BufferFull(format!(
156                        "Buffer size {} exceeds maximum {}",
157                        len, self.max_size
158                    )));
159                }
160                let val = serde_json::from_str(text)
161                    .map_err(|e| karyon_net::Error::IO(io::Error::other(e)))?;
162                Ok(Some((len, val)))
163            }
164            _ => Ok(None),
165        }
166    }
167}