Skip to main content

oxigdal_websocket/protocol/
json.rs

1//! JSON protocol implementation
2
3use crate::error::{Error, Result};
4use crate::protocol::message::Message;
5use bytes::Bytes;
6
7/// JSON message codec
8pub struct JsonCodec;
9
10impl JsonCodec {
11    /// Encode a message to JSON
12    pub fn encode(message: &Message) -> Result<Bytes> {
13        let json = serde_json::to_vec(message)?;
14        Ok(Bytes::from(json))
15    }
16
17    /// Decode a message from JSON
18    pub fn decode(data: &[u8]) -> Result<Message> {
19        let message: Message = serde_json::from_slice(data)?;
20        Ok(message)
21    }
22
23    /// Encode a message to pretty JSON (for debugging)
24    pub fn encode_pretty(message: &Message) -> Result<Bytes> {
25        let json = serde_json::to_vec_pretty(message)?;
26        Ok(Bytes::from(json))
27    }
28
29    /// Validate JSON structure without full parsing
30    pub fn validate(data: &[u8]) -> Result<()> {
31        serde_json::from_slice::<serde_json::Value>(data)?;
32        Ok(())
33    }
34}
35
36/// JSON message wrapper
37pub struct JsonMessage {
38    data: Bytes,
39}
40
41impl JsonMessage {
42    /// Create a new JSON message
43    pub fn new(data: Bytes) -> Self {
44        Self { data }
45    }
46
47    /// Create from string
48    pub fn from_string(s: String) -> Self {
49        Self {
50            data: Bytes::from(s.into_bytes()),
51        }
52    }
53
54    /// Get message data
55    pub fn data(&self) -> &Bytes {
56        &self.data
57    }
58
59    /// Convert to message
60    pub fn to_message(&self) -> Result<Message> {
61        JsonCodec::decode(&self.data)
62    }
63
64    /// Get as string
65    pub fn as_string(&self) -> Result<String> {
66        String::from_utf8(self.data.to_vec())
67            .map_err(|e| Error::Protocol(format!("Invalid UTF-8: {}", e)))
68    }
69
70    /// Validate structure
71    pub fn validate(&self) -> Result<()> {
72        JsonCodec::validate(&self.data)
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn test_json_codec_ping() -> Result<()> {
82        let msg = Message::ping();
83        let encoded = JsonCodec::encode(&msg)?;
84        let decoded = JsonCodec::decode(&encoded)?;
85
86        assert_eq!(msg.msg_type, decoded.msg_type);
87        assert_eq!(msg.id, decoded.id);
88        Ok(())
89    }
90
91    #[test]
92    fn test_json_codec_pretty() -> Result<()> {
93        let msg = Message::ping();
94        let encoded = JsonCodec::encode_pretty(&msg)?;
95        let decoded = JsonCodec::decode(&encoded)?;
96
97        assert_eq!(msg.msg_type, decoded.msg_type);
98
99        // Verify it's actually pretty-printed
100        let s = String::from_utf8(encoded.to_vec()).ok();
101        assert!(s.is_some());
102        assert!(s.as_ref().is_some_and(|s| s.contains('\n')));
103        Ok(())
104    }
105
106    #[test]
107    fn test_json_message() -> Result<()> {
108        let msg = Message::ping();
109        let encoded = JsonCodec::encode(&msg)?;
110        let json_msg = JsonMessage::new(encoded);
111
112        let decoded = json_msg.to_message()?;
113        assert_eq!(msg.msg_type, decoded.msg_type);
114
115        json_msg.validate()?;
116        Ok(())
117    }
118
119    #[test]
120    fn test_json_validate_invalid() {
121        let invalid = b"not valid json";
122        let result = JsonCodec::validate(invalid);
123        assert!(result.is_err());
124    }
125}