Skip to main content

jstrict/convert/
sonic_rs.rs

1use crate::{Array, Object, Value, object::Entry};
2use sonic_rs::value::ValueRef;
3
4impl Value {
5	/// Converts a [`sonic_rs::Value`] into a `Value`.
6	///
7	/// # Example
8	///
9	/// ```
10	/// // First we create a `sonic_rs` value.
11	/// let a = sonic_rs::json!({
12	///   "foo": 1,
13	///   "bar": [2, 3]
14	/// });
15	///
16	/// // We convert the `sonic_rs` value into a `jstrict` value.
17	/// let b = jstrict::Value::from_sonic_rs(&a);
18	///
19	/// // We convert it back into a `sonic_rs` value.
20	/// let _ = jstrict::Value::into_sonic_rs(b);
21	/// ```
22	#[must_use]
23	pub fn from_sonic_rs(value: &sonic_rs::Value) -> Self {
24		match value.as_ref() {
25			ValueRef::Null => Self::Null,
26			ValueRef::Bool(b) => Self::Boolean(b),
27			ValueRef::Number(n) => Self::Number(n.into()),
28			ValueRef::String(s) => Self::String(s.into()),
29			ValueRef::Array(a) => {
30				let mut out = Array::with_capacity(a.len());
31				for v in a {
32					out.push(Self::from_sonic_rs(v));
33				}
34				Self::Array(out)
35			}
36			ValueRef::Object(o) => {
37				let mut out = Object::with_capacity(o.len());
38				for (k, v) in o {
39					out.push_entry(Entry::new(k.into(), Self::from_sonic_rs(v)));
40				}
41				Self::Object(out)
42			}
43		}
44	}
45
46	/// Converts a `Value` into a [`sonic_rs::Value`].
47	///
48	/// # Example
49	///
50	/// ```
51	/// // First we create a `sonic_rs` value.
52	/// let a = sonic_rs::json!({
53	///   "foo": 1,
54	///   "bar": [2, 3]
55	/// });
56	///
57	/// // We convert the `sonic_rs` value into a `jstrict` value.
58	/// let b = jstrict::Value::from_sonic_rs(&a);
59	///
60	/// // We convert it back into a `sonic_rs` value.
61	/// let _ = jstrict::Value::into_sonic_rs(b);
62	/// ```
63	#[must_use]
64	pub fn into_sonic_rs(self) -> sonic_rs::Value {
65		match self {
66			Self::Null => sonic_rs::Value::default(),
67			Self::Boolean(b) => sonic_rs::Value::from(b),
68			Self::Number(n) => sonic_rs::Value::from(sonic_rs::Number::from(n)),
69			Self::String(s) => sonic_rs::Value::from(s.as_str()),
70			Self::Array(a) => {
71				let mut out = sonic_rs::Array::with_capacity(a.len());
72				for v in a {
73					out.push(Value::into_sonic_rs(v));
74				}
75				sonic_rs::Value::from(out)
76			}
77			Self::Object(o) => {
78				let mut out = sonic_rs::Object::with_capacity(o.len());
79				for Entry { key, value } in o {
80					out.insert(&key.as_str(), Value::into_sonic_rs(value));
81				}
82				sonic_rs::Value::from(out)
83			}
84		}
85	}
86}
87
88impl From<sonic_rs::Value> for Value {
89	#[inline(always)]
90	fn from(value: sonic_rs::Value) -> Self {
91		Self::from_sonic_rs(&value)
92	}
93}
94
95impl From<Value> for sonic_rs::Value {
96	fn from(value: Value) -> Self {
97		value.into_sonic_rs()
98	}
99}
100
101#[cfg(test)]
102mod tests {
103	use super::*;
104	use sonic_rs::{JsonContainerTrait, JsonValueTrait};
105
106	#[test]
107	fn round_trip() {
108		let src: sonic_rs::Value = sonic_rs::from_str(
109			r#"{"n":null,"b":true,"i":-7,"u":42,"f":1.5,"s":"hi","a":[1,2,3],"o":{"k":"v"}}"#,
110		)
111		.unwrap();
112
113		let mid = Value::from_sonic_rs(&src);
114		let back = mid.into_sonic_rs();
115
116		assert!(back.get("n").unwrap().is_null());
117		assert_eq!(back.get("b").unwrap().as_bool(), Some(true));
118		assert_eq!(back.get("i").unwrap().as_i64(), Some(-7));
119		assert_eq!(back.get("u").unwrap().as_u64(), Some(42));
120		assert_eq!(back.get("f").unwrap().as_f64(), Some(1.5));
121		assert_eq!(back.get("s").unwrap().as_str(), Some("hi"));
122		assert_eq!(back.get("a").unwrap().as_array().unwrap().len(), 3);
123		assert_eq!(back.get("o").unwrap().get("k").unwrap().as_str(), Some("v"));
124	}
125}