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}