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