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, 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) => VString::new(&c.to_string()).into(),
163 ScalarValue::I64(n) => VNumber::from_i64(n).into(),
164 ScalarValue::U64(n) => VNumber::from_u64(n).into(),
165 ScalarValue::I128(n) => VString::new(&n.to_string()).into(),
166 ScalarValue::U128(n) => VString::new(&n.to_string()).into(),
167 ScalarValue::F64(n) => VNumber::from_f64(n).map(Into::into).unwrap_or(Value::NULL),
168 ScalarValue::Str(s) => VString::new(&s).into(),
169 ScalarValue::Bytes(b) => VBytes::new(b.as_ref()).into(),
170 };
171 self.emit(value);
172 Ok(())
173 }
174}
175
176pub fn to_value<'facet, T: Facet<'facet>>(
178 value: &T,
179) -> Result<Value, SerializeError<ToValueError>> {
180 let mut serializer = ValueSerializer::new();
181 serialize_root(&mut serializer, Peek::new(value))?;
182 Ok(serializer.finish())
183}
184
185pub fn peek_to_value<'mem, 'facet>(
187 peek: Peek<'mem, 'facet>,
188) -> Result<Value, SerializeError<ToValueError>> {
189 let mut serializer = ValueSerializer::new();
190 serialize_root(&mut serializer, peek)?;
191 Ok(serializer.finish())
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197 use alloc::collections::BTreeMap;
198 use alloc::string::ToString;
199 use alloc::vec;
200
201 #[test]
202 fn test_to_value_primitives() {
203 let v = to_value(&true).unwrap();
204 assert_eq!(v.as_bool(), Some(true));
205
206 let v = to_value(&false).unwrap();
207 assert_eq!(v.as_bool(), Some(false));
208
209 let v = to_value(&42i32).unwrap();
210 assert_eq!(v.as_number().unwrap().to_i64(), Some(42));
211
212 let v = to_value(&123u64).unwrap();
213 assert_eq!(v.as_number().unwrap().to_u64(), Some(123));
214
215 let v = to_value(&2.5f64).unwrap();
216 assert!((v.as_number().unwrap().to_f64().unwrap() - 2.5).abs() < 0.001);
217
218 let s = "hello".to_string();
219 let v = to_value(&s).unwrap();
220 assert_eq!(v.as_string().unwrap().as_str(), "hello");
221 }
222
223 #[test]
224 fn test_to_value_option() {
225 let some: Option<i32> = Some(42);
226 let v = to_value(&some).unwrap();
227 assert_eq!(v.as_number().unwrap().to_i64(), Some(42));
228
229 let none: Option<i32> = None;
230 let v = to_value(&none).unwrap();
231 assert!(v.is_null());
232 }
233
234 #[test]
235 fn test_to_value_vec() {
236 let vec = vec![1i32, 2, 3];
237 let v = to_value(&vec).unwrap();
238
239 let arr = v.as_array().unwrap();
240 assert_eq!(arr.len(), 3);
241 assert_eq!(arr.get(0).unwrap().as_number().unwrap().to_i64(), Some(1));
242 assert_eq!(arr.get(1).unwrap().as_number().unwrap().to_i64(), Some(2));
243 assert_eq!(arr.get(2).unwrap().as_number().unwrap().to_i64(), Some(3));
244 }
245
246 #[test]
247 fn test_to_value_map() {
248 let mut map: BTreeMap<String, i32> = BTreeMap::new();
249 map.insert("a".to_string(), 1);
250 map.insert("b".to_string(), 2);
251
252 let v = to_value(&map).unwrap();
253
254 let obj = v.as_object().unwrap();
255 assert_eq!(obj.get("a").unwrap().as_number().unwrap().to_i64(), Some(1));
256 assert_eq!(obj.get("b").unwrap().as_number().unwrap().to_i64(), Some(2));
257 }
258
259 #[test]
260 fn test_to_value_nested() {
261 let vec = vec![Some(1i32), None, Some(3)];
262 let v = to_value(&vec).unwrap();
263
264 let arr = v.as_array().unwrap();
265 assert_eq!(arr.len(), 3);
266 assert_eq!(arr.get(0).unwrap().as_number().unwrap().to_i64(), Some(1));
267 assert!(arr.get(1).unwrap().is_null());
268 assert_eq!(arr.get(2).unwrap().as_number().unwrap().to_i64(), Some(3));
269 }
270
271 #[test]
272 fn test_roundtrip_value() {
273 let original = crate::value!({
274 "name": "Alice",
275 "age": 30,
276 "active": true
277 });
278
279 let v = to_value(&original).unwrap();
280 assert_eq!(v, original);
281 }
282}