1use alloc::format;
31use alloc::string::{String, ToString};
32use alloc::vec::Vec;
33
34use facet_core::{
35 Def, Facet, NumericType, PrimitiveType, Shape, StructKind, TextualType, Type, UserType, Variant,
36};
37use facet_reflect::{Partial, ReflectError};
38
39use crate::{VNumber, Value, ValueType};
40
41#[derive(Clone, Debug, PartialEq, Eq)]
43pub enum PathSegment {
44 Field(String),
46 Variant(String),
48 Index(usize),
50}
51
52impl core::fmt::Display for PathSegment {
53 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
54 match self {
55 PathSegment::Field(name) => write!(f, ".{name}"),
56 PathSegment::Variant(name) => write!(f, "::{name}"),
57 PathSegment::Index(i) => write!(f, "[{i}]"),
58 }
59 }
60}
61
62#[derive(Debug)]
64pub struct ValueError {
65 pub kind: ValueErrorKind,
67 pub source_path: Vec<PathSegment>,
69 pub dest_path: Vec<PathSegment>,
71 pub target_shape: Option<&'static Shape>,
73 pub source_value: Option<Value>,
75}
76
77impl core::fmt::Display for ValueError {
78 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
79 if self.source_path.is_empty() {
80 write!(f, "{}", self.kind)
81 } else {
82 write!(f, "at {}: {}", self.source_path_string(), self.kind)
83 }
84 }
85}
86
87impl ValueError {
88 pub const fn new(kind: ValueErrorKind) -> Self {
90 Self {
91 kind,
92 source_path: Vec::new(),
93 dest_path: Vec::new(),
94 target_shape: None,
95 source_value: None,
96 }
97 }
98
99 pub const fn with_shape(mut self, shape: &'static Shape) -> Self {
101 self.target_shape = Some(shape);
102 self
103 }
104
105 pub fn with_value(mut self, value: Value) -> Self {
107 self.source_value = Some(value);
108 self
109 }
110
111 pub fn with_path(mut self, segment: PathSegment) -> Self {
113 self.source_path.insert(0, segment.clone());
114 self.dest_path.insert(0, segment);
115 self
116 }
117
118 pub fn source_path_string(&self) -> String {
120 if self.source_path.is_empty() {
121 "<root>".into()
122 } else {
123 use core::fmt::Write;
124 let mut s = String::new();
125 for seg in &self.source_path {
126 let _ = write!(s, "{seg}");
127 }
128 s
129 }
130 }
131
132 pub fn dest_path_string(&self) -> String {
134 if self.dest_path.is_empty() {
135 "<root>".into()
136 } else {
137 use core::fmt::Write;
138 let mut s = String::new();
139 for seg in &self.dest_path {
140 let _ = write!(s, "{seg}");
141 }
142 s
143 }
144 }
145}
146
147#[cfg(feature = "std")]
148impl core::error::Error for ValueError {}
149
150#[derive(Debug)]
152pub enum ValueErrorKind {
153 TypeMismatch {
155 expected: &'static str,
157 got: ValueType,
159 },
160 MissingField {
162 field: &'static str,
164 },
165 UnknownField {
167 field: String,
169 },
170 NumberOutOfRange {
172 message: String,
174 },
175 Reflect(ReflectError),
177 Unsupported {
179 message: String,
181 },
182}
183
184impl core::fmt::Display for ValueErrorKind {
185 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
186 match self {
187 ValueErrorKind::TypeMismatch { expected, got } => {
188 write!(f, "type mismatch: expected {expected}, got {got:?}")
189 }
190 ValueErrorKind::MissingField { field } => {
191 write!(f, "missing required field `{field}`")
192 }
193 ValueErrorKind::UnknownField { field } => {
194 write!(f, "unknown field `{field}`")
195 }
196 ValueErrorKind::NumberOutOfRange { message } => {
197 write!(f, "number out of range: {message}")
198 }
199 ValueErrorKind::Reflect(e) => write!(f, "reflection error: {e}"),
200 ValueErrorKind::Unsupported { message } => {
201 write!(f, "unsupported: {message}")
202 }
203 }
204 }
205}
206
207impl From<ReflectError> for ValueError {
208 fn from(err: ReflectError) -> Self {
209 ValueError::new(ValueErrorKind::Reflect(err))
210 }
211}
212
213pub type Result<T> = core::result::Result<T, ValueError>;
215
216pub fn from_value<'facet, T: Facet<'facet>>(value: Value) -> Result<T> {
238 let partial = Partial::alloc::<T>().map_err(|e| {
239 ValueError::from(e)
240 .with_shape(T::SHAPE)
241 .with_value(value.clone())
242 })?;
243 let partial = deserialize_value_into(&value, partial)
244 .map_err(|e| e.with_shape(T::SHAPE).with_value(value.clone()))?;
245 let heap_value = partial.build().map_err(|e| {
246 ValueError::from(e)
247 .with_shape(T::SHAPE)
248 .with_value(value.clone())
249 })?;
250 heap_value.materialize().map_err(|e| {
251 ValueError::from(e)
252 .with_shape(T::SHAPE)
253 .with_value(value.clone())
254 })
255}
256
257fn deserialize_value_into<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
259 let mut partial = partial;
260 let shape = partial.shape();
261
262 if matches!(&shape.def, Def::Option(_)) {
264 return deserialize_option(value, partial);
265 }
266
267 if matches!(&shape.def, Def::Pointer(_)) {
269 return deserialize_pointer(value, partial);
270 }
271
272 #[cfg(feature = "alloc")]
274 if shape.proxy.is_some() {
275 let (partial_returned, has_proxy) = partial.begin_custom_deserialization_from_shape()?;
276 partial = partial_returned;
277 if has_proxy {
278 partial = deserialize_value_into(value, partial)?;
279 partial = partial.end()?;
280 return Ok(partial);
281 }
282 }
283
284 if shape.builder_shape.is_some() {
286 partial = partial.begin_inner()?;
287 partial = deserialize_value_into(value, partial)?;
288 partial = partial.end()?;
289 return Ok(partial);
290 }
291
292 if shape.inner.is_some()
295 && !matches!(
296 &shape.def,
297 Def::List(_) | Def::Map(_) | Def::Set(_) | Def::Array(_)
298 )
299 {
300 partial = partial.begin_inner()?;
301 partial = deserialize_value_into(value, partial)?;
302 partial = partial.end()?;
303 return Ok(partial);
304 }
305
306 match &shape.ty {
308 Type::User(UserType::Struct(struct_def)) => {
309 if struct_def.kind == StructKind::Tuple {
310 return deserialize_tuple(value, partial);
311 }
312 return deserialize_struct(value, partial);
313 }
314 Type::User(UserType::Enum(_)) => return deserialize_enum(value, partial),
315 _ => {}
316 }
317
318 match &shape.def {
320 Def::Scalar => deserialize_scalar(value, partial),
321 Def::List(_) => deserialize_list(value, partial),
322 Def::Map(_) => deserialize_map(value, partial),
323 Def::Array(_) => deserialize_array(value, partial),
324 Def::Set(_) => deserialize_set(value, partial),
325 Def::DynamicValue(_) => {
326 partial = partial.set(value.clone())?;
328 Ok(partial)
329 }
330 _ => Err(ValueError::new(ValueErrorKind::Unsupported {
331 message: format!("unsupported shape def: {:?}", shape.def),
332 })),
333 }
334}
335
336fn deserialize_scalar<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
338 let mut partial = partial;
339 let shape = partial.shape();
340
341 match value.value_type() {
342 ValueType::Null => {
343 partial = partial.set_default()?;
344 Ok(partial)
345 }
346 ValueType::Bool => {
347 let b = value.as_bool().unwrap();
348 partial = partial.set(b)?;
349 Ok(partial)
350 }
351 ValueType::Number => {
352 let num = value.as_number().unwrap();
353 if shape.type_identifier == "String" {
357 let s = if let Some(i) = num.to_i64() {
358 format!("{i}")
359 } else if let Some(u) = num.to_u64() {
360 format!("{u}")
361 } else if let Some(f) = num.to_f64() {
362 format!("{f}")
363 } else {
364 return Err(ValueError::new(ValueErrorKind::TypeMismatch {
365 expected: "String",
366 got: ValueType::Number,
367 }));
368 };
369 partial = partial.set(s)?;
370 Ok(partial)
371 } else {
372 set_number(num, partial, shape)
373 }
374 }
375 ValueType::String => {
376 let s = value.as_string().unwrap();
377 if shape.vtable.has_parse() {
379 partial = partial.parse_from_str(s.as_str())?;
380 } else {
381 partial = partial.set(s.as_str().to_string())?;
382 }
383 Ok(partial)
384 }
385 ValueType::Bytes => {
386 let bytes = value.as_bytes().unwrap();
387 partial = partial.set(bytes.as_slice().to_vec())?;
388 Ok(partial)
389 }
390 other => Err(ValueError::new(ValueErrorKind::TypeMismatch {
391 expected: shape.type_identifier,
392 got: other,
393 })),
394 }
395}
396
397fn set_number<'p>(num: &VNumber, partial: Partial<'p>, shape: &Shape) -> Result<Partial<'p>> {
399 use facet_core::{NumericType, PrimitiveType, ShapeLayout};
400
401 let mut partial = partial;
402 let size = match shape.layout {
403 ShapeLayout::Sized(layout) => layout.size(),
404 _ => {
405 return Err(ValueError::new(ValueErrorKind::Unsupported {
406 message: "unsized numeric type".into(),
407 }));
408 }
409 };
410
411 match &shape.ty {
412 Type::Primitive(PrimitiveType::Numeric(NumericType::Integer { signed: true })) => {
413 let val = num.to_i64().ok_or_else(|| {
414 ValueError::new(ValueErrorKind::NumberOutOfRange {
415 message: "value cannot be represented as i64".into(),
416 })
417 })?;
418 if shape.type_identifier == "isize" {
420 let v = isize::try_from(val).map_err(|_| {
421 ValueError::new(ValueErrorKind::NumberOutOfRange {
422 message: format!("{val} out of range for isize"),
423 })
424 })?;
425 partial = partial.set(v)?;
426 } else {
427 match size {
428 1 => {
429 let v = i8::try_from(val).map_err(|_| {
430 ValueError::new(ValueErrorKind::NumberOutOfRange {
431 message: format!("{val} out of range for i8"),
432 })
433 })?;
434 partial = partial.set(v)?;
435 }
436 2 => {
437 let v = i16::try_from(val).map_err(|_| {
438 ValueError::new(ValueErrorKind::NumberOutOfRange {
439 message: format!("{val} out of range for i16"),
440 })
441 })?;
442 partial = partial.set(v)?;
443 }
444 4 => {
445 let v = i32::try_from(val).map_err(|_| {
446 ValueError::new(ValueErrorKind::NumberOutOfRange {
447 message: format!("{val} out of range for i32"),
448 })
449 })?;
450 partial = partial.set(v)?;
451 }
452 8 => {
453 partial = partial.set(val)?;
454 }
455 16 => {
456 partial = partial.set(val as i128)?;
457 }
458 _ => {
459 return Err(ValueError::new(ValueErrorKind::Unsupported {
460 message: format!("unexpected integer size: {size}"),
461 }));
462 }
463 }
464 }
465 }
466 Type::Primitive(PrimitiveType::Numeric(NumericType::Integer { signed: false })) => {
467 let val = num.to_u64().ok_or_else(|| {
468 ValueError::new(ValueErrorKind::NumberOutOfRange {
469 message: "value cannot be represented as u64".into(),
470 })
471 })?;
472 if shape.type_identifier == "usize" {
474 let v = usize::try_from(val).map_err(|_| {
475 ValueError::new(ValueErrorKind::NumberOutOfRange {
476 message: format!("{val} out of range for usize"),
477 })
478 })?;
479 partial = partial.set(v)?;
480 } else {
481 match size {
482 1 => {
483 let v = u8::try_from(val).map_err(|_| {
484 ValueError::new(ValueErrorKind::NumberOutOfRange {
485 message: format!("{val} out of range for u8"),
486 })
487 })?;
488 partial = partial.set(v)?;
489 }
490 2 => {
491 let v = u16::try_from(val).map_err(|_| {
492 ValueError::new(ValueErrorKind::NumberOutOfRange {
493 message: format!("{val} out of range for u16"),
494 })
495 })?;
496 partial = partial.set(v)?;
497 }
498 4 => {
499 let v = u32::try_from(val).map_err(|_| {
500 ValueError::new(ValueErrorKind::NumberOutOfRange {
501 message: format!("{val} out of range for u32"),
502 })
503 })?;
504 partial = partial.set(v)?;
505 }
506 8 => {
507 partial = partial.set(val)?;
508 }
509 16 => {
510 partial = partial.set(val as u128)?;
511 }
512 _ => {
513 return Err(ValueError::new(ValueErrorKind::Unsupported {
514 message: format!("unexpected integer size: {size}"),
515 }));
516 }
517 }
518 }
519 }
520 Type::Primitive(PrimitiveType::Numeric(NumericType::Float)) => {
521 let val = num.to_f64_lossy();
522 match size {
523 4 => {
524 partial = partial.set(val as f32)?;
525 }
526 8 => {
527 partial = partial.set(val)?;
528 }
529 _ => {
530 return Err(ValueError::new(ValueErrorKind::Unsupported {
531 message: format!("unexpected float size: {size}"),
532 }));
533 }
534 }
535 }
536 _ => {
537 return Err(ValueError::new(ValueErrorKind::TypeMismatch {
538 expected: shape.type_identifier,
539 got: ValueType::Number,
540 }));
541 }
542 }
543 Ok(partial)
544}
545
546fn deserialize_struct<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
548 let mut partial = partial;
549 let obj = value.as_object().ok_or_else(|| {
550 ValueError::new(ValueErrorKind::TypeMismatch {
551 expected: "object",
552 got: value.value_type(),
553 })
554 })?;
555
556 let struct_def = match &partial.shape().ty {
557 Type::User(UserType::Struct(s)) => s,
558 _ => {
559 return Err(ValueError::new(ValueErrorKind::Unsupported {
560 message: "expected struct type".into(),
561 }));
562 }
563 };
564
565 let deny_unknown_fields = partial.shape().has_deny_unknown_fields_attr();
566
567 let has_flattened = struct_def.fields.iter().any(|f| f.is_flattened());
569
570 if has_flattened {
571 return deserialize_struct_with_flatten(obj, partial, struct_def, deny_unknown_fields);
572 }
573
574 let num_fields = struct_def.fields.len();
576 let mut fields_set = alloc::vec![false; num_fields];
577
578 for (key, val) in obj.iter() {
580 let key_str = key.as_str();
581
582 let field_info = struct_def
584 .fields
585 .iter()
586 .enumerate()
587 .find(|(_, f)| f.name == key_str || f.alias == Some(key_str));
588
589 if let Some((idx, field)) = field_info {
590 partial = partial.begin_field(field.name)?;
591 #[cfg(feature = "alloc")]
593 if field.proxy_convert_in_fn().is_some() {
594 partial = partial.begin_custom_deserialization()?;
595 partial = deserialize_value_into(val, partial)?;
596 partial = partial.end()?;
597 } else {
598 partial = deserialize_value_into(val, partial)?;
599 }
600 #[cfg(not(feature = "alloc"))]
601 {
602 partial = deserialize_value_into(val, partial)?;
603 }
604 partial = partial.end()?;
605 fields_set[idx] = true;
606 } else if deny_unknown_fields {
607 return Err(ValueError::new(ValueErrorKind::UnknownField {
608 field: key_str.to_string(),
609 }));
610 }
611 }
613
614 for (idx, field) in struct_def.fields.iter().enumerate() {
616 if fields_set[idx] {
617 continue;
618 }
619
620 partial = partial
622 .set_nth_field_to_default(idx)
623 .map_err(|_| ValueError::new(ValueErrorKind::MissingField { field: field.name }))?;
624 }
625
626 Ok(partial)
627}
628
629fn deserialize_struct_with_flatten<'p>(
631 obj: &crate::VObject,
632 mut partial: Partial<'p>,
633 struct_def: &'static facet_core::StructType,
634 deny_unknown_fields: bool,
635) -> Result<Partial<'p>> {
636 use alloc::collections::BTreeMap;
637
638 let num_fields = struct_def.fields.len();
639 let mut fields_set = alloc::vec![false; num_fields];
640
641 let mut flatten_keys: BTreeMap<&str, (usize, &str)> = BTreeMap::new();
644
645 for (idx, field) in struct_def.fields.iter().enumerate() {
647 if !field.is_flattened() {
648 continue;
649 }
650
651 let inner_shape = field.shape.get();
653 if let Type::User(UserType::Struct(inner_struct)) = &inner_shape.ty {
654 for inner_field in inner_struct.fields.iter() {
655 let key_name = inner_field.rename.unwrap_or(inner_field.name);
657 flatten_keys.insert(key_name, (idx, inner_field.name));
658 }
659 }
660 }
661
662 let mut flatten_values: Vec<BTreeMap<String, Value>> =
664 (0..num_fields).map(|_| BTreeMap::new()).collect();
665
666 for (key, val) in obj.iter() {
668 let key_str = key.as_str();
669
670 let direct_field =
672 struct_def.fields.iter().enumerate().find(|(_, f)| {
673 !f.is_flattened() && (f.name == key_str || f.alias == Some(key_str))
674 });
675
676 if let Some((idx, field)) = direct_field {
677 partial = partial.begin_field(field.name)?;
678 #[cfg(feature = "alloc")]
680 if field.proxy_convert_in_fn().is_some() {
681 partial = partial.begin_custom_deserialization()?;
682 partial = deserialize_value_into(val, partial)?;
683 partial = partial.end()?;
684 } else {
685 partial = deserialize_value_into(val, partial)?;
686 }
687 #[cfg(not(feature = "alloc"))]
688 {
689 partial = deserialize_value_into(val, partial)?;
690 }
691 partial = partial.end()?;
692 fields_set[idx] = true;
693 continue;
694 }
695
696 if let Some(&(flatten_idx, inner_name)) = flatten_keys.get(key_str) {
698 flatten_values[flatten_idx].insert(inner_name.to_string(), val.clone());
699 fields_set[flatten_idx] = true;
700 continue;
701 }
702
703 if deny_unknown_fields {
705 return Err(ValueError::new(ValueErrorKind::UnknownField {
706 field: key_str.to_string(),
707 }));
708 }
709 }
711
712 for (idx, field) in struct_def.fields.iter().enumerate() {
714 if !field.is_flattened() {
715 continue;
716 }
717
718 if !flatten_values[idx].is_empty() {
719 let mut synthetic_obj = crate::VObject::new();
721 let values = core::mem::take(&mut flatten_values[idx]);
722 for (k, v) in values {
723 synthetic_obj.insert(k, v);
724 }
725 let synthetic_value = Value::from(synthetic_obj);
726
727 partial = partial.begin_field(field.name)?;
728 partial = deserialize_value_into(&synthetic_value, partial)?;
729 partial = partial.end()?;
730 fields_set[idx] = true;
731 }
732 }
733
734 for (idx, field) in struct_def.fields.iter().enumerate() {
736 if fields_set[idx] {
737 continue;
738 }
739
740 partial = partial
742 .set_nth_field_to_default(idx)
743 .map_err(|_| ValueError::new(ValueErrorKind::MissingField { field: field.name }))?;
744 }
745
746 Ok(partial)
747}
748
749fn deserialize_tuple<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
751 let mut partial = partial;
752 let arr = value.as_array().ok_or_else(|| {
753 ValueError::new(ValueErrorKind::TypeMismatch {
754 expected: "array",
755 got: value.value_type(),
756 })
757 })?;
758
759 let tuple_len = match &partial.shape().ty {
760 Type::User(UserType::Struct(struct_def)) => struct_def.fields.len(),
761 _ => {
762 return Err(ValueError::new(ValueErrorKind::Unsupported {
763 message: "expected tuple type".into(),
764 }));
765 }
766 };
767
768 if arr.len() != tuple_len {
769 return Err(ValueError::new(ValueErrorKind::Unsupported {
770 message: format!("tuple has {} elements but got {}", tuple_len, arr.len()),
771 }));
772 }
773
774 for (i, item) in arr.iter().enumerate() {
775 partial = partial.begin_nth_field(i)?;
776 partial = deserialize_value_into(item, partial)?;
777 partial = partial.end()?;
778 }
779
780 Ok(partial)
781}
782
783fn deserialize_enum<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
785 let shape = partial.shape();
786
787 if shape.is_numeric() {
789 return deserialize_numeric_enum(value, partial);
790 }
791
792 if shape.is_untagged() {
793 return deserialize_untagged_enum(value, partial);
794 }
795
796 let tag_key = shape.get_tag_attr();
797 let content_key = shape.get_content_attr();
798
799 match (tag_key, content_key) {
800 (Some(tag_key), None) => deserialize_internally_tagged_enum(value, partial, tag_key),
802 (Some(tag_key), Some(content_key)) => {
804 deserialize_adjacently_tagged_enum(value, partial, tag_key, content_key)
805 }
806 (None, None) => deserialize_externally_tagged_enum(value, partial),
808 (None, Some(_)) => Err(ValueError::new(ValueErrorKind::Unsupported {
810 message: "content key without tag key is invalid".into(),
811 })),
812 }
813}
814
815fn deserialize_numeric_enum<'p>(value: &Value, mut partial: Partial<'p>) -> Result<Partial<'p>> {
822 let discriminant = match value.value_type() {
823 ValueType::Number => {
824 let num = value.as_number().unwrap();
825 if let Some(i) = num.to_i64() {
826 i
827 } else {
828 return Err(ValueError::new(ValueErrorKind::TypeMismatch {
829 expected: "Could not parse discriminant into i64", got: ValueType::Number,
831 }));
832 }
833 }
834 ValueType::String => {
835 let s = value.as_string().unwrap().as_str();
837 s.parse().map_err(|_| {
838 ValueError::new(ValueErrorKind::TypeMismatch {
839 expected: "Failed to parse string into i64",
840 got: ValueType::String,
841 })
842 })?
843 }
844 other => {
845 return Err(ValueError::new(ValueErrorKind::TypeMismatch {
846 expected: "Expected number or string for numeric enum",
847 got: other,
848 }));
849 }
850 };
851
852 partial = partial.select_variant(discriminant)?;
853 Ok(partial)
854}
855
856fn deserialize_externally_tagged_enum<'p>(
858 value: &Value,
859 mut partial: Partial<'p>,
860) -> Result<Partial<'p>> {
861 match value.value_type() {
862 ValueType::String => {
864 let variant_name = value.as_string().unwrap().as_str();
865 partial = partial.select_variant_named(variant_name)?;
866 Ok(partial)
867 }
868 ValueType::Object => {
870 let obj = value.as_object().unwrap();
871 if obj.len() != 1 {
872 return Err(ValueError::new(ValueErrorKind::Unsupported {
873 message: format!("enum object must have exactly 1 key, got {}", obj.len()),
874 }));
875 }
876
877 let (key, val) = obj.iter().next().unwrap();
878 let variant_name = key.as_str();
879
880 partial = partial.select_variant_named(variant_name)?;
881
882 let variant = partial.selected_variant().ok_or_else(|| {
883 ValueError::new(ValueErrorKind::Unsupported {
884 message: "failed to get selected variant".into(),
885 })
886 })?;
887
888 populate_variant_from_value(val, partial, &variant)
889 }
890 other => Err(ValueError::new(ValueErrorKind::TypeMismatch {
891 expected: "string or object for enum",
892 got: other,
893 })),
894 }
895}
896
897fn deserialize_internally_tagged_enum<'p>(
899 value: &Value,
900 mut partial: Partial<'p>,
901 tag_key: &str,
902) -> Result<Partial<'p>> {
903 let obj = value.as_object().ok_or_else(|| {
904 ValueError::new(ValueErrorKind::TypeMismatch {
905 expected: "object for internally tagged enum",
906 got: value.value_type(),
907 })
908 })?;
909
910 let tag_value = obj.get(tag_key).ok_or_else(|| {
912 ValueError::new(ValueErrorKind::Unsupported {
913 message: format!("internally tagged enum missing tag key '{tag_key}'"),
914 })
915 })?;
916
917 let variant_name = tag_value.as_string().ok_or_else(|| {
918 ValueError::new(ValueErrorKind::TypeMismatch {
919 expected: "string for enum tag",
920 got: tag_value.value_type(),
921 })
922 })?;
923
924 partial = partial.select_variant_named(variant_name.as_str())?;
925
926 let variant = partial.selected_variant().ok_or_else(|| {
927 ValueError::new(ValueErrorKind::Unsupported {
928 message: "failed to get selected variant".into(),
929 })
930 })?;
931
932 match variant.data.kind {
934 StructKind::Unit => {
935 Ok(partial)
937 }
938 StructKind::Struct => {
939 for field in variant.data.fields.iter() {
941 if let Some(field_value) = obj.get(field.name) {
942 partial = partial.begin_field(field.name)?;
943 partial = deserialize_value_into(field_value, partial)?;
944 partial = partial.end()?;
945 }
946 }
947 Ok(partial)
948 }
949 StructKind::TupleStruct | StructKind::Tuple => {
950 Err(ValueError::new(ValueErrorKind::Unsupported {
951 message: "internally tagged tuple variants are not supported".into(),
952 }))
953 }
954 }
955}
956
957fn deserialize_adjacently_tagged_enum<'p>(
959 value: &Value,
960 mut partial: Partial<'p>,
961 tag_key: &str,
962 content_key: &str,
963) -> Result<Partial<'p>> {
964 let obj = value.as_object().ok_or_else(|| {
965 ValueError::new(ValueErrorKind::TypeMismatch {
966 expected: "object for adjacently tagged enum",
967 got: value.value_type(),
968 })
969 })?;
970
971 let tag_value = obj.get(tag_key).ok_or_else(|| {
973 ValueError::new(ValueErrorKind::Unsupported {
974 message: format!("adjacently tagged enum missing tag key '{tag_key}'"),
975 })
976 })?;
977
978 let variant_name = tag_value.as_string().ok_or_else(|| {
979 ValueError::new(ValueErrorKind::TypeMismatch {
980 expected: "string for enum tag",
981 got: tag_value.value_type(),
982 })
983 })?;
984
985 partial = partial.select_variant_named(variant_name.as_str())?;
986
987 let variant = partial.selected_variant().ok_or_else(|| {
988 ValueError::new(ValueErrorKind::Unsupported {
989 message: "failed to get selected variant".into(),
990 })
991 })?;
992
993 match variant.data.kind {
995 StructKind::Unit => {
996 Ok(partial)
998 }
999 _ => {
1000 let content_value = obj.get(content_key).ok_or_else(|| {
1002 ValueError::new(ValueErrorKind::Unsupported {
1003 message: format!("adjacently tagged enum missing content key '{content_key}'"),
1004 })
1005 })?;
1006
1007 populate_variant_from_value(content_value, partial, &variant)
1008 }
1009 }
1010}
1011
1012fn deserialize_untagged_enum<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
1013 let mut partial = partial;
1014 let shape = partial.shape();
1015 let enum_type = match &shape.ty {
1016 Type::User(UserType::Enum(enum_def)) => enum_def,
1017 _ => {
1018 return Err(ValueError::new(ValueErrorKind::Unsupported {
1019 message: "expected enum type".into(),
1020 }));
1021 }
1022 };
1023
1024 for variant in enum_type.variants.iter() {
1025 if value_matches_variant(value, variant) {
1026 partial = partial.select_variant_named(variant.effective_name())?;
1027 return populate_variant_from_value(value, partial, variant);
1028 }
1029 }
1030
1031 Err(ValueError::new(ValueErrorKind::TypeMismatch {
1032 expected: shape.type_identifier,
1033 got: value.value_type(),
1034 }))
1035}
1036
1037fn populate_variant_from_value<'p>(
1038 value: &Value,
1039 mut partial: Partial<'p>,
1040 variant: &Variant,
1041) -> Result<Partial<'p>> {
1042 match variant.data.kind {
1043 StructKind::Unit => {
1044 if !matches!(value.value_type(), ValueType::Null) {
1045 return Err(ValueError::new(ValueErrorKind::TypeMismatch {
1046 expected: "null for unit variant",
1047 got: value.value_type(),
1048 }));
1049 }
1050 }
1051 StructKind::TupleStruct | StructKind::Tuple => {
1052 let num_fields = variant.data.fields.len();
1053 if num_fields == 0 {
1054 } else if num_fields == 1 {
1056 partial = partial.begin_nth_field(0)?;
1057 partial = deserialize_value_into(value, partial)?;
1058 partial = partial.end()?;
1059 } else {
1060 let arr = value.as_array().ok_or_else(|| {
1061 ValueError::new(ValueErrorKind::TypeMismatch {
1062 expected: "array for tuple variant",
1063 got: value.value_type(),
1064 })
1065 })?;
1066
1067 if arr.len() != num_fields {
1068 return Err(ValueError::new(ValueErrorKind::Unsupported {
1069 message: format!(
1070 "tuple variant has {} fields but got {}",
1071 num_fields,
1072 arr.len()
1073 ),
1074 }));
1075 }
1076
1077 for (i, item) in arr.iter().enumerate() {
1078 partial = partial.begin_nth_field(i)?;
1079 partial = deserialize_value_into(item, partial)?;
1080 partial = partial.end()?;
1081 }
1082 }
1083 }
1084 StructKind::Struct => {
1085 let inner_obj = value.as_object().ok_or_else(|| {
1086 ValueError::new(ValueErrorKind::TypeMismatch {
1087 expected: "object for struct variant",
1088 got: value.value_type(),
1089 })
1090 })?;
1091
1092 for (field_key, field_val) in inner_obj.iter() {
1093 partial = partial.begin_field(field_key.as_str())?;
1094 partial = deserialize_value_into(field_val, partial)?;
1095 partial = partial.end()?;
1096 }
1097 }
1098 }
1099
1100 Ok(partial)
1101}
1102
1103fn value_matches_variant(value: &Value, variant: &Variant) -> bool {
1104 match variant.data.kind {
1105 StructKind::Unit => matches!(value.value_type(), ValueType::Null),
1106 StructKind::TupleStruct | StructKind::Tuple => {
1107 let fields = variant.data.fields;
1108 if fields.is_empty() {
1109 matches!(value.value_type(), ValueType::Null)
1110 } else if fields.len() == 1 {
1111 value_matches_shape(value, fields[0].shape.get())
1112 } else {
1113 value
1114 .as_array()
1115 .map(|arr| arr.len() == fields.len())
1116 .unwrap_or(false)
1117 }
1118 }
1119 StructKind::Struct => matches!(value.value_type(), ValueType::Object),
1120 }
1121}
1122
1123fn value_matches_shape(value: &Value, shape: &'static Shape) -> bool {
1124 match &shape.ty {
1125 Type::Primitive(PrimitiveType::Boolean) => {
1126 matches!(value.value_type(), ValueType::Bool)
1127 }
1128 Type::Primitive(PrimitiveType::Numeric(num)) => match num {
1129 NumericType::Integer { signed } => {
1130 if *signed {
1131 value.as_number().and_then(|n| n.to_i64()).is_some()
1132 } else {
1133 value.as_number().and_then(|n| n.to_u64()).is_some()
1134 }
1135 }
1136 NumericType::Float => value.as_number().and_then(|n| n.to_f64()).is_some(),
1137 },
1138 _ => true,
1139 }
1140}
1141
1142fn deserialize_list<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
1144 let mut partial = partial;
1145 let arr = value.as_array().ok_or_else(|| {
1146 ValueError::new(ValueErrorKind::TypeMismatch {
1147 expected: "array",
1148 got: value.value_type(),
1149 })
1150 })?;
1151
1152 partial = partial.init_list()?;
1153
1154 for item in arr.iter() {
1155 partial = partial.begin_list_item()?;
1156 partial = deserialize_value_into(item, partial)?;
1157 partial = partial.end()?;
1158 }
1159
1160 Ok(partial)
1161}
1162
1163fn deserialize_array<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
1165 let mut partial = partial;
1166 let arr = value.as_array().ok_or_else(|| {
1167 ValueError::new(ValueErrorKind::TypeMismatch {
1168 expected: "array",
1169 got: value.value_type(),
1170 })
1171 })?;
1172
1173 let array_len = match &partial.shape().def {
1174 Def::Array(arr_def) => arr_def.n,
1175 _ => {
1176 return Err(ValueError::new(ValueErrorKind::Unsupported {
1177 message: "expected array type".into(),
1178 }));
1179 }
1180 };
1181
1182 if arr.len() != array_len {
1183 return Err(ValueError::new(ValueErrorKind::Unsupported {
1184 message: format!(
1185 "fixed array has {} elements but got {}",
1186 array_len,
1187 arr.len()
1188 ),
1189 }));
1190 }
1191
1192 for (i, item) in arr.iter().enumerate() {
1193 partial = partial.begin_nth_field(i)?;
1194 partial = deserialize_value_into(item, partial)?;
1195 partial = partial.end()?;
1196 }
1197
1198 Ok(partial)
1199}
1200
1201fn deserialize_set<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
1203 let mut partial = partial;
1204 let arr = value.as_array().ok_or_else(|| {
1205 ValueError::new(ValueErrorKind::TypeMismatch {
1206 expected: "array",
1207 got: value.value_type(),
1208 })
1209 })?;
1210
1211 partial = partial.init_set()?;
1212
1213 for item in arr.iter() {
1214 partial = partial.begin_set_item()?;
1215 partial = deserialize_value_into(item, partial)?;
1216 partial = partial.end()?;
1217 }
1218
1219 Ok(partial)
1220}
1221
1222fn deserialize_map<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
1224 let mut partial = partial;
1225 let obj = value.as_object().ok_or_else(|| {
1226 ValueError::new(ValueErrorKind::TypeMismatch {
1227 expected: "object",
1228 got: value.value_type(),
1229 })
1230 })?;
1231
1232 partial = partial.init_map()?;
1233
1234 for (key, val) in obj.iter() {
1235 partial = partial.begin_key()?;
1237 if partial.shape().inner.is_some() {
1240 partial = partial.begin_inner()?;
1241 partial = partial.set(key.as_str().to_string())?;
1242 partial = partial.end()?;
1243 } else {
1244 partial = partial.set(key.as_str().to_string())?;
1245 }
1246 partial = partial.end()?;
1247
1248 partial = partial.begin_value()?;
1250 partial = deserialize_value_into(val, partial)?;
1251 partial = partial.end()?;
1252 }
1253
1254 Ok(partial)
1255}
1256
1257fn deserialize_option<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
1259 let mut partial = partial;
1260 if value.is_null() {
1261 partial = partial.set_default()?; } else {
1263 partial = partial.begin_some()?;
1264 partial = deserialize_value_into(value, partial)?;
1265 partial = partial.end()?;
1266 }
1267 Ok(partial)
1268}
1269
1270fn deserialize_pointer<'p>(value: &Value, partial: Partial<'p>) -> Result<Partial<'p>> {
1272 use facet_core::{KnownPointer, SequenceType};
1273
1274 let mut partial = partial;
1275 let (is_slice_pointer, is_reference, is_cow) =
1276 if let Def::Pointer(ptr_def) = partial.shape().def {
1277 let is_slice = if let Some(pointee) = ptr_def.pointee() {
1278 matches!(pointee.ty, Type::Sequence(SequenceType::Slice(_)))
1279 } else {
1280 false
1281 };
1282 let is_ref = matches!(
1283 ptr_def.known,
1284 Some(KnownPointer::SharedReference | KnownPointer::ExclusiveReference)
1285 );
1286 let is_cow = matches!(ptr_def.known, Some(KnownPointer::Cow));
1287 (is_slice, is_ref, is_cow)
1288 } else {
1289 (false, false, false)
1290 };
1291
1292 if is_reference {
1294 return Err(ValueError::new(ValueErrorKind::Unsupported {
1295 message: format!(
1296 "cannot deserialize into reference type '{}'",
1297 partial.shape().type_identifier
1298 ),
1299 }));
1300 }
1301
1302 if is_cow {
1304 if let Def::Pointer(ptr_def) = partial.shape().def
1306 && let Some(pointee) = ptr_def.pointee()
1307 && matches!(
1308 pointee.ty,
1309 Type::Primitive(PrimitiveType::Textual(TextualType::Str))
1310 )
1311 {
1312 if let Some(s) = value.as_string() {
1314 partial = partial.set(alloc::borrow::Cow::<'static, str>::Owned(
1316 s.as_str().to_string(),
1317 ))?;
1318 return Ok(partial);
1319 } else {
1320 return Err(ValueError::new(ValueErrorKind::TypeMismatch {
1321 expected: "string for Cow<str>",
1322 got: value.value_type(),
1323 }));
1324 }
1325 }
1326 partial = partial.begin_inner()?;
1328 partial = deserialize_value_into(value, partial)?;
1329 partial = partial.end()?;
1330 return Ok(partial);
1331 }
1332
1333 partial = partial.begin_smart_ptr()?;
1334
1335 if is_slice_pointer {
1336 let arr = value.as_array().ok_or_else(|| {
1338 ValueError::new(ValueErrorKind::TypeMismatch {
1339 expected: "array",
1340 got: value.value_type(),
1341 })
1342 })?;
1343
1344 for item in arr.iter() {
1345 partial = partial.begin_list_item()?;
1346 partial = deserialize_value_into(item, partial)?;
1347 partial = partial.end()?;
1348 }
1349 } else {
1350 partial = deserialize_value_into(value, partial)?;
1352 }
1353
1354 partial = partial.end()?;
1355 Ok(partial)
1356}
1357
1358#[cfg(test)]
1359mod tests {
1360 use super::*;
1361 use crate::{VArray, VObject, VString};
1362
1363 #[test]
1364 fn test_deserialize_primitives() {
1365 let v = Value::TRUE;
1367 let b: bool = from_value(v).unwrap();
1368 assert!(b);
1369
1370 let v = Value::from(42i64);
1372 let n: i32 = from_value(v).unwrap();
1373 assert_eq!(n, 42);
1374
1375 let v: Value = VString::new("hello").into();
1377 let s: String = from_value(v).unwrap();
1378 assert_eq!(s, "hello");
1379 }
1380
1381 #[test]
1382 fn test_deserialize_option() {
1383 let v = Value::from(42i64);
1385 let opt: Option<i32> = from_value(v).unwrap();
1386 assert_eq!(opt, Some(42));
1387
1388 let v = Value::NULL;
1390 let opt: Option<i32> = from_value(v).unwrap();
1391 assert_eq!(opt, None);
1392 }
1393
1394 #[test]
1395 fn test_deserialize_vec() {
1396 let mut arr = VArray::new();
1397 arr.push(Value::from(1i64));
1398 arr.push(Value::from(2i64));
1399 arr.push(Value::from(3i64));
1400
1401 let v: Value = arr.into();
1402 let vec: alloc::vec::Vec<i32> = from_value(v).unwrap();
1403 assert_eq!(vec, alloc::vec![1, 2, 3]);
1404 }
1405
1406 #[test]
1407 fn test_deserialize_nested() {
1408 let mut arr = VArray::new();
1410 arr.push(Value::from(1i64));
1411 arr.push(Value::NULL);
1412 arr.push(Value::from(3i64));
1413
1414 let v: Value = arr.into();
1415 let vec: alloc::vec::Vec<Option<i32>> = from_value(v).unwrap();
1416 assert_eq!(vec, alloc::vec![Some(1), None, Some(3)]);
1417 }
1418
1419 #[test]
1420 fn test_deserialize_map() {
1421 use alloc::collections::BTreeMap;
1422
1423 let mut obj = VObject::new();
1424 obj.insert("a", Value::from(1i64));
1425 obj.insert("b", Value::from(2i64));
1426
1427 let v: Value = obj.into();
1428 let map: BTreeMap<String, i32> = from_value(v).unwrap();
1429 assert_eq!(map.get("a"), Some(&1));
1430 assert_eq!(map.get("b"), Some(&2));
1431 }
1432}