1use embedded_hal::digital::v2::toggleable;
9use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
10
11#[derive(PartialEq, Eq, Debug)]
12pub enum State {
13 Low,
14 High,
15}
16
17pub struct Pin {
18 state: Option<State>,
19}
20
21impl Pin {
22 pub fn new() -> Self {
23 Pin { state: None }
24 }
25
26 pub fn with_state(state: State) -> Self {
27 Pin { state: Some(state) }
28 }
29}
30
31type MockError = &'static str;
32
33impl InputPin for Pin {
34 type Error = MockError;
35
36 fn is_high(&self) -> Result<bool, Self::Error> {
37 match self.state {
38 Some(State::High) => Ok(true),
39 Some(State::Low) => Ok(false),
40 None => Err("state not set"),
41 }
42 }
43
44 fn is_low(&self) -> Result<bool, Self::Error> {
45 match self.is_high() {
46 Ok(v) => Ok(!v),
47 Err(e) => Err(e),
48 }
49 }
50}
51
52impl OutputPin for Pin {
53 type Error = MockError;
54
55 fn set_low(&mut self) -> Result<(), Self::Error> {
56 self.state = Some(State::Low);
57 Ok(())
58 }
59
60 fn set_high(&mut self) -> Result<(), Self::Error> {
61 self.state = Some(State::High);
62 Ok(())
63 }
64}
65
66impl StatefulOutputPin for Pin {
67 fn is_set_low(&self) -> Result<bool, Self::Error> {
68 self.is_low()
69 }
70
71 fn is_set_high(&self) -> Result<bool, Self::Error> {
72 self.is_high()
73 }
74}
75
76impl toggleable::Default for Pin {}
77
78#[cfg(test)]
79mod test {
80 use super::*;
81
82 mod new {
83 use super::*;
84
85 #[test]
86 fn state_is_unitialized() {
87 let pin = Pin::new();
88 assert_eq!(None, pin.state);
89 pin.is_low().expect_err("Expected unitialized pin");
90 }
91 }
92
93 mod input_pin {
94 use super::*;
95
96 #[test]
97 fn error_when_uninitialized() {
98 let pin = Pin { state: None };
99 pin.is_high().expect_err("Expected unitialized pin");
100 }
101
102 mod is_high {
103 use super::*;
104
105 #[test]
106 fn returns_true_when_state_is_high() {
107 let pin = Pin::with_state(State::High);
108 assert_eq!(true, pin.is_high().unwrap());
109 }
110
111 #[test]
112 fn returns_false_when_state_is_low() {
113 let pin = Pin::with_state(State::Low);
114 assert_eq!(false, pin.is_high().unwrap());
115 }
116 }
117
118 mod is_low {
119 use super::*;
120
121 #[test]
122 fn returns_false_when_state_is_high() {
123 let pin = Pin::with_state(State::High);
124 assert_eq!(false, pin.is_low().unwrap());
125 }
126
127 #[test]
128 fn returns_true_when_state_is_high() {
129 let pin = Pin::with_state(State::Low);
130 assert_eq!(true, pin.is_low().unwrap());
131 }
132 }
133 }
134
135 mod output_pin {
136 use super::*;
137
138 #[test]
139 fn set_low() {
140 let mut pin = Pin::new();
141 pin.set_low().unwrap();
142
143 assert_eq!(true, pin.is_low().unwrap());
144 }
145
146 #[test]
147 fn set_high() {
148 let mut pin = Pin::new();
149 pin.set_high().unwrap();
150
151 assert_eq!(true, pin.is_high().unwrap());
152 }
153 }
154
155 mod statful_output_pin {
156 use super::*;
157
158 #[test]
159 fn error_when_uninitialized() {
160 let pin = Pin { state: None };
161 pin.is_set_high().expect_err("Expected unitialized pin");
162 }
163
164 mod is_set_low {
165 use super::*;
166
167 #[test]
168 fn returns_false_when_state_is_high() {
169 let pin = Pin::with_state(State::High);
170 assert_eq!(false, pin.is_set_low().unwrap());
171 }
172
173 #[test]
174 fn returns_true_when_state_is_high() {
175 let pin = Pin::with_state(State::Low);
176 assert_eq!(true, pin.is_set_low().unwrap());
177 }
178 }
179
180 mod is_set_high {
181 use super::*;
182
183 #[test]
184 fn returns_true_when_state_is_high() {
185 let pin = Pin::with_state(State::High);
186 assert_eq!(true, pin.is_set_high().unwrap());
187 }
188
189 #[test]
190 fn returns_false_when_state_is_low() {
191 let pin = Pin::with_state(State::Low);
192 assert_eq!(false, pin.is_set_high().unwrap());
193 }
194 }
195
196 mod toggleable {
197 use super::*;
198 use embedded_hal::digital::v2::ToggleableOutputPin;
199
200 #[test]
201 fn default_toggleable_impl() {
202 let mut pin = Pin::with_state(State::Low);
203 pin.toggle().unwrap();
204 assert_eq!(true, pin.is_set_high().unwrap());
205 }
206 }
207 }
208}