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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/// Two-way map from a type to `usize` range from `0..ORDINAL_SIZE`.
///
/// Two way ordinal mapping means:
/// - the type has `ORDINAL_SIZE` possible values
/// - each value has a unique ordinal number in the range `0..ORDINAL_SIZE`
/// - each ordinal number corresponds to a unique value
///
/// This type is implemented for
/// - small integer types
/// - tuples
/// - some builtin types like [`Option`] and [`Result`]
/// - and it can be derived with the `#[derive(Ordinal)]` attribute for structs and enums
///
/// # Relation to `Ord` and `PartialOrd`
///
/// Implementations provided in this crate and generated with `#[derive(Ordinal)]`
/// are compatible with `Ord` and `PartialOrd`, meaning `a < b <=> a.ordinal() < b.ordinal()`
/// **with the exception** of derive on enums with explicit discriminants
/// (derive ignores them and assigns ordinal numbers in order of declaration).
///
/// This is not enforced by the trait itself, but it is a good practice to follow.
///
/// # Derive
///
/// `#[derive(Ordinal)]` works for arbitrary structs and enums.
/// Generated implementation is compatible with `#[derive(PartialOrd)]`.
///
/// ```
/// use ordinal_map::Ordinal;
/// #[derive(Ordinal)]
/// enum Color {
/// Red,
/// Cyan,
/// Blue,
/// }
///
/// #[derive(Ordinal)]
/// struct Bright(bool);
///
/// #[derive(Ordinal)]
/// enum MaybeColor {
/// Default,
/// Colored(Color, Bright),
/// Invisible,
/// }
///
/// assert_eq!(0, MaybeColor::Default.ordinal());
/// assert_eq!(1, MaybeColor::Colored(Color::Red, Bright(false)).ordinal());
/// assert_eq!(2, MaybeColor::Colored(Color::Red, Bright(true)).ordinal());
/// assert_eq!(3, MaybeColor::Colored(Color::Cyan, Bright(false)).ordinal());
/// assert_eq!(4, MaybeColor::Colored(Color::Cyan, Bright(true)).ordinal());
/// ```
///
/// # See also
///
/// - [`Iter`](crate::OrdinalValues) to iterate over all possible values.
/// - [`map`](crate::map) module for constant time lookup maps.
/// - [`set`](crate::set) module for constant time lookup sets.