1#![cfg_attr(not(feature = "std"), no_std)]
26#![warn(missing_docs)]
27
28extern crate alloc;
29
30use alloc::string::String;
31use alloc::vec::Vec;
32
33use crate::{VArray, VChar, VNumber, VObject, VString, Value};
34use facet_core::Facet;
35use facet_format::{FormatSerializer, ScalarValue, SerializeError, serialize_root};
36use facet_reflect::Peek;
37
38use crate::VBytes;
39
40#[derive(Debug)]
42pub struct ToValueError {
43 msg: String,
44}
45
46impl ToValueError {
47 pub fn new(msg: impl Into<String>) -> Self {
49 Self { msg: msg.into() }
50 }
51}
52
53impl core::fmt::Display for ToValueError {
54 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55 f.write_str(&self.msg)
56 }
57}
58
59impl core::error::Error for ToValueError {}
60
61struct ValueSerializer {
63 stack: Vec<StackFrame>,
64 result: Option<Value>,
65}
66
67enum StackFrame {
68 Object {
69 obj: VObject,
70 pending_key: Option<String>,
71 },
72 Array {
73 arr: VArray,
74 },
75}
76
77impl ValueSerializer {
78 fn new() -> Self {
79 Self {
80 stack: Vec::new(),
81 result: None,
82 }
83 }
84
85 fn finish(self) -> Value {
86 self.result.unwrap_or(Value::NULL)
87 }
88
89 fn emit(&mut self, value: Value) {
90 match self.stack.last_mut() {
91 Some(StackFrame::Object { obj, pending_key }) => {
92 if let Some(key) = pending_key.take() {
93 obj.insert(key, value);
94 } else {
95 panic!("emit called on object without pending key");
96 }
97 }
98 Some(StackFrame::Array { arr }) => {
99 arr.push(value);
100 }
101 None => {
102 self.result = Some(value);
103 }
104 }
105 }
106}
107
108impl FormatSerializer for ValueSerializer {
109 type Error = ToValueError;
110
111 fn begin_struct(&mut self) -> Result<(), Self::Error> {
112 self.stack.push(StackFrame::Object {
113 obj: VObject::new(),
114 pending_key: None,
115 });
116 Ok(())
117 }
118
119 fn field_key(&mut self, key: &str) -> Result<(), Self::Error> {
120 match self.stack.last_mut() {
121 Some(StackFrame::Object { pending_key, .. }) => {
122 *pending_key = Some(key.to_string());
123 Ok(())
124 }
125 _ => Err(ToValueError::new("field_key called outside of object")),
126 }
127 }
128
129 fn end_struct(&mut self) -> Result<(), Self::Error> {
130 match self.stack.pop() {
131 Some(StackFrame::Object { obj, .. }) => {
132 self.emit(obj.into());
133 Ok(())
134 }
135 _ => Err(ToValueError::new(
136 "end_struct called without matching begin_struct",
137 )),
138 }
139 }
140
141 fn begin_seq(&mut self) -> Result<(), Self::Error> {
142 self.stack.push(StackFrame::Array { arr: VArray::new() });
143 Ok(())
144 }
145
146 fn end_seq(&mut self) -> Result<(), Self::Error> {
147 match self.stack.pop() {
148 Some(StackFrame::Array { arr }) => {
149 self.emit(arr.into());
150 Ok(())
151 }
152 _ => Err(ToValueError::new(
153 "end_seq called without matching begin_seq",
154 )),
155 }
156 }
157
158 fn scalar(&mut self, scalar: ScalarValue<'_>) -> Result<(), Self::Error> {
159 let value = match scalar {
160 ScalarValue::Unit | ScalarValue::Null => Value::NULL,
161 ScalarValue::Bool(b) => Value::from(b),
162 ScalarValue::Char(c) => VChar::new(c).into(),
163 ScalarValue::I64(n) => VNumber::from_i64(n).into(),
164 ScalarValue::U64(n) => VNumber::from_u64(n).into(),
165 ScalarValue::I128(n) => VNumber::from_i128(n).into(),
166 ScalarValue::U128(n) => VNumber::from_u128(n).into(),
167 ScalarValue::F64(n) => VNumber::from_f64(n).into(),
168 ScalarValue::Str(s) => VString::new(&s).into(),
169 ScalarValue::Bytes(b) => VBytes::new(b.as_ref()).into(),
170 _ => return Err(ToValueError::new("unsupported scalar value kind")),
171 };
172 self.emit(value);
173 Ok(())
174 }
175}
176
177pub fn to_value<'facet, T: Facet<'facet>>(
179 value: &T,
180) -> Result<Value, SerializeError<ToValueError>> {
181 let mut serializer = ValueSerializer::new();
182 serialize_root(&mut serializer, Peek::new(value))?;
183 Ok(serializer.finish())
184}
185
186pub fn peek_to_value<'mem, 'facet>(
188 peek: Peek<'mem, 'facet>,
189) -> Result<Value, SerializeError<ToValueError>> {
190 let mut serializer = ValueSerializer::new();
191 serialize_root(&mut serializer, peek)?;
192 Ok(serializer.finish())
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198 use alloc::collections::BTreeMap;
199 use alloc::string::ToString;
200 use alloc::vec;
201
202 #[test]
203 fn test_to_value_primitives() {
204 let v = to_value(&true).unwrap();
205 assert_eq!(v.as_bool(), Some(true));
206
207 let v = to_value(&false).unwrap();
208 assert_eq!(v.as_bool(), Some(false));
209
210 let v = to_value(&42i32).unwrap();
211 assert_eq!(v.as_number().unwrap().to_i64(), Some(42));
212
213 let v = to_value(&123u64).unwrap();
214 assert_eq!(v.as_number().unwrap().to_u64(), Some(123));
215
216 let v = to_value(&2.5f64).unwrap();
217 assert!((v.as_number().unwrap().to_f64().unwrap() - 2.5).abs() < 0.001);
218
219 let s = "hello".to_string();
220 let v = to_value(&s).unwrap();
221 assert_eq!(v.as_string().unwrap().as_str(), "hello");
222 }
223
224 #[test]
225 fn test_to_value_option() {
226 let some: Option<i32> = Some(42);
227 let v = to_value(&some).unwrap();
228 assert_eq!(v.as_number().unwrap().to_i64(), Some(42));
229
230 let none: Option<i32> = None;
231 let v = to_value(&none).unwrap();
232 assert!(v.is_null());
233 }
234
235 #[test]
236 fn test_to_value_vec() {
237 let vec = vec![1i32, 2, 3];
238 let v = to_value(&vec).unwrap();
239
240 let arr = v.as_array().unwrap();
241 assert_eq!(arr.len(), 3);
242 assert_eq!(arr.get(0).unwrap().as_number().unwrap().to_i64(), Some(1));
243 assert_eq!(arr.get(1).unwrap().as_number().unwrap().to_i64(), Some(2));
244 assert_eq!(arr.get(2).unwrap().as_number().unwrap().to_i64(), Some(3));
245 }
246
247 #[test]
248 fn test_to_value_map() {
249 let mut map: BTreeMap<String, i32> = BTreeMap::new();
250 map.insert("a".to_string(), 1);
251 map.insert("b".to_string(), 2);
252
253 let v = to_value(&map).unwrap();
254
255 let obj = v.as_object().unwrap();
256 assert_eq!(obj.get("a").unwrap().as_number().unwrap().to_i64(), Some(1));
257 assert_eq!(obj.get("b").unwrap().as_number().unwrap().to_i64(), Some(2));
258 }
259
260 #[test]
261 fn test_to_value_nested() {
262 let vec = vec![Some(1i32), None, Some(3)];
263 let v = to_value(&vec).unwrap();
264
265 let arr = v.as_array().unwrap();
266 assert_eq!(arr.len(), 3);
267 assert_eq!(arr.get(0).unwrap().as_number().unwrap().to_i64(), Some(1));
268 assert!(arr.get(1).unwrap().is_null());
269 assert_eq!(arr.get(2).unwrap().as_number().unwrap().to_i64(), Some(3));
270 }
271
272 #[test]
273 fn test_roundtrip_value() {
274 let original = crate::value!({
275 "name": "Alice",
276 "age": 30,
277 "active": true
278 });
279
280 let v = to_value(&original).unwrap();
281 assert_eq!(v, original);
282 }
283
284 #[test]
285 fn test_to_value_char() {
286 let c = 'λ';
288 let v = to_value(&c).unwrap();
289 assert_eq!(v.value_type(), crate::ValueType::Char);
290 assert_eq!(v.as_char(), Some('λ'));
291 }
292
293 #[test]
294 fn test_scalar_128_mapping_preserves_number() {
295 use facet_format::ScalarValue;
296
297 let mut ser = ValueSerializer::new();
302 ser.scalar(ScalarValue::U128(u128::MAX)).unwrap();
303 let v = ser.finish();
304 assert_eq!(v.value_type(), crate::ValueType::Number);
305 assert_eq!(v.as_number().unwrap().to_u128(), Some(u128::MAX));
306
307 let mut ser = ValueSerializer::new();
308 ser.scalar(ScalarValue::I128(i128::MIN)).unwrap();
309 let v = ser.finish();
310 assert_eq!(v.value_type(), crate::ValueType::Number);
311 assert_eq!(v.as_number().unwrap().to_i128(), Some(i128::MIN));
312 }
313
314 #[test]
315 fn test_roundtrip_128_and_char_struct() {
316 use crate::from_value;
317 use facet::Facet;
318
319 #[derive(Debug, Facet, PartialEq)]
320 struct Wide {
321 big_u: u128,
322 big_i: i128,
323 letter: char,
324 }
325
326 let original = Wide {
327 big_u: u128::MAX,
328 big_i: i128::MIN,
329 letter: '🦀',
330 };
331
332 let v = to_value(&original).unwrap();
334 let obj = v.as_object().unwrap();
335 assert_eq!(obj.get("letter").unwrap().as_char(), Some('🦀'));
336
337 let back: Wide = from_value(v).unwrap();
340 assert_eq!(back, original);
341 }
342}