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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright 2019 Andrew Thomas Christensen
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the
// MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option. This file may not be copied,
// modified, or distributed except according to those terms.
use crate::;
/// A meta-`trait` defining the common `Base` type and `Mode` storage conventions used by a related group of `Mode`
/// implementations. `Mode`s can **only** transition to other `Mode`s within the same `Family`, i.e. where both `Mode`s
/// share the same `Family` associated `type`.
///
/// # The `Base` type
/// The `Base` associated type may be either a `dyn Trait` or a concrete type that represents how the current `Mode` can
/// be accessed from outside the `Automaton`.
///
/// If given some `dyn Trait`, **only** functions common to the `trait` interface will be callable on the current
/// `Mode`, as the `Automaton` will **only** allow it to be borrowed via a `trait` reference. However, the `Automaton`
/// will allow swapping between different concrete implementations of this common interface, provided that the `Mode`
/// associated `type` is a pointer of some kind (e.g. `Box`) and they share the same `Family` associated `type`.
///
/// If given a concrete type, e.g. an `enum` or `struct`, **all** functions and members defined on the inner type will
/// be accessible from outside the `Automaton`. However, this also implies that **all** states in the `Automaton` will
/// be represented by instances of this same concrete type.
///
/// # Usage
/// To define a new `Family` of `Mode`s, simply define a new unit `struct` and `impl Family` for it. This will allow the
/// associated `type`s within `Family` to be defined for that specific `struct`, with the `struct` representing the
/// common usage pattern of all `Mode`s with a `Family` associated `type` equal to that `struct`. (See examples below.)
///
/// ## A `Family` where `Base` is a concrete type
/// ```
/// use mode::{Family, Mode};
///
/// enum SomeMode { A, B, C }
///
/// impl Mode for SomeMode {
/// type Family = SomeFamily;
/// }
///
/// impl SomeMode {
/// pub fn swap(self) -> Self {
/// match self {
/// Self::A => Self::B,
/// Self::B => Self::C,
/// Self::C => Self::A,
/// }
/// }
/// }
///
/// struct SomeFamily;
///
/// impl Family for SomeFamily {
/// type Base = SomeMode; // All SomeFamily Modes will be visible as SomeMode from outside the Automaton.
/// type Mode = SomeMode; // The current Mode in the Automaton will be stored as a SomeMode in-place.
/// }
/// ```
///
/// ## A `Family` where `Base` is a `dyn Trait`
/// ```
/// use mode::{Mode, Family};
///
/// trait SomeTrait : Mode<Family = SomeFamily> {
/// // ...
/// }
///
/// struct SomeFamily;
///
/// impl Family for SomeFamily {
/// type Base = dyn SomeTrait; // All SomeFamily Modes will expose their SomeTrait interface via the Automaton.
/// type Mode = Box<dyn SomeTrait>; // The current Mode in the Automaton will be stored as a Box<dyn SomeTrait>.
/// }
/// ```
///