1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// saltpig -- the Rustic, ergonomic, and extensible CBOR implementation
// Copyright (C) 2018 Moonbolt{K}
//
// saltpig is free software: you may redistribute and/or modify it under
// version 3.0 or later of the GNU GPL (<LICENSE-GPL> or
// <https://www.gnu.org/licenses/gpl-3.0-standalone.html>), or the BSD 3-Clause
// License (<LICENSE-BSD> or <https://opensource.org/licenses/BSD-3-Clause>), at
// your option.
//
// saltpig is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See either of its licenses for more details.

//! The extension trait, and modules with [IANA-accepted extensions][1].
//!
//! [1]: https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml

pub mod cbor;
pub mod uuid;

use ::std::convert::TryFrom;

use ::value::Value;

/// The extension trait.
///
/// This trait marks types which are _extensions_. Each extension type `T` knows
/// four things:
///
/// - What CBOR tag belongs to it
/// - How to convert a `T` into a [`Value`]
/// - How to tell whether a given `Value` represents a valid `T`
/// - How to convert a `Value` that represents a `T` into an actual `T`
///
/// These are enforced by the `Into<Value>` and `TryFrom<Value>` bounds, and the
/// `TAG` associated const.
///
/// Normally, a `Value` represents a `T` if it is a [`Tagged`] and the tag
/// matches [`T::TAG`], with its classification as representing a _valid_ `T`
/// conditional on the inner value conforming to some specific structure (for
/// example, to be a _valid_ [`Uuid`], a value with tag `37` must be a byte
/// string with length `16`).
///
/// Extension types are expected to meet `saltpig`'s ergonomic standards. For
/// example, an extension type representing a bignum should implement [standard
/// conversions] from and to the relevant bignum type (as well as the required
/// conversions from and to `Value`).
///
/// # Examples
///
/// Each of the submodules is an example. [`extensions::uuid`] is a nice and
/// simple one.
///
/// [`Value`]: ../value/enum.Value.html
/// [`Tagged`]: ../value/enum.Value.html#variant.Tagged
/// [`T::TAG`]: trait.Extension.html#associatedconstant.TAG
/// [`Uuid`]: uuid/struct.Uuid.html
/// [standard conversions]: https://doc.rust-lang.org/std/convert/
/// [`extensions::uuid`]: uuid/index.html
pub trait Extension: Into<Value> + TryFrom<Value> {
    /// The tag value belonging to this extension type.
    const TAG: u64;
}