Skip to main content

qubit_codec/value/
json_bytes_value_codec.rs

1// =============================================================================
2//    Copyright (c) 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Bidirectional Serde JSON bytes codec for one owned value.
9
10use core::marker::PhantomData;
11
12use serde::Serialize;
13use serde::de::DeserializeOwned;
14use serde_json::Error as JsonError;
15
16use super::JsonBytesValueDecoder;
17use super::JsonBytesValueEncoder;
18use super::ValueDecoder;
19use super::ValueEncoder;
20
21/// Encodes and decodes one serializable value through JSON bytes.
22///
23/// This type combines [`JsonBytesValueEncoder`] and [`JsonBytesValueDecoder`]
24/// for registry-backed or bidirectional call sites. It holds no state between
25/// calls, so it is `Copy` and `Default` without requiring those traits on `T`;
26/// encoding and decoding can share one value through [`ValueEncoder`] and
27/// [`ValueDecoder`].
28///
29/// # Type Parameters
30///
31/// - `T`: Value type serialized to JSON bytes and recovered from them.
32///
33/// # Examples
34///
35/// ```
36/// use qubit_codec::JsonBytesValueCodec;
37/// use qubit_codec::ValueDecoder;
38/// use qubit_codec::ValueEncoder;
39///
40/// let mut codec = JsonBytesValueCodec::<String>::new();
41/// assert_eq!(codec.encode(&"hello".to_string()).unwrap(), br#""hello""#.to_vec());
42/// assert_eq!(codec.decode(br#""hello""#).unwrap(), "hello");
43/// ```
44#[must_use]
45#[derive(Debug)]
46pub struct JsonBytesValueCodec<T> {
47    /// Associates the codec with `T` without retaining a value.
48    _marker: PhantomData<T>,
49}
50
51impl<T> Copy for JsonBytesValueCodec<T> {}
52
53impl<T> Clone for JsonBytesValueCodec<T> {
54    /// Returns an identical stateless codec without requiring `T: Clone`.
55    ///
56    /// # Returns
57    ///
58    /// Returns a codec associated with the same value type.
59    #[inline]
60    fn clone(&self) -> Self {
61        *self
62    }
63}
64
65impl<T> Default for JsonBytesValueCodec<T> {
66    /// Creates a codec for `T` without constructing a value of that type.
67    ///
68    /// # Returns
69    ///
70    /// Returns a stateless codec associated with `T`.
71    #[inline]
72    fn default() -> Self {
73        Self::new()
74    }
75}
76
77impl<T> JsonBytesValueCodec<T> {
78    /// Creates a bidirectional JSON bytes codec for values of type `T`.
79    ///
80    /// # Returns
81    ///
82    /// Returns a stateless codec bound to values of type `T`.
83    #[inline]
84    pub const fn new() -> Self {
85        Self { _marker: PhantomData }
86    }
87}
88
89impl<T> ValueEncoder<T> for JsonBytesValueCodec<T>
90where
91    T: Serialize,
92{
93    /// Serialization failure reported by Serde JSON.
94    type Error = JsonError;
95    /// Newly allocated UTF-8 JSON bytes owned by the caller.
96    type Output = Vec<u8>;
97
98    /// Serializes `input` into UTF-8 JSON bytes.
99    ///
100    /// # Parameters
101    ///
102    /// - `input`: Value borrowed for the duration of serialization.
103    ///
104    /// # Returns
105    ///
106    /// Returns a newly allocated vector containing the serialized JSON.
107    ///
108    /// # Errors
109    ///
110    /// Returns a JSON error if `T` rejects serialization or contains a map key
111    /// that cannot be represented as a JSON object key.
112    #[inline]
113    fn encode(&mut self, input: &T) -> Result<Self::Output, Self::Error> {
114        JsonBytesValueEncoder::<T>::new().encode(input)
115    }
116}
117
118impl<T> ValueDecoder<[u8]> for JsonBytesValueCodec<T>
119where
120    T: DeserializeOwned,
121{
122    /// JSON syntax or target-value deserialization failure.
123    type Error = JsonError;
124    /// Owned value deserialized independently of the input byte slice.
125    type Output = T;
126
127    /// Deserializes `input` using [`serde_json::from_slice`].
128    ///
129    /// # Parameters
130    ///
131    /// - `input`: One complete JSON value, optionally surrounded by whitespace.
132    ///   String-content validation follows `T`'s Serde deserialization
133    ///   implementation.
134    ///
135    /// # Returns
136    ///
137    /// Returns an owned `T`; decoding may allocate according to the target
138    /// type.
139    ///
140    /// # Errors
141    ///
142    /// Returns a JSON error for malformed or incomplete input, trailing
143    /// non-whitespace data, or a value incompatible with `T`. Validation
144    /// follows serde_json and `T`'s `Deserialize` implementation; byte-oriented
145    /// targets may accept non-UTF-8 string contents.
146    #[inline]
147    fn decode(&mut self, input: &[u8]) -> Result<Self::Output, Self::Error> {
148        JsonBytesValueDecoder::<T>::new().decode(input)
149    }
150}