1use std::borrow::Cow;
5use std::collections::HashMap;
6use std::hash::{BuildHasher, Hash};
7
8use serde::de::DeserializeOwned;
9#[cfg(test)]
10use serde::Deserialize;
11use serde::Serialize;
12
13use crate::Result;
14
15#[cfg(not(feature = "simd_json"))]
16mod export {
17 pub type Value = serde_json::Value;
18 pub type JsonMap = serde_json::Map<String, Value>;
19 pub const NULL: Value = Value::Null;
20
21 pub use serde_json::{json, Error as JsonError};
22}
23
24#[cfg(feature = "simd_json")]
25mod export {
26 pub type Value = simd_json::OwnedValue;
27 pub type JsonMap = simd_json::owned::Object;
28 pub const NULL: Value = Value::Static(simd_json::StaticNode::Null);
29
30 pub use simd_json::prelude::{
31 TypedContainerValue,
32 ValueAsContainer,
33 ValueAsMutContainer,
34 ValueAsScalar,
35 };
36 pub use simd_json::{json, Error as JsonError, StaticNode};
37}
38
39pub use export::*;
40
41#[cfg(feature = "http")]
42pub(crate) async fn decode_resp<T: serde::de::DeserializeOwned>(
43 resp: reqwest::Response,
44) -> Result<T> {
45 #[cfg(not(feature = "simd_json"))]
46 let result = serde_json::from_slice(&resp.bytes().await?)?;
47 #[cfg(feature = "simd_json")]
48 let result = simd_json::from_slice(&mut resp.bytes().await?.to_vec())?;
49 Ok(result)
50}
51
52pub fn hashmap_to_json_map<H, T>(map: HashMap<T, Value, H>) -> JsonMap
54where
55 H: BuildHasher,
56 T: Eq + Hash + ToString,
57{
58 map.into_iter().map(|(k, v)| (k.to_string(), v)).collect()
59}
60
61#[allow(clippy::missing_errors_doc)]
66pub fn from_str<'a, T>(s: impl Into<Cow<'a, str>>) -> Result<T>
67where
68 T: DeserializeOwned,
69{
70 let s = s.into();
71 #[cfg(not(feature = "simd_json"))]
72 let result = serde_json::from_str(&s)?;
73 #[cfg(feature = "simd_json")]
74 let result = simd_json::from_slice(&mut s.into_owned().into_bytes())?;
75 Ok(result)
76}
77
78#[allow(clippy::missing_errors_doc)]
80pub fn from_slice<T>(v: &[u8]) -> Result<T>
81where
82 T: DeserializeOwned,
83{
84 #[cfg(not(feature = "simd_json"))]
85 let result = serde_json::from_slice(v)?;
86 #[cfg(feature = "simd_json")]
87 let result = simd_json::from_slice(&mut v.to_vec())?;
90 Ok(result)
91}
92
93#[allow(clippy::missing_errors_doc)]
95pub fn from_value<T>(value: Value) -> Result<T>
96where
97 T: DeserializeOwned,
98{
99 #[cfg(not(feature = "simd_json"))]
100 let result = serde_json::from_value(value)?;
101 #[cfg(feature = "simd_json")]
102 let result = simd_json::serde::from_owned_value(value)?;
103 Ok(result)
104}
105
106#[allow(clippy::missing_errors_doc)]
108pub fn from_reader<R, T>(rdr: R) -> Result<T>
109where
110 R: std::io::Read,
111 T: DeserializeOwned,
112{
113 #[cfg(not(feature = "simd_json"))]
114 let result = serde_json::from_reader(rdr)?;
115 #[cfg(feature = "simd_json")]
116 let result = simd_json::from_reader(rdr)?;
117 Ok(result)
118}
119
120#[allow(clippy::missing_errors_doc)]
122pub fn to_string<T>(value: &T) -> Result<String>
123where
124 T: ?Sized + Serialize,
125{
126 #[cfg(not(feature = "simd_json"))]
127 let result = serde_json::to_string(value)?;
128 #[cfg(feature = "simd_json")]
129 let result = simd_json::to_string(value)?;
130 Ok(result)
131}
132
133#[allow(clippy::missing_errors_doc)]
135pub fn to_string_pretty<T>(value: &T) -> Result<String>
136where
137 T: ?Sized + Serialize,
138{
139 #[cfg(not(feature = "simd_json"))]
140 let result = serde_json::to_string_pretty(value)?;
141 #[cfg(feature = "simd_json")]
142 let result = simd_json::to_string_pretty(value)?;
143 Ok(result)
144}
145
146#[allow(clippy::missing_errors_doc)]
148pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
149where
150 T: ?Sized + Serialize,
151{
152 #[cfg(not(feature = "simd_json"))]
153 let result = serde_json::to_vec(value)?;
154 #[cfg(feature = "simd_json")]
155 let result = simd_json::to_vec(value)?;
156 Ok(result)
157}
158
159#[allow(clippy::missing_errors_doc)]
161pub fn to_vec_pretty<T>(value: &T) -> Result<Vec<u8>>
162where
163 T: ?Sized + Serialize,
164{
165 #[cfg(not(feature = "simd_json"))]
166 let result = serde_json::to_vec_pretty(value)?;
167 #[cfg(feature = "simd_json")]
168 let result = simd_json::to_vec_pretty(value)?;
169 Ok(result)
170}
171
172#[allow(clippy::missing_errors_doc)]
174pub fn to_value<T>(value: T) -> Result<Value>
175where
176 T: Serialize,
177{
178 #[cfg(not(feature = "simd_json"))]
179 let result = serde_json::to_value(value)?;
180 #[cfg(feature = "simd_json")]
181 let result = simd_json::serde::to_owned_value(value)?;
182 Ok(result)
183}
184
185#[cfg(test)]
186#[track_caller]
187pub(crate) fn assert_json<T>(data: &T, json: crate::json::Value)
188where
189 T: Serialize + for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug,
190{
191 let serialized = to_value(data).unwrap();
193 assert!(
194 serialized == json,
195 "data->JSON serialization failed\nexpected: {json:?}\n got: {serialized:?}"
196 );
197
198 let deserialized = from_value::<T>(json).unwrap();
200 assert!(
201 &deserialized == data,
202 "JSON->data deserialization failed\nexpected: {data:?}\n got: {deserialized:?}"
203 );
204}