facet_dom/deserializer/
entrypoints.rs

1//! Deserializer construction and main entry points.
2//!
3//! This module contains the public API for creating deserializers and deserializing values.
4//! These are separated from the implementation details for easy auditing.
5
6use facet_core::Facet;
7use facet_reflect::{HeapValue, Partial};
8
9use super::DomDeserializer;
10use crate::DomParser;
11use crate::error::DomDeserializeError;
12
13impl<'de, P> DomDeserializer<'de, true, P>
14where
15    P: DomParser<'de>,
16{
17    /// Create a new DOM deserializer that can borrow strings from input.
18    pub fn new(parser: P) -> Self {
19        Self {
20            parser,
21            _marker: std::marker::PhantomData,
22        }
23    }
24}
25
26impl<'de, P> DomDeserializer<'de, false, P>
27where
28    P: DomParser<'de>,
29{
30    /// Create a new DOM deserializer that produces owned strings.
31    pub fn new_owned(parser: P) -> Self {
32        Self {
33            parser,
34            _marker: std::marker::PhantomData,
35        }
36    }
37}
38
39impl<'de, P> DomDeserializer<'de, true, P>
40where
41    P: DomParser<'de>,
42{
43    /// Deserialize a value of type `T`, allowing borrowed strings from input.
44    pub fn deserialize<T>(&mut self) -> Result<T, DomDeserializeError<P::Error>>
45    where
46        T: Facet<'de>,
47    {
48        let wip: Partial<'de, true> =
49            Partial::alloc::<T>().map_err(DomDeserializeError::Reflect)?;
50        let partial = self.deserialize_into(wip)?;
51        let heap_value: HeapValue<'de, true> =
52            partial.build().map_err(DomDeserializeError::Reflect)?;
53        heap_value
54            .materialize::<T>()
55            .map_err(DomDeserializeError::Reflect)
56    }
57}
58
59impl<'de, P> DomDeserializer<'de, false, P>
60where
61    P: DomParser<'de>,
62{
63    /// Deserialize a value of type `T` into an owned type.
64    pub fn deserialize<T>(&mut self) -> Result<T, DomDeserializeError<P::Error>>
65    where
66        T: Facet<'static>,
67    {
68        // SAFETY: When BORROW=false, no references into the input are stored.
69        // The Partial only contains owned data (String, Vec, etc.), so the
70        // lifetime parameter is purely phantom. We transmute from 'static to 'de
71        // to satisfy the type system, but the actual data has no lifetime dependency.
72        #[allow(unsafe_code)]
73        let wip: Partial<'de, false> = unsafe {
74            core::mem::transmute::<Partial<'static, false>, Partial<'de, false>>(
75                Partial::alloc_owned::<T>().map_err(DomDeserializeError::Reflect)?,
76            )
77        };
78        let partial = self.deserialize_into(wip)?;
79        // SAFETY: Same reasoning - with BORROW=false, HeapValue contains only
80        // owned data. The 'de lifetime is phantom and we can safely transmute
81        // back to 'static since T: Facet<'static>.
82        #[allow(unsafe_code)]
83        let heap_value: HeapValue<'static, false> = unsafe {
84            core::mem::transmute::<HeapValue<'de, false>, HeapValue<'static, false>>(
85                partial.build().map_err(DomDeserializeError::Reflect)?,
86            )
87        };
88        heap_value
89            .materialize::<T>()
90            .map_err(DomDeserializeError::Reflect)
91    }
92}