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}