Skip to main content

compio_io/framed/codec/
serde_json.rs

1//! [`Encoder`]/[`Decoder`] implementation with serde_json
2//!
3//! This module provides a codec implementation for JSON serialization and
4//! deserialization using serde_json.
5//!
6//! # Examples
7//!
8//! ```
9//! use compio_buf::IoBuf;
10//! use compio_io::framed::codec::{Decoder, Encoder, serde_json::SerdeJsonCodec};
11//! use serde::{Deserialize, Serialize};
12//!
13//! #[derive(Serialize, Deserialize)]
14//! struct Person {
15//!     name: String,
16//!     age: u32,
17//! }
18//!
19//! let mut codec = SerdeJsonCodec::new();
20//! let person = Person {
21//!     name: "Alice".to_string(),
22//!     age: 30,
23//! };
24//!
25//! // Encoding
26//! let mut buffer = Vec::new();
27//! codec.encode(person, &mut buffer).unwrap();
28//!
29//! // Decoding
30//! let buf = buffer.slice(..);
31//! let decoded: Person = codec.decode(&buf).unwrap();
32//! assert_eq!(decoded.name, "Alice");
33//! assert_eq!(decoded.age, 30);
34//! ```
35//!
36//! [`Encoder`]: crate::framed::codec::Encoder
37//! [`Decoder`]: crate::framed::codec::Decoder
38
39use std::io;
40
41use compio_buf::{IoBuf, IoBufMut, Slice};
42use serde::{Serialize, de::DeserializeOwned};
43use thiserror::Error;
44
45use crate::framed::codec::{Decoder, Encoder};
46
47/// A codec for JSON serialization and deserialization using serde_json.
48///
49/// This codec can be configured to output pretty-printed JSON by setting the
50/// `pretty` flag.
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
52pub struct SerdeJsonCodec {
53    pretty: bool,
54}
55
56impl SerdeJsonCodec {
57    /// Creates a new `SerdeJsonCodec` with default settings (not
58    /// pretty-printed).
59    pub fn new() -> Self {
60        Self { pretty: false }
61    }
62
63    /// Creates a new `SerdeJsonCodec` with pretty-printing enabled.
64    pub fn pretty() -> Self {
65        Self { pretty: true }
66    }
67
68    /// Sets whether the JSON output should be pretty-printed.
69    pub fn set_pretty(&mut self, pretty: bool) -> &mut Self {
70        self.pretty = pretty;
71        self
72    }
73
74    /// Returns whether pretty-printing is enabled.
75    pub fn is_pretty(&self) -> bool {
76        self.pretty
77    }
78}
79
80impl Default for SerdeJsonCodec {
81    fn default() -> Self {
82        Self::new()
83    }
84}
85
86/// Errors that can occur during JSON encoding or decoding.
87#[derive(Debug, Error)]
88pub enum SerdeJsonCodecError {
89    /// Error from serde_json during serialization or deserialization.
90    #[error("serde-json error: {0}")]
91    SerdeJsonError(serde_json::Error),
92
93    /// I/O error during encoding or decoding.
94    #[error("IO error: {0}")]
95    IoError(#[from] io::Error),
96}
97
98impl<T: Serialize, B: IoBufMut> Encoder<T, B> for SerdeJsonCodec {
99    type Error = SerdeJsonCodecError;
100
101    fn encode(&mut self, item: T, buf: &mut B) -> Result<(), Self::Error> {
102        let writer = buf.as_writer();
103        if self.pretty {
104            serde_json::to_writer_pretty(writer, &item)
105        } else {
106            serde_json::to_writer(writer, &item)
107        }
108        .map_err(SerdeJsonCodecError::SerdeJsonError)
109    }
110}
111
112impl<T: DeserializeOwned, B: IoBuf> Decoder<T, B> for SerdeJsonCodec {
113    type Error = SerdeJsonCodecError;
114
115    fn decode(&mut self, buf: &Slice<B>) -> Result<T, Self::Error> {
116        serde_json::from_slice(buf).map_err(SerdeJsonCodecError::SerdeJsonError)
117    }
118}
119
120#[test]
121fn test_serde_json_codec() {
122    use serde::{Deserialize, Serialize};
123
124    #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
125    struct TestStruct {
126        id: u32,
127        name: String,
128    }
129
130    let mut codec = SerdeJsonCodec::new();
131    let item = TestStruct {
132        id: 114514,
133        name: "Test".to_string(),
134    };
135
136    // Test encoding
137    let mut buffer = Vec::new();
138    codec.encode(item.clone(), &mut buffer).unwrap();
139
140    // Test decoding
141    let slice = buffer.slice(..);
142    let decoded: TestStruct = codec.decode(&slice).unwrap();
143
144    assert_eq!(item, decoded);
145}