Skip to main content

dbt_yaml/value/
de.rs

1use crate::mapping::{DuplicateKey, MappingVisitor};
2use crate::path::{OwnedPath, Path};
3use crate::value::de::borrowed::ValueRefDeserializer;
4use crate::value::tagged::TagStringVisitor;
5use crate::value::TaggedValue;
6use crate::{error, number, spanned, Error, Sequence, Span, Value};
7use serde::de::{
8    self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error as _, Expected, MapAccess,
9    SeqAccess, Unexpected, VariantAccess, Visitor,
10};
11use std::fmt;
12
13mod borrowed;
14mod owned;
15
16pub(crate) use borrowed::{MapRefDeserializer, SeqRefDeserializer};
17pub use owned::ValueDeserializer;
18
19/// A type alias for the result of transforming a [Value] into another [Value].
20pub type TransformedResult =
21    Result<Option<Value>, Box<dyn std::error::Error + 'static + Send + Sync>>;
22
23/// A callback type for handling duplicate keys during deserialization.
24pub type DuplicateKeyCallback<'d> =
25    &'d mut dyn for<'p, 'v> FnMut(Path<'p>, &'v Value, &'v Value) -> DuplicateKey;
26
27/// A callback type for handling unused keys during deserialization.
28pub type UnusedKeyCallback<'u> = &'u mut dyn for<'p, 'v> FnMut(Path<'p>, &'v Value, &'v Value);
29
30/// A transformer function for modifying field values during deserialization.
31pub type FieldTransformer<'f> = &'f mut dyn for<'v> FnMut(&'v Value) -> TransformedResult;
32
33impl Value {
34    /// Deserialize a [Value] from a string of YAML text.
35    pub fn from_str<F>(s: &str, duplicate_key_callback: F) -> Result<Self, Error>
36    where
37        F: FnMut(Path<'_>, &Self, &Self) -> DuplicateKey,
38    {
39        let de = crate::de::Deserializer::from_str(s);
40        spanned::set_marker(spanned::Marker::start());
41        let res = deserialize(de, duplicate_key_callback);
42        spanned::reset_marker();
43        res
44    }
45
46    /// Deserialize a [Value] from an IO stream of YAML text.
47    pub fn from_reader<R, F>(rdr: R, duplicate_key_callback: F) -> Result<Self, Error>
48    where
49        R: std::io::Read,
50        F: FnMut(Path<'_>, &Self, &Self) -> DuplicateKey,
51    {
52        let de = crate::de::Deserializer::from_reader(rdr);
53        spanned::set_marker(spanned::Marker::start());
54        let res = deserialize(de, duplicate_key_callback);
55        spanned::reset_marker();
56        res
57    }
58
59    /// Deserialize a [Value] from a byte slice of YAML text.
60    pub fn from_slice<F>(s: &[u8], duplicate_key_callback: F) -> Result<Self, Error>
61    where
62        F: FnMut(Path<'_>, &Self, &Self) -> DuplicateKey,
63    {
64        let de = crate::de::Deserializer::from_slice(s);
65        spanned::set_marker(spanned::Marker::start());
66        let res = deserialize(de, duplicate_key_callback);
67        spanned::reset_marker();
68        res
69    }
70
71    /// Deserialize a [Value] into an instance of some [Deserialize] type `T`.
72    pub fn into_typed<'de, T, U, F>(
73        self,
74        mut unused_key_callback: U,
75        mut field_transformer: F,
76    ) -> Result<T, Error>
77    where
78        T: Deserialize<'de>,
79        U: FnMut(Path<'_>, &Value, &Value),
80        F: for<'v> FnMut(&'v Value) -> TransformedResult,
81    {
82        let de = ValueDeserializer::new_with(
83            self,
84            Path::Root,
85            Some(&mut unused_key_callback),
86            Some(&mut field_transformer),
87        );
88
89        T::deserialize(de)
90    }
91
92    /// Deserialize a [Value] into an instance of some [Deserialize] type `T`,
93    /// without consuming the [Value].
94    pub fn to_typed<'de, T, U, F>(
95        &'de self,
96        mut unused_key_callback: U,
97        mut field_transformer: F,
98    ) -> Result<T, Error>
99    where
100        T: Deserialize<'de>,
101        U: FnMut(Path<'_>, &Value, &Value),
102        F: for<'v> FnMut(&'v Value) -> TransformedResult,
103    {
104        let de = ValueRefDeserializer::new_with(
105            self,
106            Path::Root,
107            Some(&mut unused_key_callback),
108            Some(&mut field_transformer),
109        );
110
111        T::deserialize(de)
112    }
113}
114
115pub(crate) struct ValueVisitor<'d, 'b> {
116    pub callback: DuplicateKeyCallback<'d>,
117    pub path: Path<'b>,
118}
119
120impl<'de> serde::de::Visitor<'de> for ValueVisitor<'_, '_> {
121    type Value = Value;
122
123    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
124        formatter.write_str("any valid YAML value")
125    }
126
127    fn visit_bool<E>(self, b: bool) -> Result<Value, E>
128    where
129        E: serde::de::Error,
130    {
131        Ok(Value::bool(b))
132    }
133
134    fn visit_i64<E>(self, i: i64) -> Result<Value, E>
135    where
136        E: serde::de::Error,
137    {
138        Ok(Value::number(i.into()))
139    }
140
141    fn visit_u64<E>(self, u: u64) -> Result<Value, E>
142    where
143        E: serde::de::Error,
144    {
145        Ok(Value::number(u.into()))
146    }
147
148    fn visit_f64<E>(self, f: f64) -> Result<Value, E>
149    where
150        E: serde::de::Error,
151    {
152        Ok(Value::number(f.into()))
153    }
154
155    fn visit_str<E>(self, s: &str) -> Result<Value, E>
156    where
157        E: serde::de::Error,
158    {
159        Ok(Value::string(s.to_owned()))
160    }
161
162    fn visit_string<E>(self, s: String) -> Result<Value, E>
163    where
164        E: serde::de::Error,
165    {
166        Ok(Value::string(s))
167    }
168
169    fn visit_unit<E>(self) -> Result<Value, E>
170    where
171        E: serde::de::Error,
172    {
173        Ok(Value::null())
174    }
175
176    fn visit_none<E>(self) -> Result<Value, E>
177    where
178        E: serde::de::Error,
179    {
180        Ok(Value::null())
181    }
182
183    fn visit_some<D>(self, deserializer: D) -> Result<Value, D::Error>
184    where
185        D: Deserializer<'de>,
186    {
187        Deserialize::deserialize(deserializer)
188    }
189
190    fn visit_seq<A>(self, data: A) -> Result<Value, A::Error>
191    where
192        A: SeqAccess<'de>,
193    {
194        let de = serde::de::value::SeqAccessDeserializer::new(data);
195        let visitor = SequenceVisitor {
196            callback: &mut *self.callback,
197            path: self.path,
198        };
199        let sequence = de.deserialize_seq(visitor)?;
200        Ok(Value::sequence(sequence))
201    }
202
203    fn visit_map<A>(self, data: A) -> Result<Value, A::Error>
204    where
205        A: MapAccess<'de>,
206    {
207        let de = serde::de::value::MapAccessDeserializer::new(data);
208        let visitor = MappingVisitor {
209            callback: &mut *self.callback,
210            path: self.path,
211        };
212        let mapping = de.deserialize_map(visitor)?;
213        Ok(Value::mapping(mapping))
214    }
215
216    fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
217    where
218        A: EnumAccess<'de>,
219    {
220        let (tag, contents) = data.variant_seed(TagStringVisitor)?;
221        let value = contents.newtype_variant()?;
222        Ok(Value::tagged(TaggedValue { tag, value }))
223    }
224}
225
226impl<'de> DeserializeSeed<'de> for ValueVisitor<'_, '_> {
227    type Value = Value;
228
229    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
230    where
231        D: Deserializer<'de>,
232    {
233        let start = spanned::get_marker();
234        let val = deserializer.deserialize_any(self)?;
235        let span = Span::from(start..spanned::get_marker());
236
237        #[cfg(feature = "filename")]
238        let span = span.maybe_capture_filename();
239
240        Ok(val.with_span(span))
241    }
242}
243
244struct SequenceVisitor<'d, 'b> {
245    pub callback: DuplicateKeyCallback<'d>,
246    pub path: Path<'b>,
247}
248
249impl<'de> serde::de::Visitor<'de> for SequenceVisitor<'_, '_> {
250    type Value = Sequence;
251
252    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
253        formatter.write_str("a sequence")
254    }
255
256    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
257    where
258        A: SeqAccess<'de>,
259    {
260        let mut values = Vec::new();
261        let mut idx = 0;
262        while let Some(value) = seq.next_element_seed(ValueVisitor {
263            callback: &mut *self.callback,
264            path: Path::Seq {
265                parent: &self.path,
266                index: idx,
267            },
268        })? {
269            idx += 1;
270            values.push(value);
271        }
272
273        Ok(values)
274    }
275}
276
277fn deserialize<'de, D, F>(deserializer: D, mut duplicate_key_callback: F) -> Result<Value, D::Error>
278where
279    D: serde::Deserializer<'de>,
280    F: FnMut(Path<'_>, &Value, &Value) -> DuplicateKey,
281{
282    let start = spanned::get_marker();
283    set_is_deserializing_value();
284    let res = deserializer.deserialize_any(ValueVisitor {
285        callback: &mut duplicate_key_callback,
286        path: Path::Root,
287    });
288    let maybe_state = unsafe { load_deserializer_state() };
289    reset_is_deserializing_value();
290
291    // Fast path: if the deserializer has returned a value through the side
292    // channel, then we use it and ignore the result of the deserializer.
293    if let Some(state) = maybe_state {
294        return Ok(state.value);
295    }
296
297    let val = res?;
298    let span = Span::from(start..spanned::get_marker());
299
300    #[cfg(feature = "filename")]
301    let span = span.maybe_capture_filename();
302
303    Ok(val.with_span(span))
304}
305
306impl<'de> Deserialize<'de> for Value {
307    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
308    where
309        D: Deserializer<'de>,
310    {
311        deserialize(deserializer, |_, _, _| DuplicateKey::Error)
312    }
313}
314
315macro_rules! maybe_why_not {
316    ($value_ref:expr, $res:expr) => {{
317        let is_expecting_should_be = $crate::shouldbe::is_expecting_should_be_then_reset();
318        let res = $res;
319        match res {
320            Err(err) if is_expecting_should_be => {
321                let msg = err.to_string();
322                $crate::shouldbe::set_why_not($value_ref.clone(), err);
323                // This error will be ignored by ShouldBe, but we still have to
324                // return an error here nonetheless.
325                Err(Error::custom(msg))
326            }
327            _ => res,
328        }
329    }};
330}
331pub(crate) use maybe_why_not;
332
333impl Value {
334    fn deserialize_number<'de, V>(&self, visitor: V) -> Result<V::Value, Error>
335    where
336        V: Visitor<'de>,
337    {
338        let span = self.span().clone();
339        self.broadcast_end_mark();
340        maybe_why_not!(
341            self,
342            match self.untag_ref() {
343                Value::Number(n, ..) => n.deserialize_any(visitor),
344                other => Err(other.invalid_type(&visitor)),
345            }
346            .map_err(|e| error::set_span(e, span))
347        )
348    }
349
350    #[cold]
351    fn invalid_type(&self, exp: &dyn Expected) -> Error {
352        error::set_span(
353            de::Error::invalid_type(self.unexpected(), exp),
354            self.span().clone(),
355        )
356    }
357
358    /// Returns an [Unexpected] that describes this Value
359    #[cold]
360    pub fn unexpected(&self) -> Unexpected<'_> {
361        match self {
362            Value::Null(..) => Unexpected::Unit,
363            Value::Bool(b, ..) => Unexpected::Bool(*b),
364            Value::Number(n, ..) => number::unexpected(n),
365            Value::String(s, ..) => Unexpected::Str(s),
366            Value::Sequence(..) => Unexpected::Seq,
367            Value::Mapping(..) => Unexpected::Map,
368            Value::Tagged(..) => Unexpected::Enum,
369        }
370    }
371}
372
373#[inline]
374fn should_short_circuit_any(has_transformer: bool) -> bool {
375    if !is_deserializing_value_then_reset() {
376        return false;
377    }
378
379    // We can short circuit if we don't need to transform the value:
380    !has_transformer || !crate::verbatim::should_transform_any()
381}
382
383#[inline]
384fn is_deserializing_value_then_reset() -> bool {
385    clear_deserializer_state();
386    private::IS_DESERIALIZING_VALUE.with(|cell| cell.replace(false))
387}
388
389#[inline]
390fn set_is_deserializing_value() {
391    clear_deserializer_state();
392    private::IS_DESERIALIZING_VALUE.with(|cell| cell.set(true));
393}
394
395#[inline]
396fn reset_is_deserializing_value() {
397    clear_deserializer_state();
398    private::IS_DESERIALIZING_VALUE.with(|cell| cell.set(false));
399}
400
401#[inline]
402fn clear_deserializer_state() {
403    private::THE_VALUE.with(|cell| cell.set(None));
404    private::THE_PATH.with(|cell| cell.set(None));
405    private::UNUSED_KEY_CALLBACK.with(|cell| cell.set(None));
406    private::FIELD_TRANSFORMER.with(|cell| cell.set(None));
407}
408
409unsafe fn save_deserializer_state<'u, 'f>(
410    value: Option<Value>,
411    path: Path<'_>,
412    unused_key_callback: Option<UnusedKeyCallback<'u>>,
413    field_transformer: Option<FieldTransformer<'f>>,
414) {
415    private::THE_VALUE.with(|cell| cell.set(value));
416    private::THE_PATH.with(|cell| cell.set(Some(path.to_owned_path())));
417    private::UNUSED_KEY_CALLBACK.with(|cell| {
418        cell.set(unsafe {
419            std::mem::transmute::<Option<UnusedKeyCallback<'u>>, Option<UnusedKeyCallback<'static>>>(unused_key_callback)
420        })
421    });
422    private::FIELD_TRANSFORMER.with(|cell| {
423        cell.set(unsafe {
424            std::mem::transmute::<Option<FieldTransformer<'f>>, Option<FieldTransformer<'static>>>(
425                field_transformer,
426            )
427        })
428    });
429}
430
431/// Consumes a [Deserializer] and converts it into a [DeserializerState], which
432/// can be used to construct reusable deserializers for deserializing untagged
433/// enum variants.
434pub fn extract_reusable_deserializer_state<'de, D>(
435    deserializer: D,
436) -> Result<DeserializerState, D::Error>
437where
438    D: Deserializer<'de>,
439{
440    set_is_deserializing_value();
441    // Also disable field transformation for this part:
442    let _g = crate::verbatim::with_should_not_transform_any();
443    let res = deserializer.deserialize_any(ValueVisitor {
444        callback: &mut |_, _, _| DuplicateKey::Error,
445        path: Path::Root,
446    });
447    let maybe_state = unsafe { load_deserializer_state() };
448    reset_is_deserializing_value();
449
450    if let Some(state) = maybe_state {
451        Ok(state)
452    } else {
453        let val = res?;
454        Ok(DeserializerState::new(val, OwnedPath::Root, None, None))
455    }
456}
457
458/// Consumes a [Deserializer] and extracts the tag and the reusable deserializer
459/// state. Used for deserializing internally-tagged enums.
460pub fn extract_tag_and_deserializer_state<'de, D>(
461    deserializer: D,
462    tag_key: &str,
463) -> Result<(Value, DeserializerState), D::Error>
464where
465    D: Deserializer<'de>,
466{
467    let mut state = extract_reusable_deserializer_state(deserializer)?;
468    let val = &mut state.value;
469    match val {
470        Value::Mapping(map, ..) => {
471            let Some(mut tag) = map.remove(tag_key) else {
472                return Err(D::Error::custom(format!(
473                    "Expected tag key {tag_key:?} not found"
474                )));
475            };
476            if let Some(transformer) = &mut state.field_transformer {
477                if let Some(transformed) = transformer(&tag)
478                    .map_err(|e| D::Error::custom(format!("Failed to transform tag: {e}")))?
479                {
480                    tag = transformed;
481                }
482            }
483
484            Ok((tag, state))
485        }
486        _ => Err(D::Error::custom("Expected a mapping")),
487    }
488}
489
490/// Captures the state of a [Value] deserializer
491pub struct DeserializerState {
492    value: Value,
493    path: OwnedPath,
494    unused_key_callback: Option<UnusedKeyCallback<'static>>,
495    field_transformer: Option<FieldTransformer<'static>>,
496}
497
498impl DeserializerState {
499    /// Constructs a new [DeserializerState] with the given parameters.
500    pub fn new(
501        value: Value,
502        path: OwnedPath,
503        unused_key_callback: Option<UnusedKeyCallback<'static>>,
504        field_transformer: Option<FieldTransformer<'static>>,
505    ) -> Self {
506        Self {
507            value,
508            path,
509            unused_key_callback,
510            field_transformer,
511        }
512    }
513
514    /// Constructs a Value [Deserializer] from the captured state
515    pub fn get_deserializer<'de, 'u>(
516        &'de mut self,
517        unused_key_callback: Option<UnusedKeyCallback<'u>>,
518    ) -> ValueRefDeserializer<'de, 'de, 'u, 'de> {
519        let field_transformer = self
520            .field_transformer
521            .as_deref_mut()
522            .map(|cb| &mut *cb as FieldTransformer<'_>);
523
524        ValueRefDeserializer::new_with(
525            &self.value,
526            *self.path.as_path(),
527            unused_key_callback,
528            field_transformer,
529        )
530    }
531
532    /// Constructs a Value [Deserializer] from the captured state
533    pub fn get_owned_deserializer<'de>(&'de mut self) -> ValueDeserializer<'de, 'de, 'de> {
534        let value = std::mem::take(&mut self.value);
535
536        ValueDeserializer::new_with(
537            value,
538            *self.path.as_path(),
539            self.unused_key_callback
540                .as_deref_mut()
541                .map(|cb| &mut *cb as UnusedKeyCallback<'_>),
542            self.field_transformer
543                .as_deref_mut()
544                .map(|cb| &mut *cb as FieldTransformer<'_>),
545        )
546    }
547
548    /// Extracts the unused key callback from the state, if any.
549    pub fn take_unused_key_callback(&mut self) -> Option<UnusedKeyCallback<'static>> {
550        self.unused_key_callback.take()
551    }
552}
553
554unsafe fn load_deserializer_state() -> Option<DeserializerState> {
555    let Some(value) = private::THE_VALUE.with(|cell| cell.take()) else {
556        return None;
557    };
558
559    let path = private::THE_PATH
560        .with(|cell| cell.take())
561        .unwrap_or(OwnedPath::Root);
562    let unused_key_callback = private::UNUSED_KEY_CALLBACK.with(|cell| cell.take());
563    let field_transformer = private::FIELD_TRANSFORMER.with(|cell| cell.take());
564
565    Some(DeserializerState {
566        value,
567        path,
568        unused_key_callback,
569        field_transformer,
570    })
571}
572
573mod private {
574    use crate::{path::OwnedPath, Value};
575
576    thread_local! {
577        pub static IS_DESERIALIZING_VALUE: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
578
579        pub static THE_VALUE: std::cell::Cell<Option<Value>> = const { std::cell::Cell::new(None) };
580        pub static THE_PATH: std::cell::Cell<Option<OwnedPath>> = const { std::cell::Cell::new(None) };
581        pub static UNUSED_KEY_CALLBACK: std::cell::Cell<Option<super::UnusedKeyCallback<'static>>> = std::cell::Cell::new(
582            None
583        );
584        pub static FIELD_TRANSFORMER: std::cell::Cell<Option<super::FieldTransformer<'static>>> = std::cell::Cell::new(
585            None
586        );
587    }
588}