Skip to main content

facet_value/
deserialize.rs

1#![allow(clippy::result_large_err)]
2//! Deserialize from a `Value` into any type implementing `Facet`.
3//!
4//! This module provides the inverse of serialization: given a `Value`, you can
5//! deserialize it into any Rust type that implements `Facet`.
6//!
7//! # Example
8//!
9//! ```ignore
10//! use facet::Facet;
11//! use facet_value::{Value, from_value};
12//!
13//! #[derive(Debug, Facet, PartialEq)]
14//! struct Person {
15//!     name: String,
16//!     age: u32,
17//! }
18//!
19//! // Create a Value (could come from JSON, MessagePack, etc.)
20//! let value = facet_value::value!({
21//!     "name": "Alice",
22//!     "age": 30
23//! });
24//!
25//! // Deserialize into a typed struct
26//! let person: Person = from_value(value).unwrap();
27//! assert_eq!(person.name, "Alice");
28//! assert_eq!(person.age, 30);
29//! ```
30
31use alloc::format;
32use alloc::string::{String, ToString};
33use alloc::vec::Vec;
34
35use facet_core::{
36    Def, Facet, Field, NumericType, PrimitiveType, Shape, StructKind, TextualType, Type, UserType,
37    Variant,
38};
39use facet_reflect::{AllocError, Partial, ReflectError, ShapeMismatchError, TypePlan};
40
41use crate::{VNumber, Value, ValueType};
42
43/// A segment in a deserialization path
44#[derive(Clone, Debug, PartialEq, Eq)]
45pub enum PathSegment {
46    /// A field name in a struct or map
47    Field(String),
48    /// A variant name in an enum
49    Variant(String),
50    /// An index in an array or list
51    Index(usize),
52}
53
54impl core::fmt::Display for PathSegment {
55    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
56        match self {
57            PathSegment::Field(name) => write!(f, ".{name}"),
58            PathSegment::Variant(name) => write!(f, "::{name}"),
59            PathSegment::Index(i) => write!(f, "[{i}]"),
60        }
61    }
62}
63
64/// Error type for Value deserialization.
65#[derive(Debug)]
66pub struct ValueError {
67    /// The specific kind of error
68    pub kind: ValueErrorKind,
69    /// Path through the source Value where the error occurred
70    pub source_path: Vec<PathSegment>,
71    /// Path through the target Shape where the error occurred
72    pub dest_path: Vec<PathSegment>,
73    /// The target Shape we were deserializing into (for diagnostics)
74    pub target_shape: Option<&'static Shape>,
75    /// The source Value we were deserializing from (for diagnostics)
76    pub source_value: Option<Value>,
77}
78
79impl core::fmt::Display for ValueError {
80    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
81        if self.source_path.is_empty() {
82            write!(f, "{}", self.kind)
83        } else {
84            write!(f, "at {}: {}", self.source_path_string(), self.kind)
85        }
86    }
87}
88
89impl ValueError {
90    /// Create a new ValueError with empty paths
91    pub const fn new(kind: ValueErrorKind) -> Self {
92        Self {
93            kind,
94            source_path: Vec::new(),
95            dest_path: Vec::new(),
96            target_shape: None,
97            source_value: None,
98        }
99    }
100
101    /// Set the target shape for diagnostics
102    pub const fn with_shape(mut self, shape: &'static Shape) -> Self {
103        self.target_shape = Some(shape);
104        self
105    }
106
107    /// Set the source value for diagnostics
108    pub fn with_value(mut self, value: Value) -> Self {
109        self.source_value = Some(value);
110        self
111    }
112
113    /// Add a path segment to both paths (prepends since we unwind from error site)
114    pub fn with_path(mut self, segment: PathSegment) -> Self {
115        self.source_path.insert(0, segment.clone());
116        self.dest_path.insert(0, segment);
117        self
118    }
119
120    /// Format the source path as a string
121    pub fn source_path_string(&self) -> String {
122        if self.source_path.is_empty() {
123            "<root>".into()
124        } else {
125            use core::fmt::Write;
126            let mut s = String::new();
127            for seg in &self.source_path {
128                let _ = write!(s, "{seg}");
129            }
130            s
131        }
132    }
133
134    /// Format the dest path as a string
135    pub fn dest_path_string(&self) -> String {
136        if self.dest_path.is_empty() {
137            "<root>".into()
138        } else {
139            use core::fmt::Write;
140            let mut s = String::new();
141            for seg in &self.dest_path {
142                let _ = write!(s, "{seg}");
143            }
144            s
145        }
146    }
147}
148
149#[cfg(feature = "std")]
150impl core::error::Error for ValueError {}
151
152/// Specific error kinds for Value deserialization.
153#[derive(Debug)]
154pub enum ValueErrorKind {
155    /// Type mismatch between Value and target type
156    TypeMismatch {
157        /// What the target type expected
158        expected: &'static str,
159        /// What the Value actually contained
160        got: ValueType,
161    },
162    /// A required field is missing from the object
163    MissingField {
164        /// The name of the missing field
165        field: &'static str,
166    },
167    /// An unknown field was encountered (when deny_unknown_fields is set)
168    UnknownField {
169        /// The unknown field name
170        field: String,
171    },
172    /// Number conversion failed (out of range)
173    NumberOutOfRange {
174        /// Description of the error
175        message: String,
176    },
177    /// Reflection error from facet-reflect
178    Reflect(ReflectError),
179    /// Unsupported type or feature
180    Unsupported {
181        /// Description of what's unsupported
182        message: String,
183    },
184}
185
186impl core::fmt::Display for ValueErrorKind {
187    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
188        match self {
189            ValueErrorKind::TypeMismatch { expected, got } => {
190                write!(f, "type mismatch: expected {expected}, got {got:?}")
191            }
192            ValueErrorKind::MissingField { field } => {
193                write!(f, "missing required field `{field}`")
194            }
195            ValueErrorKind::UnknownField { field } => {
196                write!(f, "unknown field `{field}`")
197            }
198            ValueErrorKind::NumberOutOfRange { message } => {
199                write!(f, "number out of range: {message}")
200            }
201            ValueErrorKind::Reflect(e) => write!(f, "reflection error: {e}"),
202            ValueErrorKind::Unsupported { message } => {
203                write!(f, "unsupported: {message}")
204            }
205        }
206    }
207}
208
209impl From<ReflectError> for ValueError {
210    fn from(err: ReflectError) -> Self {
211        ValueError::new(ValueErrorKind::Reflect(err))
212    }
213}
214
215impl From<ShapeMismatchError> for ValueError {
216    fn from(err: ShapeMismatchError) -> Self {
217        ValueError::new(ValueErrorKind::Unsupported {
218            message: format!(
219                "shape mismatch: expected {}, got {}",
220                err.expected, err.actual
221            ),
222        })
223    }
224}
225
226impl From<AllocError> for ValueError {
227    fn from(err: AllocError) -> Self {
228        ValueError::new(ValueErrorKind::Unsupported {
229            message: format!("allocation failed for {}: {}", err.shape, err.operation),
230        })
231    }
232}
233
234/// Result type for Value deserialization.
235pub type Result<T> = core::result::Result<T, ValueError>;
236
237/// Deserialize a `Value` into any type implementing `Facet`.
238///
239/// This is the main entry point for converting a dynamic `Value` into a
240/// typed Rust value.
241///
242/// # Example
243///
244/// ```ignore
245/// use facet::Facet;
246/// use facet_value::{Value, from_value};
247///
248/// #[derive(Debug, Facet, PartialEq)]
249/// struct Point {
250///     x: i32,
251///     y: i32,
252/// }
253///
254/// let value = facet_value::value!({"x": 10, "y": 20});
255/// let point: Point = from_value(value).unwrap();
256/// assert_eq!(point, Point { x: 10, y: 20 });
257/// ```
258pub fn from_value<T: Facet<'static>>(value: Value) -> Result<T> {
259    let plan = TypePlan::<T>::build().map_err(|e| {
260        ValueError::from(e)
261            .with_shape(T::SHAPE)
262            .with_value(value.clone())
263    })?;
264    let partial = plan.partial_owned().map_err(|e| {
265        ValueError::from(e)
266            .with_shape(T::SHAPE)
267            .with_value(value.clone())
268    })?;
269    let partial = deserialize_value_into(&value, partial)
270        .map_err(|e| e.with_shape(T::SHAPE).with_value(value.clone()))?;
271    let heap_value = partial.build().map_err(|e| {
272        ValueError::from(e)
273            .with_shape(T::SHAPE)
274            .with_value(value.clone())
275    })?;
276    heap_value.materialize().map_err(|e| {
277        ValueError::from(e)
278            .with_shape(T::SHAPE)
279            .with_value(value.clone())
280    })
281}
282
283/// Internal deserializer that reads from a Value and writes to a Partial.
284fn deserialize_value_into<'facet>(
285    value: &Value,
286    partial: Partial<'facet, false>,
287) -> Result<Partial<'facet, false>> {
288    let mut partial = partial;
289    let shape = partial.shape();
290
291    // Check for Option first (it's also an enum but needs special handling)
292    if matches!(&shape.def, Def::Option(_)) {
293        return deserialize_option(value, partial);
294    }
295
296    // Check for smart pointers
297    if matches!(&shape.def, Def::Pointer(_)) {
298        return deserialize_pointer(value, partial);
299    }
300
301    // Check for container-level proxy
302    #[cfg(feature = "alloc")]
303    if shape.proxy.is_some() {
304        let (partial_returned, has_proxy) = partial.begin_custom_deserialization_from_shape()?;
305        partial = partial_returned;
306        if has_proxy {
307            partial = deserialize_value_into(value, partial)?;
308            partial = partial.end()?;
309            return Ok(partial);
310        }
311    }
312
313    // Priority 1: Check for builder_shape (immutable collections like Bytes -> BytesMut)
314    if shape.builder_shape.is_some() {
315        partial = partial.begin_inner()?;
316        partial = deserialize_value_into(value, partial)?;
317        partial = partial.end()?;
318        return Ok(partial);
319    }
320
321    // Priority 2: Check for .inner (transparent wrappers like NonZero)
322    // Collections (List/Map/Set/Array) have .inner for variance but shouldn't use this path
323    if shape.inner.is_some()
324        && !matches!(
325            &shape.def,
326            Def::List(_) | Def::Map(_) | Def::Set(_) | Def::Array(_)
327        )
328    {
329        partial = partial.begin_inner()?;
330        partial = deserialize_value_into(value, partial)?;
331        partial = partial.end()?;
332        return Ok(partial);
333    }
334
335    // Priority 3: Check the Type for structs and enums
336    match &shape.ty {
337        Type::User(UserType::Struct(struct_def)) => {
338            if struct_def.kind == StructKind::Tuple {
339                return deserialize_tuple(value, partial);
340            }
341            return deserialize_struct(value, partial);
342        }
343        Type::User(UserType::Enum(_)) => return deserialize_enum(value, partial),
344        _ => {}
345    }
346
347    // Priority 4: Check Def for containers and special types
348    match &shape.def {
349        Def::Scalar => deserialize_scalar(value, partial),
350        Def::List(_) => deserialize_list(value, partial),
351        Def::Map(_) => deserialize_map(value, partial),
352        Def::Array(_) => deserialize_array(value, partial),
353        Def::Set(_) => deserialize_set(value, partial),
354        Def::DynamicValue(_) => {
355            // Target is a DynamicValue (like Value itself) - just clone
356            partial = partial.set(value.clone())?;
357            Ok(partial)
358        }
359        _ => Err(ValueError::new(ValueErrorKind::Unsupported {
360            message: format!("unsupported shape def: {:?}", shape.def),
361        })),
362    }
363}
364
365/// Deserialize a scalar value (primitives, strings).
366fn deserialize_scalar<'facet>(
367    value: &Value,
368    partial: Partial<'facet, false>,
369) -> Result<Partial<'facet, false>> {
370    let mut partial = partial;
371    let shape = partial.shape();
372
373    match value.value_type() {
374        ValueType::Null => {
375            partial = partial.set_default()?;
376            Ok(partial)
377        }
378        ValueType::Bool => {
379            let b = value.as_bool().unwrap();
380            partial = partial.set(b)?;
381            Ok(partial)
382        }
383        ValueType::Number => {
384            let num = value.as_number().unwrap();
385            // If target expects a string, stringify the number
386            // This is needed for formats like XML where type inference may produce
387            // numbers even when strings are expected
388            if *shape == *String::SHAPE {
389                let s = if let Some(i) = num.to_i64() {
390                    format!("{i}")
391                } else if let Some(u) = num.to_u64() {
392                    format!("{u}")
393                } else if let Some(f) = num.to_f64() {
394                    format!("{f}")
395                } else {
396                    return Err(ValueError::new(ValueErrorKind::TypeMismatch {
397                        expected: "String",
398                        got: ValueType::Number,
399                    }));
400                };
401                partial = partial.set(s)?;
402                Ok(partial)
403            } else {
404                set_number(num, partial, shape)
405            }
406        }
407        ValueType::String => {
408            let s = value.as_string().unwrap();
409            // Try parse_from_str first if the type supports it
410            if shape.vtable.has_parse() {
411                partial = partial.parse_from_str(s.as_str())?;
412            } else {
413                partial = partial.set(s.as_str().to_string())?;
414            }
415            Ok(partial)
416        }
417        ValueType::Bytes => {
418            let bytes = value.as_bytes().unwrap();
419            partial = partial.set(bytes.as_slice().to_vec())?;
420            Ok(partial)
421        }
422        other => Err(ValueError::new(ValueErrorKind::TypeMismatch {
423            expected: shape.type_identifier,
424            got: other,
425        })),
426    }
427}
428
429/// Set a numeric value with appropriate type conversion.
430fn set_number<'facet>(
431    num: &VNumber,
432    partial: Partial<'facet, false>,
433    shape: &Shape,
434) -> Result<Partial<'facet, false>> {
435    use facet_core::{NumericType, PrimitiveType, ShapeLayout};
436
437    let mut partial = partial;
438    let size = match shape.layout {
439        ShapeLayout::Sized(layout) => layout.size(),
440        _ => {
441            return Err(ValueError::new(ValueErrorKind::Unsupported {
442                message: "unsized numeric type".into(),
443            }));
444        }
445    };
446
447    match &shape.ty {
448        Type::Primitive(PrimitiveType::Numeric(NumericType::Integer { signed: true })) => {
449            let val = num.to_i64().ok_or_else(|| {
450                ValueError::new(ValueErrorKind::NumberOutOfRange {
451                    message: "value cannot be represented as i64".into(),
452                })
453            })?;
454            // Check shape to distinguish i64 from isize (both 8 bytes on 64-bit)
455            if *shape == *isize::SHAPE {
456                let v = isize::try_from(val).map_err(|_| {
457                    ValueError::new(ValueErrorKind::NumberOutOfRange {
458                        message: format!("{val} out of range for isize"),
459                    })
460                })?;
461                partial = partial.set(v)?;
462            } else {
463                match size {
464                    1 => {
465                        let v = i8::try_from(val).map_err(|_| {
466                            ValueError::new(ValueErrorKind::NumberOutOfRange {
467                                message: format!("{val} out of range for i8"),
468                            })
469                        })?;
470                        partial = partial.set(v)?;
471                    }
472                    2 => {
473                        let v = i16::try_from(val).map_err(|_| {
474                            ValueError::new(ValueErrorKind::NumberOutOfRange {
475                                message: format!("{val} out of range for i16"),
476                            })
477                        })?;
478                        partial = partial.set(v)?;
479                    }
480                    4 => {
481                        let v = i32::try_from(val).map_err(|_| {
482                            ValueError::new(ValueErrorKind::NumberOutOfRange {
483                                message: format!("{val} out of range for i32"),
484                            })
485                        })?;
486                        partial = partial.set(v)?;
487                    }
488                    8 => {
489                        partial = partial.set(val)?;
490                    }
491                    16 => {
492                        partial = partial.set(val as i128)?;
493                    }
494                    _ => {
495                        return Err(ValueError::new(ValueErrorKind::Unsupported {
496                            message: format!("unexpected integer size: {size}"),
497                        }));
498                    }
499                }
500            }
501        }
502        Type::Primitive(PrimitiveType::Numeric(NumericType::Integer { signed: false })) => {
503            let val = num.to_u64().ok_or_else(|| {
504                ValueError::new(ValueErrorKind::NumberOutOfRange {
505                    message: "value cannot be represented as u64".into(),
506                })
507            })?;
508            // Check shape to distinguish u64 from usize (both 8 bytes on 64-bit)
509            if *shape == *usize::SHAPE {
510                let v = usize::try_from(val).map_err(|_| {
511                    ValueError::new(ValueErrorKind::NumberOutOfRange {
512                        message: format!("{val} out of range for usize"),
513                    })
514                })?;
515                partial = partial.set(v)?;
516            } else {
517                match size {
518                    1 => {
519                        let v = u8::try_from(val).map_err(|_| {
520                            ValueError::new(ValueErrorKind::NumberOutOfRange {
521                                message: format!("{val} out of range for u8"),
522                            })
523                        })?;
524                        partial = partial.set(v)?;
525                    }
526                    2 => {
527                        let v = u16::try_from(val).map_err(|_| {
528                            ValueError::new(ValueErrorKind::NumberOutOfRange {
529                                message: format!("{val} out of range for u16"),
530                            })
531                        })?;
532                        partial = partial.set(v)?;
533                    }
534                    4 => {
535                        let v = u32::try_from(val).map_err(|_| {
536                            ValueError::new(ValueErrorKind::NumberOutOfRange {
537                                message: format!("{val} out of range for u32"),
538                            })
539                        })?;
540                        partial = partial.set(v)?;
541                    }
542                    8 => {
543                        partial = partial.set(val)?;
544                    }
545                    16 => {
546                        partial = partial.set(val as u128)?;
547                    }
548                    _ => {
549                        return Err(ValueError::new(ValueErrorKind::Unsupported {
550                            message: format!("unexpected integer size: {size}"),
551                        }));
552                    }
553                }
554            }
555        }
556        Type::Primitive(PrimitiveType::Numeric(NumericType::Float)) => {
557            let val = num.to_f64_lossy();
558            match size {
559                4 => {
560                    partial = partial.set(val as f32)?;
561                }
562                8 => {
563                    partial = partial.set(val)?;
564                }
565                _ => {
566                    return Err(ValueError::new(ValueErrorKind::Unsupported {
567                        message: format!("unexpected float size: {size}"),
568                    }));
569                }
570            }
571        }
572        _ => {
573            return Err(ValueError::new(ValueErrorKind::TypeMismatch {
574                expected: shape.type_identifier,
575                got: ValueType::Number,
576            }));
577        }
578    }
579    Ok(partial)
580}
581
582/// Deserialize a struct from a Value::Object.
583fn deserialize_struct<'facet>(
584    value: &Value,
585    partial: Partial<'facet, false>,
586) -> Result<Partial<'facet, false>> {
587    let mut partial = partial;
588    let obj = value.as_object().ok_or_else(|| {
589        ValueError::new(ValueErrorKind::TypeMismatch {
590            expected: "object",
591            got: value.value_type(),
592        })
593    })?;
594
595    let struct_def = match &partial.shape().ty {
596        Type::User(UserType::Struct(s)) => s,
597        _ => {
598            return Err(ValueError::new(ValueErrorKind::Unsupported {
599                message: "expected struct type".into(),
600            }));
601        }
602    };
603
604    let deny_unknown_fields = partial.struct_plan().unwrap().deny_unknown_fields;
605
606    // Check if we have any flattened fields
607    let has_flattened = struct_def.fields.iter().any(|f| f.is_flattened());
608
609    if has_flattened {
610        return deserialize_struct_with_flatten(obj, partial, struct_def, deny_unknown_fields);
611    }
612
613    // Track which fields we've set
614    let num_fields = struct_def.fields.len();
615    let mut fields_set = alloc::vec![false; num_fields];
616
617    // Process each key-value pair in the object
618    for (key, val) in obj.iter() {
619        let key_str = key.as_str();
620
621        // Find matching field by effective_name (rename if present, else name) or alias
622        let field_info = struct_def
623            .fields
624            .iter()
625            .enumerate()
626            .find(|(_, f)| f.effective_name() == key_str || f.alias == Some(key_str));
627
628        if let Some((idx, field)) = field_info {
629            partial = partial.begin_field(field.name)?;
630            // Check for field-level proxy
631            #[cfg(feature = "alloc")]
632            if field.proxy_convert_in_fn().is_some() {
633                partial = partial.begin_custom_deserialization()?;
634                partial = deserialize_value_into(val, partial)?;
635                partial = partial.end()?;
636            } else {
637                partial = deserialize_value_into(val, partial)?;
638            }
639            #[cfg(not(feature = "alloc"))]
640            {
641                partial = deserialize_value_into(val, partial)?;
642            }
643            partial = partial.end()?;
644            fields_set[idx] = true;
645        } else if deny_unknown_fields {
646            return Err(ValueError::new(ValueErrorKind::UnknownField {
647                field: key_str.to_string(),
648            }));
649        }
650        // else: skip unknown field
651    }
652
653    // Handle missing fields - try to set defaults
654    for (idx, field) in struct_def.fields.iter().enumerate() {
655        if fields_set[idx] {
656            continue;
657        }
658
659        // Try to set default for the field
660        partial = partial
661            .set_nth_field_to_default(idx)
662            .map_err(|_| ValueError::new(ValueErrorKind::MissingField { field: field.name }))?;
663    }
664
665    Ok(partial)
666}
667
668/// Deserialize a struct that has flattened fields.
669fn deserialize_struct_with_flatten<'facet>(
670    obj: &crate::VObject,
671    mut partial: Partial<'facet, false>,
672    struct_def: &'static facet_core::StructType,
673    deny_unknown_fields: bool,
674) -> Result<Partial<'facet, false>> {
675    use alloc::collections::BTreeMap;
676
677    let num_fields = struct_def.fields.len();
678    let mut fields_set = alloc::vec![false; num_fields];
679
680    // Collect which keys go to which flattened field
681    // Key -> (flattened_field_idx, inner_field_name)
682    let mut flatten_keys: BTreeMap<&str, (usize, &str)> = BTreeMap::new();
683
684    // First pass: identify which keys belong to flattened fields
685    for (idx, field) in struct_def.fields.iter().enumerate() {
686        if !field.is_flattened() {
687            continue;
688        }
689
690        // Get the inner struct's fields
691        let inner_shape = field.shape.get();
692        if let Type::User(UserType::Struct(inner_struct)) = &inner_shape.ty {
693            for inner_field in inner_struct.fields.iter() {
694                // Use the serialization name (rename if present, else name)
695                let key_name = inner_field.rename.unwrap_or(inner_field.name);
696                flatten_keys.insert(key_name, (idx, inner_field.name));
697            }
698        }
699    }
700
701    // Collect values for each flattened field
702    let mut flatten_values: Vec<BTreeMap<String, Value>> =
703        (0..num_fields).map(|_| BTreeMap::new()).collect();
704
705    // Process each key-value pair in the object
706    for (key, val) in obj.iter() {
707        let key_str = key.as_str();
708
709        // First, check for direct field match (non-flattened fields) by effective_name or alias
710        let direct_field = struct_def.fields.iter().enumerate().find(|(_, f)| {
711            !f.is_flattened() && (f.effective_name() == key_str || f.alias == Some(key_str))
712        });
713
714        if let Some((idx, field)) = direct_field {
715            partial = partial.begin_field(field.name)?;
716            // Check for field-level proxy
717            #[cfg(feature = "alloc")]
718            if field.proxy_convert_in_fn().is_some() {
719                partial = partial.begin_custom_deserialization()?;
720                partial = deserialize_value_into(val, partial)?;
721                partial = partial.end()?;
722            } else {
723                partial = deserialize_value_into(val, partial)?;
724            }
725            #[cfg(not(feature = "alloc"))]
726            {
727                partial = deserialize_value_into(val, partial)?;
728            }
729            partial = partial.end()?;
730            fields_set[idx] = true;
731            continue;
732        }
733
734        // Check if this key belongs to a flattened field
735        if let Some(&(flatten_idx, inner_name)) = flatten_keys.get(key_str) {
736            flatten_values[flatten_idx].insert(inner_name.to_string(), val.clone());
737            fields_set[flatten_idx] = true;
738            continue;
739        }
740
741        // Unknown field
742        if deny_unknown_fields {
743            return Err(ValueError::new(ValueErrorKind::UnknownField {
744                field: key_str.to_string(),
745            }));
746        }
747        // else: skip unknown field
748    }
749
750    // Deserialize each flattened field from its collected values
751    for (idx, field) in struct_def.fields.iter().enumerate() {
752        if !field.is_flattened() {
753            continue;
754        }
755
756        if !flatten_values[idx].is_empty() {
757            // Build a synthetic Value::Object for this flattened field
758            let mut synthetic_obj = crate::VObject::new();
759            let values = core::mem::take(&mut flatten_values[idx]);
760            for (k, v) in values {
761                synthetic_obj.insert(k, v);
762            }
763            let synthetic_value = Value::from(synthetic_obj);
764
765            partial = partial.begin_field(field.name)?;
766            partial = deserialize_value_into(&synthetic_value, partial)?;
767            partial = partial.end()?;
768            fields_set[idx] = true;
769        }
770    }
771
772    // Handle missing fields - try to set defaults
773    for (idx, field) in struct_def.fields.iter().enumerate() {
774        if fields_set[idx] {
775            continue;
776        }
777
778        // Try to set default for the field
779        partial = partial
780            .set_nth_field_to_default(idx)
781            .map_err(|_| ValueError::new(ValueErrorKind::MissingField { field: field.name }))?;
782    }
783
784    Ok(partial)
785}
786
787/// Deserialize a tuple from a Value::Array.
788fn deserialize_tuple<'facet>(
789    value: &Value,
790    partial: Partial<'facet, false>,
791) -> Result<Partial<'facet, false>> {
792    let mut partial = partial;
793    let arr = value.as_array().ok_or_else(|| {
794        ValueError::new(ValueErrorKind::TypeMismatch {
795            expected: "array",
796            got: value.value_type(),
797        })
798    })?;
799
800    let tuple_len = match &partial.shape().ty {
801        Type::User(UserType::Struct(struct_def)) => struct_def.fields.len(),
802        _ => {
803            return Err(ValueError::new(ValueErrorKind::Unsupported {
804                message: "expected tuple type".into(),
805            }));
806        }
807    };
808
809    if arr.len() != tuple_len {
810        return Err(ValueError::new(ValueErrorKind::Unsupported {
811            message: format!("tuple has {} elements but got {}", tuple_len, arr.len()),
812        }));
813    }
814
815    for (i, item) in arr.iter().enumerate() {
816        partial = partial.begin_nth_field(i)?;
817        partial = deserialize_value_into(item, partial)?;
818        partial = partial.end()?;
819    }
820
821    Ok(partial)
822}
823
824/// Deserialize an enum from a Value.
825fn deserialize_enum<'facet>(
826    value: &Value,
827    partial: Partial<'facet, false>,
828) -> Result<Partial<'facet, false>> {
829    let shape = partial.shape();
830
831    let tag_key = shape.get_tag_attr();
832    let content_key = shape.get_content_attr();
833
834    // Check for numeric enums first (like #[repr(u8)] enums)
835    if shape.is_numeric() && tag_key.is_none() {
836        return deserialize_numeric_enum(value, partial);
837    }
838
839    if shape.is_untagged() {
840        return deserialize_untagged_enum(value, partial);
841    }
842
843    match (tag_key, content_key) {
844        // Internally tagged: {"type": "Circle", "radius": 5.0}
845        (Some(tag_key), None) => deserialize_internally_tagged_enum(value, partial, tag_key),
846        // Adjacently tagged: {"t": "Message", "c": "hello"}
847        (Some(tag_key), Some(content_key)) => {
848            deserialize_adjacently_tagged_enum(value, partial, tag_key, content_key)
849        }
850        // Externally tagged (default): {"VariantName": {...}}
851        (None, None) => deserialize_externally_tagged_enum(value, partial),
852        // Invalid: content without tag
853        (None, Some(_)) => Err(ValueError::new(ValueErrorKind::Unsupported {
854            message: "content key without tag key is invalid".into(),
855        })),
856    }
857}
858
859/// Deserialize a numeric enum from a Value::Number or Value::String.
860///
861/// Numeric enums use their discriminant value for serialization (e.g., `#[repr(u8)]` enums).
862/// Accepts:
863/// - Number values (i64/u64)
864/// - String values that can be parsed as i64
865fn deserialize_numeric_enum<'facet>(
866    value: &Value,
867    mut partial: Partial<'facet, false>,
868) -> Result<Partial<'facet, false>> {
869    let discriminant = match value.value_type() {
870        ValueType::Number => {
871            let num = value.as_number().unwrap();
872            if let Some(i) = num.to_i64() {
873                i
874            } else {
875                return Err(ValueError::new(ValueErrorKind::TypeMismatch {
876                    expected: "Could not parse discriminant into i64", // TODO
877                    got: ValueType::Number,
878                }));
879            }
880        }
881        ValueType::String => {
882            // Parse string as i64 discriminant
883            let s = value.as_string().unwrap().as_str();
884            s.parse().map_err(|_| {
885                ValueError::new(ValueErrorKind::TypeMismatch {
886                    expected: "Failed to parse string into i64",
887                    got: ValueType::String,
888                })
889            })?
890        }
891        other => {
892            return Err(ValueError::new(ValueErrorKind::TypeMismatch {
893                expected: "Expected number or string for numeric enum",
894                got: other,
895            }));
896        }
897    };
898
899    partial = partial.select_variant(discriminant)?;
900    Ok(partial)
901}
902
903/// Deserialize an externally tagged enum: {"VariantName": data} or "VariantName"
904fn deserialize_externally_tagged_enum<'facet>(
905    value: &Value,
906    mut partial: Partial<'facet, false>,
907) -> Result<Partial<'facet, false>> {
908    match value.value_type() {
909        // String = unit variant
910        ValueType::String => {
911            let variant_name = value.as_string().unwrap().as_str();
912            partial = partial.select_variant_named(variant_name)?;
913            Ok(partial)
914        }
915        // Object = externally tagged variant with data
916        ValueType::Object => {
917            let obj = value.as_object().unwrap();
918            if obj.len() != 1 {
919                return Err(ValueError::new(ValueErrorKind::Unsupported {
920                    message: format!("enum object must have exactly 1 key, got {}", obj.len()),
921                }));
922            }
923
924            let (key, val) = obj.iter().next().unwrap();
925            let variant_name = key.as_str();
926
927            partial = partial.select_variant_named(variant_name)?;
928
929            let variant = partial.selected_variant().ok_or_else(|| {
930                ValueError::new(ValueErrorKind::Unsupported {
931                    message: "failed to get selected variant".into(),
932                })
933            })?;
934
935            populate_variant_from_value(val, partial, &variant)
936        }
937        other => Err(ValueError::new(ValueErrorKind::TypeMismatch {
938            expected: "string or object for enum",
939            got: other,
940        })),
941    }
942}
943
944/// Deserialize an internally tagged enum: {"type": "Circle", "radius": 5.0}
945fn deserialize_internally_tagged_enum<'facet>(
946    value: &Value,
947    mut partial: Partial<'facet, false>,
948    tag_key: &str,
949) -> Result<Partial<'facet, false>> {
950    let obj = value.as_object().ok_or_else(|| {
951        ValueError::new(ValueErrorKind::TypeMismatch {
952            expected: "object for internally tagged enum",
953            got: value.value_type(),
954        })
955    })?;
956
957    // Find the tag value
958    let tag_value = obj.get(tag_key).ok_or_else(|| {
959        ValueError::new(ValueErrorKind::Unsupported {
960            message: format!("internally tagged enum missing tag key '{tag_key}'"),
961        })
962    })?;
963
964    if partial.shape().is_numeric() {
965        let discriminant = tag_value
966            .as_number()
967            .and_then(VNumber::to_i64)
968            .ok_or_else(|| {
969                ValueError::new(ValueErrorKind::TypeMismatch {
970                    expected: "integer for enum discriminant",
971                    got: tag_value.value_type(),
972                })
973            })?;
974        partial = partial.select_variant(discriminant)?;
975    } else {
976        let variant_name = tag_value.as_string().ok_or_else(|| {
977            ValueError::new(ValueErrorKind::TypeMismatch {
978                expected: "string for enum tag",
979                got: tag_value.value_type(),
980            })
981        })?;
982        partial = partial.select_variant_named(variant_name.as_str())?;
983    }
984
985    let variant = partial.selected_variant().ok_or_else(|| {
986        ValueError::new(ValueErrorKind::Unsupported {
987            message: "failed to get selected variant".into(),
988        })
989    })?;
990
991    // For struct variants, deserialize the remaining fields (excluding the tag)
992    match variant.data.kind {
993        StructKind::Unit => {
994            // Unit variant - just the tag, no other fields expected
995            Ok(partial)
996        }
997        StructKind::Struct => {
998            // Struct variant - deserialize fields from the same object (excluding tag)
999            for field in variant.data.fields.iter() {
1000                if let Some(field_value) = obj
1001                    .get(field.effective_name())
1002                    .or_else(|| field.alias.and_then(|alias| obj.get(alias)))
1003                {
1004                    partial = partial.begin_field(field.name)?;
1005                    partial = deserialize_enum_field_value(field_value, field, partial)?;
1006                    partial = partial.end()?;
1007                }
1008            }
1009            Ok(partial)
1010        }
1011        StructKind::TupleStruct | StructKind::Tuple => {
1012            Err(ValueError::new(ValueErrorKind::Unsupported {
1013                message: "internally tagged tuple variants are not supported".into(),
1014            }))
1015        }
1016    }
1017}
1018
1019/// Deserialize an adjacently tagged enum: {"t": "Message", "c": "hello"}
1020fn deserialize_adjacently_tagged_enum<'facet>(
1021    value: &Value,
1022    mut partial: Partial<'facet, false>,
1023    tag_key: &str,
1024    content_key: &str,
1025) -> Result<Partial<'facet, false>> {
1026    let obj = value.as_object().ok_or_else(|| {
1027        ValueError::new(ValueErrorKind::TypeMismatch {
1028            expected: "object for adjacently tagged enum",
1029            got: value.value_type(),
1030        })
1031    })?;
1032
1033    // Find the tag value
1034    let tag_value = obj.get(tag_key).ok_or_else(|| {
1035        ValueError::new(ValueErrorKind::Unsupported {
1036            message: format!("adjacently tagged enum missing tag key '{tag_key}'"),
1037        })
1038    })?;
1039
1040    if partial.shape().is_numeric() {
1041        let discriminant = tag_value
1042            .as_number()
1043            .and_then(VNumber::to_i64)
1044            .ok_or_else(|| {
1045                ValueError::new(ValueErrorKind::TypeMismatch {
1046                    expected: "integer for enum discriminant",
1047                    got: tag_value.value_type(),
1048                })
1049            })?;
1050        partial = partial.select_variant(discriminant)?;
1051    } else {
1052        let variant_name = tag_value.as_string().ok_or_else(|| {
1053            ValueError::new(ValueErrorKind::TypeMismatch {
1054                expected: "string for enum tag",
1055                got: tag_value.value_type(),
1056            })
1057        })?;
1058        partial = partial.select_variant_named(variant_name.as_str())?;
1059    }
1060
1061    let variant = partial.selected_variant().ok_or_else(|| {
1062        ValueError::new(ValueErrorKind::Unsupported {
1063            message: "failed to get selected variant".into(),
1064        })
1065    })?;
1066
1067    // For non-unit variants, get the content
1068    match variant.data.kind {
1069        StructKind::Unit => {
1070            // Unit variant - no content field needed
1071            Ok(partial)
1072        }
1073        _ => {
1074            // Get the content value
1075            let content_value = obj.get(content_key).ok_or_else(|| {
1076                ValueError::new(ValueErrorKind::Unsupported {
1077                    message: format!("adjacently tagged enum missing content key '{content_key}'"),
1078                })
1079            })?;
1080
1081            populate_variant_from_value(content_value, partial, &variant)
1082        }
1083    }
1084}
1085
1086fn deserialize_untagged_enum<'facet>(
1087    value: &Value,
1088    partial: Partial<'facet, false>,
1089) -> Result<Partial<'facet, false>> {
1090    let mut partial = partial;
1091    let shape = partial.shape();
1092    let enum_type = match &shape.ty {
1093        Type::User(UserType::Enum(enum_def)) => enum_def,
1094        _ => {
1095            return Err(ValueError::new(ValueErrorKind::Unsupported {
1096                message: "expected enum type".into(),
1097            }));
1098        }
1099    };
1100
1101    for variant in enum_type.variants.iter() {
1102        if value_matches_variant(value, variant) {
1103            partial = partial.select_variant_named(variant.effective_name())?;
1104            return populate_variant_from_value(value, partial, variant);
1105        }
1106    }
1107
1108    Err(ValueError::new(ValueErrorKind::TypeMismatch {
1109        expected: shape.type_identifier,
1110        got: value.value_type(),
1111    }))
1112}
1113
1114fn populate_variant_from_value<'facet>(
1115    value: &Value,
1116    mut partial: Partial<'facet, false>,
1117    variant: &Variant,
1118) -> Result<Partial<'facet, false>> {
1119    match variant.data.kind {
1120        StructKind::Unit => {
1121            if !matches!(value.value_type(), ValueType::Null) {
1122                return Err(ValueError::new(ValueErrorKind::TypeMismatch {
1123                    expected: "null for unit variant",
1124                    got: value.value_type(),
1125                }));
1126            }
1127        }
1128        StructKind::TupleStruct | StructKind::Tuple => {
1129            let num_fields = variant.data.fields.len();
1130            if num_fields == 0 {
1131                // nothing to populate
1132            } else if num_fields == 1 {
1133                let field = variant.data.fields[0];
1134                partial = partial.begin_nth_field(0)?;
1135                partial = deserialize_enum_field_value(value, &field, partial)?;
1136                partial = partial.end()?;
1137            } else {
1138                let arr = value.as_array().ok_or_else(|| {
1139                    ValueError::new(ValueErrorKind::TypeMismatch {
1140                        expected: "array for tuple variant",
1141                        got: value.value_type(),
1142                    })
1143                })?;
1144
1145                if arr.len() != num_fields {
1146                    return Err(ValueError::new(ValueErrorKind::Unsupported {
1147                        message: format!(
1148                            "tuple variant has {} fields but got {}",
1149                            num_fields,
1150                            arr.len()
1151                        ),
1152                    }));
1153                }
1154
1155                for (i, (field, item)) in variant.data.fields.iter().zip(arr.iter()).enumerate() {
1156                    partial = partial.begin_nth_field(i)?;
1157                    partial = deserialize_enum_field_value(item, field, partial)?;
1158                    partial = partial.end()?;
1159                }
1160            }
1161        }
1162        StructKind::Struct => {
1163            let inner_obj = value.as_object().ok_or_else(|| {
1164                ValueError::new(ValueErrorKind::TypeMismatch {
1165                    expected: "object for struct variant",
1166                    got: value.value_type(),
1167                })
1168            })?;
1169
1170            for (field_key, field_val) in inner_obj.iter() {
1171                let key = field_key.as_str();
1172                let field = variant
1173                    .data
1174                    .fields
1175                    .iter()
1176                    .find(|f| f.effective_name() == key || f.alias == Some(key))
1177                    .ok_or_else(|| {
1178                        ValueError::new(ValueErrorKind::UnknownField {
1179                            field: key.to_string(),
1180                        })
1181                    })?;
1182
1183                partial = partial.begin_field(field.name)?;
1184                partial = deserialize_enum_field_value(field_val, field, partial)?;
1185                partial = partial.end()?;
1186            }
1187        }
1188    }
1189
1190    Ok(partial)
1191}
1192
1193fn deserialize_enum_field_value<'facet>(
1194    value: &Value,
1195    field: &Field,
1196    mut partial: Partial<'facet, false>,
1197) -> Result<Partial<'facet, false>> {
1198    #[cfg(feature = "alloc")]
1199    if field.proxy_convert_in_fn().is_some() {
1200        partial = partial.begin_custom_deserialization()?;
1201        partial = deserialize_value_into(value, partial)?;
1202        partial = partial.end()?;
1203    } else {
1204        partial = deserialize_value_into(value, partial)?;
1205    }
1206
1207    #[cfg(not(feature = "alloc"))]
1208    {
1209        partial = deserialize_value_into(value, partial)?;
1210    }
1211
1212    Ok(partial)
1213}
1214
1215fn value_matches_variant(value: &Value, variant: &Variant) -> bool {
1216    match variant.data.kind {
1217        StructKind::Unit => matches!(value.value_type(), ValueType::Null),
1218        StructKind::TupleStruct | StructKind::Tuple => {
1219            let fields = variant.data.fields;
1220            if fields.is_empty() {
1221                matches!(value.value_type(), ValueType::Null)
1222            } else if fields.len() == 1 {
1223                value_matches_shape(value, fields[0].shape.get())
1224            } else {
1225                value
1226                    .as_array()
1227                    .map(|arr| arr.len() == fields.len())
1228                    .unwrap_or(false)
1229            }
1230        }
1231        StructKind::Struct => matches!(value.value_type(), ValueType::Object),
1232    }
1233}
1234
1235fn value_matches_shape(value: &Value, shape: &'static Shape) -> bool {
1236    match &shape.ty {
1237        Type::Primitive(PrimitiveType::Boolean) => {
1238            matches!(value.value_type(), ValueType::Bool)
1239        }
1240        Type::Primitive(PrimitiveType::Numeric(num)) => match num {
1241            NumericType::Integer { signed } => {
1242                if *signed {
1243                    value.as_number().and_then(|n| n.to_i64()).is_some()
1244                } else {
1245                    value.as_number().and_then(|n| n.to_u64()).is_some()
1246                }
1247            }
1248            NumericType::Float => value.as_number().and_then(|n| n.to_f64()).is_some(),
1249        },
1250        _ => true,
1251    }
1252}
1253
1254/// Deserialize a list/Vec from a Value::Array.
1255fn deserialize_list<'facet>(
1256    value: &Value,
1257    partial: Partial<'facet, false>,
1258) -> Result<Partial<'facet, false>> {
1259    let mut partial = partial;
1260    let arr = value.as_array().ok_or_else(|| {
1261        ValueError::new(ValueErrorKind::TypeMismatch {
1262            expected: "array",
1263            got: value.value_type(),
1264        })
1265    })?;
1266
1267    partial = partial.init_list()?;
1268
1269    for item in arr.iter() {
1270        partial = partial.begin_list_item()?;
1271        partial = deserialize_value_into(item, partial)?;
1272        partial = partial.end()?;
1273    }
1274
1275    Ok(partial)
1276}
1277
1278/// Deserialize a fixed-size array from a Value::Array.
1279fn deserialize_array<'facet>(
1280    value: &Value,
1281    partial: Partial<'facet, false>,
1282) -> Result<Partial<'facet, false>> {
1283    let mut partial = partial;
1284    let arr = value.as_array().ok_or_else(|| {
1285        ValueError::new(ValueErrorKind::TypeMismatch {
1286            expected: "array",
1287            got: value.value_type(),
1288        })
1289    })?;
1290
1291    let array_len = match &partial.shape().def {
1292        Def::Array(arr_def) => arr_def.n,
1293        _ => {
1294            return Err(ValueError::new(ValueErrorKind::Unsupported {
1295                message: "expected array type".into(),
1296            }));
1297        }
1298    };
1299
1300    if arr.len() != array_len {
1301        return Err(ValueError::new(ValueErrorKind::Unsupported {
1302            message: format!(
1303                "fixed array has {} elements but got {}",
1304                array_len,
1305                arr.len()
1306            ),
1307        }));
1308    }
1309
1310    for (i, item) in arr.iter().enumerate() {
1311        partial = partial.begin_nth_field(i)?;
1312        partial = deserialize_value_into(item, partial)?;
1313        partial = partial.end()?;
1314    }
1315
1316    Ok(partial)
1317}
1318
1319/// Deserialize a set from a Value::Array.
1320fn deserialize_set<'facet>(
1321    value: &Value,
1322    partial: Partial<'facet, false>,
1323) -> Result<Partial<'facet, false>> {
1324    let mut partial = partial;
1325    let arr = value.as_array().ok_or_else(|| {
1326        ValueError::new(ValueErrorKind::TypeMismatch {
1327            expected: "array",
1328            got: value.value_type(),
1329        })
1330    })?;
1331
1332    partial = partial.init_set()?;
1333
1334    for item in arr.iter() {
1335        partial = partial.begin_set_item()?;
1336        partial = deserialize_value_into(item, partial)?;
1337        partial = partial.end()?;
1338    }
1339
1340    Ok(partial)
1341}
1342
1343/// Deserialize a map from a Value::Object.
1344fn deserialize_map<'facet>(
1345    value: &Value,
1346    partial: Partial<'facet, false>,
1347) -> Result<Partial<'facet, false>> {
1348    let mut partial = partial;
1349    let obj = value.as_object().ok_or_else(|| {
1350        ValueError::new(ValueErrorKind::TypeMismatch {
1351            expected: "object",
1352            got: value.value_type(),
1353        })
1354    })?;
1355
1356    partial = partial.init_map()?;
1357
1358    for (key, val) in obj.iter() {
1359        // Set the key
1360        partial = partial.begin_key()?;
1361        // For map keys, we need to handle the key type
1362        // Most commonly it's String, but could be other types with inner
1363        if partial.shape().inner.is_some() {
1364            partial = partial.begin_inner()?;
1365            partial = partial.set(key.as_str().to_string())?;
1366            partial = partial.end()?;
1367        } else {
1368            partial = partial.set(key.as_str().to_string())?;
1369        }
1370        partial = partial.end()?;
1371
1372        // Set the value
1373        partial = partial.begin_value()?;
1374        partial = deserialize_value_into(val, partial)?;
1375        partial = partial.end()?;
1376    }
1377
1378    Ok(partial)
1379}
1380
1381/// Deserialize an Option from a Value.
1382fn deserialize_option<'facet>(
1383    value: &Value,
1384    partial: Partial<'facet, false>,
1385) -> Result<Partial<'facet, false>> {
1386    let mut partial = partial;
1387    if value.is_null() {
1388        partial = partial.set_default()?; // None
1389    } else {
1390        partial = partial.begin_some()?;
1391        partial = deserialize_value_into(value, partial)?;
1392        partial = partial.end()?;
1393    }
1394    Ok(partial)
1395}
1396
1397/// Deserialize a smart pointer (Box, Arc, Rc) or Cow from a Value.
1398fn deserialize_pointer<'facet>(
1399    value: &Value,
1400    partial: Partial<'facet, false>,
1401) -> Result<Partial<'facet, false>> {
1402    use facet_core::{KnownPointer, SequenceType};
1403
1404    let mut partial = partial;
1405    let (is_slice_pointer, is_reference, is_cow) =
1406        if let Def::Pointer(ptr_def) = partial.shape().def {
1407            let is_slice = if let Some(pointee) = ptr_def.pointee() {
1408                matches!(pointee.ty, Type::Sequence(SequenceType::Slice(_)))
1409            } else {
1410                false
1411            };
1412            let is_ref = matches!(
1413                ptr_def.known,
1414                Some(KnownPointer::SharedReference | KnownPointer::ExclusiveReference)
1415            );
1416            let is_cow = matches!(ptr_def.known, Some(KnownPointer::Cow));
1417            (is_slice, is_ref, is_cow)
1418        } else {
1419            (false, false, false)
1420        };
1421
1422    // References can't be deserialized (need existing data to borrow from)
1423    if is_reference {
1424        return Err(ValueError::new(ValueErrorKind::Unsupported {
1425            message: format!(
1426                "cannot deserialize into reference type '{}'",
1427                partial.shape().type_identifier
1428            ),
1429        }));
1430    }
1431
1432    // Cow needs special handling
1433    if is_cow {
1434        // Check if this is Cow<str> - we can set it directly from a string value
1435        if let Def::Pointer(ptr_def) = partial.shape().def
1436            && let Some(pointee) = ptr_def.pointee()
1437            && matches!(
1438                pointee.ty,
1439                Type::Primitive(PrimitiveType::Textual(TextualType::Str))
1440            )
1441        {
1442            // This is Cow<str> - deserialize from string
1443            if let Some(s) = value.as_string() {
1444                // Set the owned string value - Cow<str> will store it as Owned
1445                partial = partial.set(alloc::borrow::Cow::<'static, str>::Owned(
1446                    s.as_str().to_string(),
1447                ))?;
1448                return Ok(partial);
1449            } else {
1450                return Err(ValueError::new(ValueErrorKind::TypeMismatch {
1451                    expected: "string for Cow<str>",
1452                    got: value.value_type(),
1453                }));
1454            }
1455        }
1456        // For other Cow types, use begin_inner
1457        partial = partial.begin_inner()?;
1458        partial = deserialize_value_into(value, partial)?;
1459        partial = partial.end()?;
1460        return Ok(partial);
1461    }
1462
1463    partial = partial.begin_smart_ptr()?;
1464
1465    if is_slice_pointer {
1466        // This is a slice pointer like Arc<[T]> - deserialize as array
1467        let arr = value.as_array().ok_or_else(|| {
1468            ValueError::new(ValueErrorKind::TypeMismatch {
1469                expected: "array",
1470                got: value.value_type(),
1471            })
1472        })?;
1473
1474        for item in arr.iter() {
1475            partial = partial.begin_list_item()?;
1476            partial = deserialize_value_into(item, partial)?;
1477            partial = partial.end()?;
1478        }
1479    } else {
1480        // Regular smart pointer - deserialize the inner type
1481        partial = deserialize_value_into(value, partial)?;
1482    }
1483
1484    partial = partial.end()?;
1485    Ok(partial)
1486}
1487
1488#[cfg(test)]
1489mod tests {
1490    use super::*;
1491    use crate::{VArray, VObject, VString};
1492
1493    #[test]
1494    fn test_deserialize_primitives() {
1495        // bool
1496        let v = Value::TRUE;
1497        let b: bool = from_value(v).unwrap();
1498        assert!(b);
1499
1500        // i32
1501        let v = Value::from(42i64);
1502        let n: i32 = from_value(v).unwrap();
1503        assert_eq!(n, 42);
1504
1505        // String
1506        let v: Value = VString::new("hello").into();
1507        let s: String = from_value(v).unwrap();
1508        assert_eq!(s, "hello");
1509    }
1510
1511    #[test]
1512    fn test_deserialize_option() {
1513        // Some
1514        let v = Value::from(42i64);
1515        let opt: Option<i32> = from_value(v).unwrap();
1516        assert_eq!(opt, Some(42));
1517
1518        // None
1519        let v = Value::NULL;
1520        let opt: Option<i32> = from_value(v).unwrap();
1521        assert_eq!(opt, None);
1522    }
1523
1524    #[test]
1525    fn test_deserialize_vec() {
1526        let mut arr = VArray::new();
1527        arr.push(Value::from(1i64));
1528        arr.push(Value::from(2i64));
1529        arr.push(Value::from(3i64));
1530
1531        let v: Value = arr.into();
1532        let vec: alloc::vec::Vec<i32> = from_value(v).unwrap();
1533        assert_eq!(vec, alloc::vec![1, 2, 3]);
1534    }
1535
1536    #[test]
1537    fn test_deserialize_nested() {
1538        // Vec<Option<i32>>
1539        let mut arr = VArray::new();
1540        arr.push(Value::from(1i64));
1541        arr.push(Value::NULL);
1542        arr.push(Value::from(3i64));
1543
1544        let v: Value = arr.into();
1545        let vec: alloc::vec::Vec<Option<i32>> = from_value(v).unwrap();
1546        assert_eq!(vec, alloc::vec![Some(1), None, Some(3)]);
1547    }
1548
1549    #[test]
1550    fn test_deserialize_map() {
1551        use alloc::collections::BTreeMap;
1552
1553        let mut obj = VObject::new();
1554        obj.insert("a", Value::from(1i64));
1555        obj.insert("b", Value::from(2i64));
1556
1557        let v: Value = obj.into();
1558        let map: BTreeMap<String, i32> = from_value(v).unwrap();
1559        assert_eq!(map.get("a"), Some(&1));
1560        assert_eq!(map.get("b"), Some(&2));
1561    }
1562}