Skip to main content

deser_core/ext/
mod.rs

1//! Extensions to the data model.
2//!
3//! The core data model of deser is intentionally small (see [`Atom`]).  To
4//! support values that do not map naturally onto it, the data model can be
5//! extended with arbitrary types through [`Atom::Ext`].  An extension value
6//! is a typed Rust value implementing [`Extension`] which is passed through
7//! the system as is.
8//!
9//! Every extension value has to provide a [`fallback`](Extension::fallback)
10//! which lowers the value into the core data model.  This means that producers
11//! do not need to know if a consumer understands an extension:
12//!
13//! * a serializer which knows about an extension type can
14//!   [downcast](ExtValue::downcast_ref) the value and handle it natively.
15//!   Otherwise it serializes the fallback.
16//! * a [`Sink`](crate::de::Sink) which knows about an extension type can
17//!   downcast it.  Otherwise the default handling of atoms (see
18//!   [`default_atom`](crate::de::default_atom)) retries with the fallback.
19//!
20//! This avoids in-band signalling: the value keeps its identity for everybody
21//! who understands it, and degrades gracefully for everybody else.
22//!
23//! Deser itself uses this for `u128` and `i128` and a set of well-known
24//! types (see below).  For a more complete example which annotates every
25//! value with its path and shows how that information survives internal
26//! buffering, see the
27//! [`located` example](https://github.com/mitsuhiko/deser/tree/main/examples/located).
28//!
29//! # Borrowing Extensions
30//!
31//! Extension values can borrow data, for instance a number that keeps its
32//! original text from the input.  Such extensions implement
33//! [`BorrowedExtension`] on a `'static` key type which defines the type of
34//! the values for a lifetime.  Their values are created with
35//! [`ExtValue::borrowed_value`] or [`ExtValue::owned_value`] and looked up
36//! with [`ExtValue::downcast_value_ref`].  When values are buffered they are
37//! detached from the data they borrow with
38//! [`BorrowedExtension::to_static`].
39//!
40//! # Well-Known Types
41//!
42//! Some types are common enough that many data formats support them
43//! natively, but they are not part of the core data model.  For these deser
44//! provides well-known extension types.  They are simple dependency free
45//! representations that formats can understand and that the types of other
46//! crates convert into:
47//!
48//! | Type          | Represents                            | Fallback                     |
49//! |---------------|---------------------------------------|------------------------------|
50//! | [`Datetime`]  | dates, times and date-times           | RFC 3339 string              |
51//! | [`Timestamp`] | instants in time                      | RFC 3339 string in UTC       |
52//! | [`Duration`]  | exact lengths of time                 | ISO 8601 duration string     |
53//! | [`Uuid`]      | UUIDs                                 | hyphenated string            |
54//! | [`Decimal`]   | exact decimal numbers                 | decimal string               |
55//! | [`BigInt`]    | integers that do not fit 128 bits     | decimal string               |
56//! | [`Number`]    | number literals of text formats       | `f64`                        |
57//! | [`RawInput`]  | the encoded input of values           | scalars, the input           |
58//!
59//! All well-known types implement [`Serialize`](crate::Serialize) and
60//! [`Deserialize`](crate::Deserialize).  When deserialized they accept
61//! their own extension value, the fallback and other representations where
62//! that makes sense (for instance 16 bytes for a [`Uuid`] or an integer for
63//! a [`Timestamp`]).
64//!
65//! Types of the standard library and of other crates are serialized as
66//! well-known types:
67//!
68//! * [`std::time::SystemTime`] as [`Timestamp`] and
69//!   [`core::time::Duration`] as [`Duration`].
70//! * `jiff` (feature `jiff`): `Timestamp` as [`Timestamp`], `Zoned`,
71//!   `civil::DateTime`, `civil::Date` and `civil::Time` as [`Datetime`],
72//!   `SignedDuration` as [`Duration`].
73//! * `chrono` (feature `chrono`): `DateTime<Utc>` as [`Timestamp`],
74//!   `DateTime<FixedOffset>`, `NaiveDateTime`, `NaiveDate` and `NaiveTime`
75//!   as [`Datetime`], `TimeDelta` as [`Duration`].
76//! * `time` (feature `time`): `UtcDateTime` as [`Timestamp`],
77//!   `OffsetDateTime`, `PrimitiveDateTime`, `Date` and `Time` as
78//!   [`Datetime`], `Duration` as [`Duration`].
79//! * `uuid` (feature `uuid`): `Uuid` as [`Uuid`].
80//! * `rust_decimal` (feature `rust_decimal`): `Decimal` as [`Decimal`].
81//! * `bigdecimal` (feature `bigdecimal`): `BigDecimal` as [`Decimal`].
82//! * `num-bigint` (feature `num-bigint`): `BigInt` and `BigUint` as
83//!   integers, using [`BigInt`] for values that do not fit into 128 bits.
84//!
85//! Types that map onto [`Datetime`] require the matching kind of date-time
86//! when deserialized: a `jiff::civil::Date` can only be deserialized from a
87//! local date.
88//!
89//! # Example
90//!
91//! ```
92//! use deser::de::{Deserialize, Slot, default_atom};
93//! use deser::ext::{Extension, ExtValue};
94//! use deser::ser::{Emit, Serialize};
95//! use deser::State;
96//! use deser::{Atom, Error};
97//!
98//! /// A timestamp in seconds, falls back to an integer.
99//! #[derive(Debug, Clone, PartialEq)]
100//! pub struct Timestamp(pub i64);
101//!
102//! impl Extension for Timestamp {
103//!     fn name(&self) -> &str {
104//!         "timestamp"
105//!     }
106//!
107//!     fn fallback(&self) -> Atom<'_> {
108//!         Atom::I64(self.0)
109//!     }
110//! }
111//!
112//! impl Serialize for Timestamp {
113//!     fn serialize<'a>(value: &'a Self, _state: &mut State) -> Result<Emit<'a>, Error> {
114//!         Ok(Emit::Atom(Atom::Ext(ExtValue::borrowed(value))))
115//!     }
116//! }
117//!
118//! impl<'de> Deserialize<'de> for Timestamp {
119//!     fn deserialize_atom(
120//!         slot: &mut Slot<Self>,
121//!         atom: Atom,
122//!         state: &mut State,
123//!     ) -> Result<(), Error> {
124//!         // the extension value itself
125//!         if let Atom::Ext(ref ext) = atom
126//!             && let Some(value) = ext.downcast_ref::<Timestamp>()
127//!         {
128//!             slot.set(value.clone());
129//!             return Ok(());
130//!         }
131//!         match atom {
132//!             // the fallback (other extension values are passed on as their
133//!             // fallback by `default_atom`)
134//!             Atom::I64(seconds) => {
135//!                 slot.set(Timestamp(seconds));
136//!                 Ok(())
137//!             }
138//!             other => default_atom(slot, other, state),
139//!         }
140//!     }
141//! }
142//!
143//! let value = Timestamp(1_700_000_000);
144//! let mut out = None::<Timestamp>;
145//! deser::de::DeserializeDriver::new(&mut out)
146//!     .emit(Atom::Ext(ExtValue::borrowed(&value)))
147//!     .unwrap();
148//! assert_eq!(out, Some(value));
149//! ```
150//!
151#![cfg_attr(
152    not(feature = "std"),
153    doc = "[`std::time::SystemTime`]: https://doc.rust-lang.org/std/time/struct.SystemTime.html"
154)]
155
156use alloc::string::ToString;
157use alloc::sync::Arc;
158use core::any::{Any, TypeId};
159use core::fmt;
160
161use crate::event::Atom;
162
163mod bigint;
164mod bridges;
165mod datetime;
166mod decimal;
167mod duration;
168pub(crate) mod known;
169mod number;
170pub(crate) mod raw;
171mod uuid;
172
173pub use self::bigint::BigInt;
174pub use self::datetime::{Date, Datetime, Offset, Time, Timestamp};
175pub use self::decimal::Decimal;
176pub use self::duration::Duration;
177pub use self::number::Number;
178pub use self::raw::{Raw, RawFormat, RawFormatId, RawFormatInfo, RawInput, TextRawFormat};
179pub use self::uuid::Uuid;
180
181/// A type that can be passed through deser as an extension to the data model.
182///
183/// This is implemented for extension types without lifetimes, which covers
184/// most extensions.  Types that borrow data implement
185/// [`BorrowedExtension`] instead.
186///
187/// See the [module level documentation](self) for more information.
188pub trait Extension: Any + fmt::Debug + Clone + PartialEq + Send + Sync {
189    /// Returns the human readable name of the extension type.
190    ///
191    /// This is used for error messages.
192    fn name(&self) -> &str;
193
194    /// Lowers the value into the core data model.
195    ///
196    /// This is used by consumers that do not understand this extension.  The
197    /// fallback must not be an [`Atom::Ext`] itself.
198    fn fallback(&self) -> Atom<'_>;
199}
200
201/// An extension whose values can borrow data.
202///
203/// The trait is implemented by a `'static` key type which identifies the
204/// extension.  The values are of type [`Value<'a>`](Self::Value) and can
205/// borrow for `'a`.  Typically the key is the value type with a `'static`
206/// lifetime.  Every [`Extension`] is a borrowed extension whose values are
207/// of the type itself.
208///
209/// All methods are associated functions that take the value.  Values are
210/// created with [`ExtValue::borrowed_value`] and
211/// [`ExtValue::owned_value`] and looked up with
212/// [`ExtValue::downcast_value_ref`] with the key type:
213///
214/// ```
215/// use std::borrow::Cow;
216/// use deser::ext::{BorrowedExtension, ExtValue};
217/// use deser::Atom;
218///
219/// /// A number with its original text.
220/// #[derive(Debug, Clone, PartialEq)]
221/// pub struct Literal<'a> {
222///     pub text: Cow<'a, str>,
223///     pub value: f64,
224/// }
225///
226/// impl BorrowedExtension for Literal<'static> {
227///     type Value<'a> = Literal<'a>;
228///
229///     fn name<'v>(_value: &'v Literal<'_>) -> &'v str {
230///         "literal"
231///     }
232///
233///     fn fallback<'v>(value: &'v Literal<'_>) -> Atom<'v> {
234///         Atom::F64(value.value)
235///     }
236///
237///     fn to_static(value: &Literal<'_>) -> Literal<'static> {
238///         Literal {
239///             text: Cow::Owned(value.text.to_string()),
240///             value: value.value,
241///         }
242///     }
243///
244///     fn shorten<'s, 'l: 's>(value: &'s Literal<'l>) -> &'s Literal<'s> {
245///         value
246///     }
247/// }
248///
249/// let input = String::from("1.50");
250/// let literal = Literal { text: Cow::Borrowed(&input), value: 1.5 };
251/// let ext = ExtValue::borrowed_value::<Literal>(&literal);
252/// assert_eq!(ext.downcast_value_ref::<Literal>().unwrap().text, "1.50");
253/// assert_eq!(ext.fallback(), Atom::F64(1.5));
254/// ```
255pub trait BorrowedExtension: 'static {
256    /// The type of the values of this extension.
257    type Value<'a>: fmt::Debug + PartialEq + Send + Sync + 'a;
258
259    /// Returns the human readable name of the extension type.
260    ///
261    /// This is used for error messages.
262    fn name<'v>(value: &'v Self::Value<'_>) -> &'v str;
263
264    /// Lowers the value into the core data model.
265    ///
266    /// See [`Extension::fallback`].
267    fn fallback<'v>(value: &'v Self::Value<'_>) -> Atom<'v>;
268
269    /// Detaches a value from the data it borrows.
270    ///
271    /// This is used when values are buffered (see
272    /// [`ExtValue::to_static`]).
273    fn to_static(value: &Self::Value<'_>) -> Self::Value<'static>;
274
275    /// Shortens the lifetime of a value.
276    ///
277    /// This proves that a value can be used with a shorter lifetime.  For
278    /// types that are covariant in their lifetime (which is the case for
279    /// most types that hold references or [`Cow`](alloc::borrow::Cow)s) the
280    /// implementation is just `value`.
281    fn shorten<'s, 'l: 's>(value: &'s Self::Value<'l>) -> &'s Self::Value<'s>;
282}
283
284impl<T: Extension> BorrowedExtension for T {
285    type Value<'a> = T;
286
287    fn name(value: &T) -> &str {
288        Extension::name(value)
289    }
290
291    fn fallback<'v>(value: &'v T) -> Atom<'v> {
292        Extension::fallback(value)
293    }
294
295    fn to_static(value: &T) -> T {
296        value.clone()
297    }
298
299    fn shorten<'s, 'l: 's>(value: &'s T) -> &'s T {
300        value
301    }
302}
303
304/// The object safe interface to extension values.
305trait ErasedExtension: fmt::Debug + Send + Sync {
306    /// The type id of the key of the extension.
307    fn key(&self) -> TypeId;
308    fn name(&self) -> &str;
309    fn fallback(&self) -> Atom<'_>;
310    fn to_static(&self) -> Arc<dyn ErasedExtension>;
311    /// Returns a pointer to a `K::Value<'s>` where `'s` is the lifetime of
312    /// the borrow of self if the key is `key`, otherwise null.
313    fn value_ptr(&self, key: TypeId) -> *const ();
314    fn dyn_eq(&self, other: &dyn ErasedExtension) -> bool;
315}
316
317/// Holds the value of an extension with the key `K`.
318#[repr(transparent)]
319struct Holder<'x, K: BorrowedExtension>(K::Value<'x>);
320
321impl<'x, K: BorrowedExtension> fmt::Debug for Holder<'x, K> {
322    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
323        fmt::Debug::fmt(&self.0, f)
324    }
325}
326
327impl<'x, K: BorrowedExtension> ErasedExtension for Holder<'x, K> {
328    fn key(&self) -> TypeId {
329        TypeId::of::<K>()
330    }
331
332    fn name(&self) -> &str {
333        K::name(&self.0)
334    }
335
336    fn fallback(&self) -> Atom<'_> {
337        K::fallback(&self.0)
338    }
339
340    fn to_static(&self) -> Arc<dyn ErasedExtension> {
341        Arc::new(Holder::<'static, K>(K::to_static(&self.0)))
342    }
343
344    #[inline]
345    fn value_ptr(&self, key: TypeId) -> *const () {
346        if key == TypeId::of::<K>() {
347            // the value is shortened through the implementation of the
348            // extension, which proves that it's valid for the shorter
349            // lifetime.
350            K::shorten(&self.0) as *const K::Value<'_> as *const ()
351        } else {
352            core::ptr::null()
353        }
354    }
355
356    fn dyn_eq(&self, other: &dyn ErasedExtension) -> bool {
357        let other = other.value_ptr(TypeId::of::<K>());
358        // SAFETY: the pointer is not null if the keys match, then it points
359        // to a `K::Value<'s>` for the borrow of `other`.
360        !other.is_null() && K::shorten(&self.0) == unsafe { &*(other as *const K::Value<'_>) }
361    }
362}
363
364/// An extension value carried by [`Atom::Ext`].
365///
366/// The value is either borrowed (which is typical during serialization and
367/// for values that formats create while parsing) or owned.  Owned values are
368/// reference counted, so cloning an extension value is cheap.
369///
370/// Extension values are covariant in their lifetime and they can borrow
371/// data (see [`BorrowedExtension`]).
372pub struct ExtValue<'a>(Repr<'a>);
373
374enum Repr<'a> {
375    Borrowed(&'a (dyn ErasedExtension + 'a)),
376    Owned(Arc<dyn ErasedExtension + 'a>),
377}
378
379impl<'a> ExtValue<'a> {
380    /// Creates an extension value borrowing from a value.
381    pub fn borrowed<T: Extension>(value: &'a T) -> ExtValue<'a> {
382        ExtValue::borrowed_value::<T>(value)
383    }
384
385    /// Creates an extension value that owns the value.
386    pub fn owned<T: Extension>(value: T) -> ExtValue<'a> {
387        ExtValue::owned_value::<T>(value)
388    }
389
390    /// Creates an extension value borrowing from the value of an extension.
391    ///
392    /// The extension is identified by its key `K` (see
393    /// [`BorrowedExtension`]).
394    pub fn borrowed_value<K: BorrowedExtension>(value: &'a K::Value<'a>) -> ExtValue<'a> {
395        // SAFETY: the holder is a transparent wrapper around the value
396        let holder = unsafe { &*(value as *const K::Value<'a> as *const Holder<'a, K>) };
397        ExtValue(Repr::Borrowed(holder))
398    }
399
400    /// Creates an extension value that owns the value of an extension.
401    ///
402    /// The extension is identified by its key `K` (see
403    /// [`BorrowedExtension`]).
404    pub fn owned_value<K: BorrowedExtension>(value: K::Value<'a>) -> ExtValue<'a> {
405        ExtValue(Repr::Owned(Arc::new(Holder::<'a, K>(value))))
406    }
407
408    fn get(&self) -> &(dyn ErasedExtension + 'a) {
409        match self.0 {
410            Repr::Borrowed(value) => value,
411            Repr::Owned(ref value) => &**value,
412        }
413    }
414
415    /// Returns the human readable name of the extension type.
416    pub fn name(&self) -> &str {
417        self.get().name()
418    }
419
420    /// Returns the fallback atom of the value.
421    ///
422    /// See [`Extension::fallback`].
423    pub fn fallback(&self) -> Atom<'_> {
424        self.get().fallback()
425    }
426
427    /// Returns `true` if the value is of the extension with the key `K`.
428    ///
429    /// For extensions without lifetimes the key is the type.
430    pub fn is<K: BorrowedExtension>(&self) -> bool {
431        self.get().key() == TypeId::of::<K>()
432    }
433
434    /// Returns the value if it's of type `T`.
435    ///
436    /// ```
437    /// use deser::ext::ExtValue;
438    ///
439    /// let ext = ExtValue::owned(42u128);
440    /// assert_eq!(ext.downcast_ref::<u128>(), Some(&42));
441    /// ```
442    ///
443    /// For extensions that borrow use
444    /// [`downcast_value_ref`](Self::downcast_value_ref).
445    pub fn downcast_ref<T: Extension>(&self) -> Option<&T> {
446        self.downcast_value_ref::<T>()
447    }
448
449    /// Returns the value if it's of the extension with the key `K`.
450    ///
451    /// See [`BorrowedExtension`] for an example.  The returned value borrows
452    /// from this extension value.
453    #[inline]
454    pub fn downcast_value_ref<K: BorrowedExtension>(&self) -> Option<&K::Value<'_>> {
455        let ptr = self.get().value_ptr(TypeId::of::<K>());
456        // SAFETY: the pointer is not null if the keys match, then it points
457        // to a `K::Value<'s>` for the borrow of self.
458        (!ptr.is_null()).then(|| unsafe { &*(ptr as *const K::Value<'_>) })
459    }
460
461    /// Returns the value if it's of the extension with the key `K`, for
462    /// the lifetime of the data it borrows.
463    ///
464    /// # Safety
465    ///
466    /// The values of the extension must be covariant in their lifetime.
467    #[inline]
468    pub(crate) unsafe fn downcast_value_ref_covariant<K: BorrowedExtension>(
469        &self,
470    ) -> Option<&K::Value<'a>> {
471        let ptr = self.get().value_ptr(TypeId::of::<K>());
472        // SAFETY: the pointer is not null if the keys match, then it points
473        // to a `K::Value<'x>` where `'x` outlives `'a`, which is a
474        // `K::Value<'a>` as the values are covariant.
475        (!ptr.is_null()).then(|| unsafe { &*(ptr as *const K::Value<'a>) })
476    }
477
478    /// Returns a value borrowing from this one.
479    pub fn as_borrowed(&self) -> ExtValue<'_> {
480        ExtValue(Repr::Borrowed(self.get()))
481    }
482
483    /// Makes a static clone of the value decoupling the lifetimes.
484    ///
485    /// Values that borrow data are detached from it (see
486    /// [`BorrowedExtension::to_static`]).
487    pub fn to_static(&self) -> ExtValue<'static> {
488        ExtValue(Repr::Owned(self.get().to_static()))
489    }
490}
491
492impl<'a> Clone for ExtValue<'a> {
493    fn clone(&self) -> Self {
494        match self.0 {
495            Repr::Borrowed(value) => ExtValue(Repr::Borrowed(value)),
496            Repr::Owned(ref value) => ExtValue(Repr::Owned(value.clone())),
497        }
498    }
499}
500
501impl<'a> PartialEq for ExtValue<'a> {
502    fn eq(&self, other: &Self) -> bool {
503        self.get().dyn_eq(other.get())
504    }
505}
506
507impl<'a> fmt::Debug for ExtValue<'a> {
508    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509        fmt::Debug::fmt(self.get(), f)
510    }
511}
512
513impl Extension for u128 {
514    fn name(&self) -> &str {
515        "u128"
516    }
517
518    fn fallback(&self) -> Atom<'_> {
519        match u64::try_from(*self) {
520            Ok(value) => Atom::U64(value),
521            Err(_) => Atom::Str(self.to_string().into()),
522        }
523    }
524}
525
526impl Extension for i128 {
527    fn name(&self) -> &str {
528        "i128"
529    }
530
531    fn fallback(&self) -> Atom<'_> {
532        if let Ok(value) = i64::try_from(*self) {
533            Atom::I64(value)
534        } else if let Ok(value) = u64::try_from(*self) {
535            Atom::U64(value)
536        } else {
537            Atom::Str(self.to_string().into())
538        }
539    }
540}
541
542#[test]
543fn test_auto_traits() {
544    fn assert_send_sync<T: Send + Sync>() {}
545    assert_send_sync::<ExtValue<'static>>();
546    assert_send_sync::<Atom<'static>>();
547    assert_send_sync::<crate::Event<'static>>();
548    assert_send_sync::<crate::Error>();
549}
550
551#[test]
552fn test_ext_value() {
553    let value = 42u128;
554    let ext = ExtValue::borrowed(&value);
555    assert!(ext.is::<u128>());
556    assert!(!ext.is::<i128>());
557    assert_eq!(ext.downcast_ref::<u128>(), Some(&42));
558    assert_eq!(ext.fallback(), Atom::U64(42));
559    assert_eq!(ext.to_static(), ExtValue::owned(42u128));
560    assert_ne!(ext, ExtValue::owned(42i128));
561    assert_eq!(format!("{:?}", ext), "42");
562
563    let big = u128::MAX;
564    assert_eq!(
565        ExtValue::borrowed(&big).fallback(),
566        Atom::Str(u128::MAX.to_string().into())
567    );
568    assert_eq!(ExtValue::owned(-1i128).fallback(), Atom::I64(-1));
569    assert_eq!(
570        ExtValue::owned(u64::MAX as i128).fallback(),
571        Atom::U64(u64::MAX)
572    );
573}