Skip to main content

qubit_codec/value/
json_string_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 string codec for one owned value.
9
10use core::marker::PhantomData;
11
12use serde::Serialize;
13use serde::de::DeserializeOwned;
14
15use super::JsonStringValueDecoder;
16use super::JsonStringValueEncoder;
17use super::ValueDecoder;
18use super::ValueEncoder;
19
20/// Encodes and decodes one serializable value through UTF-8 JSON strings.
21///
22/// This type combines [`JsonStringValueEncoder`] and [`JsonStringValueDecoder`]
23/// for registry-backed or bidirectional call sites. It holds no state between
24/// calls, so it is `Copy` and `Default` without requiring those traits on `T`;
25/// encoding and decoding can share one value through [`ValueEncoder`] and
26/// [`ValueDecoder`].
27///
28/// # Type Parameters
29///
30/// - `T`: Value type serialized to a JSON string and recovered from it.
31///
32/// # Examples
33///
34/// ```
35/// use qubit_codec::JsonStringValueCodec;
36/// use qubit_codec::ValueDecoder;
37/// use qubit_codec::ValueEncoder;
38///
39/// let mut codec = JsonStringValueCodec::<String>::new();
40/// assert_eq!(codec.encode(&"hello".to_string()).unwrap(), r#""hello""#.to_string());
41/// assert_eq!(codec.decode(r#""hello""#).unwrap(), "hello");
42/// ```
43#[must_use]
44#[derive(Debug)]
45pub struct JsonStringValueCodec<T> {
46    /// Associates the codec with `T` without retaining a value.
47    _marker: PhantomData<T>,
48}
49
50impl<T> Copy for JsonStringValueCodec<T> {}
51
52impl<T> Clone for JsonStringValueCodec<T> {
53    /// Copies the stateless marker without requiring `T: Clone`.
54    ///
55    /// # Returns
56    ///
57    /// Returns another marker bound to the same value type.
58    #[inline]
59    fn clone(&self) -> Self {
60        *self
61    }
62}
63
64impl<T> Default for JsonStringValueCodec<T> {
65    /// Creates the stateless marker without requiring `T: Default`.
66    ///
67    /// # Returns
68    ///
69    /// Returns a codec bound to the value type `T`.
70    #[inline]
71    fn default() -> Self {
72        Self::new()
73    }
74}
75
76impl<T> JsonStringValueCodec<T> {
77    /// Creates a bidirectional JSON string codec for values of type `T`.
78    ///
79    /// # Returns
80    ///
81    /// Returns a stateless codec bound to values of type `T`.
82    #[inline]
83    pub const fn new() -> Self {
84        Self { _marker: PhantomData }
85    }
86}
87
88impl<T> ValueEncoder<T> for JsonStringValueCodec<T>
89where
90    T: Serialize,
91{
92    /// Serialization failure reported by Serde JSON.
93    type Error = serde_json::Error;
94    /// Newly allocated UTF-8 JSON string owned by the caller.
95    type Output = String;
96
97    /// Serializes `input` into a JSON string.
98    ///
99    /// The codec holds no state, so this delegates to a freshly created
100    /// [`JsonStringValueEncoder`] and `self` stays usable for further calls.
101    ///
102    /// # Parameters
103    ///
104    /// - `input`: Value to serialize as JSON.
105    ///
106    /// # Returns
107    ///
108    /// Returns the serialized JSON text as an owned UTF-8 string.
109    ///
110    /// # Errors
111    ///
112    /// Returns [`serde_json::Error`] when `input` cannot be serialized to
113    /// JSON, including when a custom `Serialize` implementation fails or a map
114    /// key cannot be represented as a JSON object key.
115    #[inline]
116    fn encode(&mut self, input: &T) -> Result<Self::Output, Self::Error> {
117        JsonStringValueEncoder::<T>::new().encode(input)
118    }
119}
120
121impl<T> ValueDecoder<str> for JsonStringValueCodec<T>
122where
123    T: DeserializeOwned,
124{
125    /// JSON syntax or target-value deserialization failure.
126    type Error = serde_json::Error;
127    /// Owned value deserialized independently of the input string lifetime.
128    type Output = T;
129
130    /// Deserializes `input` from a JSON string.
131    ///
132    /// The codec holds no state, so this delegates to a freshly created
133    /// [`JsonStringValueDecoder`] and `self` stays usable for further calls.
134    ///
135    /// # Parameters
136    ///
137    /// - `input`: Complete JSON value to deserialize.
138    ///
139    /// # Returns
140    ///
141    /// Returns an owned `T` deserialized independently of `input`'s lifetime.
142    ///
143    /// # Errors
144    ///
145    /// Returns [`serde_json::Error`] when `input` is not valid JSON or when a
146    /// valid JSON document does not match the shape required by `T`.
147    #[inline]
148    fn decode(&mut self, input: &str) -> Result<Self::Output, Self::Error> {
149        JsonStringValueDecoder::<T>::new().decode(input)
150    }
151}