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 UTF-8 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 #[inline]
55 fn clone(&self) -> Self {
56 *self
57 }
58}
59
60impl<T> Default for JsonBytesValueCodec<T> {
61 #[inline]
62 fn default() -> Self {
63 Self::new()
64 }
65}
66
67impl<T> JsonBytesValueCodec<T> {
68 /// Creates a bidirectional JSON bytes codec for values of type `T`.
69 ///
70 /// # Returns
71 ///
72 /// Returns a stateless codec bound to values of type `T`.
73 #[inline]
74 pub const fn new() -> Self {
75 Self { _marker: PhantomData }
76 }
77}
78
79impl<T> ValueEncoder<T> for JsonBytesValueCodec<T>
80where
81 T: Serialize,
82{
83 /// Serialization failure reported by Serde JSON.
84 type Error = JsonError;
85 /// Newly allocated UTF-8 JSON bytes owned by the caller.
86 type Output = Vec<u8>;
87
88 /// Serializes `input` into UTF-8 JSON bytes.
89 ///
90 /// # Parameters
91 ///
92 /// - `input`: Value borrowed for the duration of serialization.
93 ///
94 /// # Returns
95 ///
96 /// Returns a newly allocated vector containing the serialized JSON.
97 ///
98 /// # Errors
99 ///
100 /// Returns a JSON error if `T` rejects serialization or contains a map key
101 /// that cannot be represented as a JSON object key.
102 #[inline]
103 fn encode(&mut self, input: &T) -> Result<Self::Output, Self::Error> {
104 JsonBytesValueEncoder::<T>::new().encode(input)
105 }
106}
107
108impl<T> ValueDecoder<[u8]> for JsonBytesValueCodec<T>
109where
110 T: DeserializeOwned,
111{
112 /// JSON syntax, UTF-8, or target-value deserialization failure.
113 type Error = JsonError;
114 /// Owned value deserialized independently of the input byte slice.
115 type Output = T;
116
117 /// Deserializes `input` from UTF-8 JSON bytes.
118 ///
119 /// # Parameters
120 ///
121 /// - `input`: One complete UTF-8 JSON value, optionally surrounded by
122 /// whitespace.
123 ///
124 /// # Returns
125 ///
126 /// Returns an owned `T`; decoding may allocate according to the target
127 /// type.
128 ///
129 /// # Errors
130 ///
131 /// Returns a JSON error for invalid UTF-8, malformed or incomplete input,
132 /// trailing non-whitespace data, or a value incompatible with `T`.
133 #[inline]
134 fn decode(&mut self, input: &[u8]) -> Result<Self::Output, Self::Error> {
135 JsonBytesValueDecoder::<T>::new().decode(input)
136 }
137}