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}