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