embedded_hal/digital/
v1_compat.rs

1//! v1 compatibility wrappers
2//!
3//! This module provides wrappers to support use of v2 implementations with
4//! v1 consumers. v2 traits must be explicitly cast to the v1 version using
5//! `.into()`, and will panic on internal errors
6//!
7//! ```
8//! extern crate embedded_hal;
9//! use embedded_hal::digital::{v1, v2, v1_compat::OldOutputPin};
10//!
11//! struct NewOutputPinImpl {}
12//!
13//! impl v2::OutputPin for NewOutputPinImpl {
14//!     type Error = ();
15//!     fn set_low(&mut self) -> Result<(), Self::Error> { Ok(()) }
16//!     fn set_high(&mut self) -> Result<(), Self::Error>{ Ok(()) }
17//! }
18//!
19//! struct OldOutputPinConsumer<T: v1::OutputPin> {
20//!     _pin: T,
21//! }
22//!
23//! impl <T>OldOutputPinConsumer<T>
24//! where T: v1::OutputPin {
25//!     pub fn new(pin: T) -> OldOutputPinConsumer<T> {
26//!         OldOutputPinConsumer{ _pin: pin }
27//!     }
28//! }
29//!
30//! fn main() {
31//!     let pin = NewOutputPinImpl{};
32//!     let _consumer: OldOutputPinConsumer<OldOutputPin<_>> = OldOutputPinConsumer::new(pin.into());
33//! }
34//! ```
35//!
36
37#[allow(deprecated)]
38use super::v1;
39use super::v2;
40
41/// Wrapper to allow fallible `v2::OutputPin` traits to be converted to `v1::OutputPin` traits
42pub struct OldOutputPin<T> {
43    pin: T,
44}
45
46impl<T, E> OldOutputPin<T>
47where
48    T: v2::OutputPin<Error = E>,
49    E: core::fmt::Debug,
50{
51    /// Create a new OldOutputPin wrapper around a `v2::OutputPin`
52    pub fn new(pin: T) -> Self {
53        Self { pin }
54    }
55
56    /// Fetch a reference to the inner `v2::OutputPin` impl
57    #[cfg(test)]
58    fn inner(&self) -> &T {
59        &self.pin
60    }
61}
62
63impl<T, E> From<T> for OldOutputPin<T>
64where
65    T: v2::OutputPin<Error = E>,
66    E: core::fmt::Debug,
67{
68    fn from(pin: T) -> Self {
69        OldOutputPin { pin }
70    }
71}
72
73/// Implementation of `v1::OutputPin` trait for fallible `v2::OutputPin` output pins
74/// where errors will panic.
75#[allow(deprecated)]
76impl<T, E> v1::OutputPin for OldOutputPin<T>
77where
78    T: v2::OutputPin<Error = E>,
79    E: core::fmt::Debug,
80{
81    fn set_low(&mut self) {
82        self.pin.set_low().unwrap()
83    }
84
85    fn set_high(&mut self) {
86        self.pin.set_high().unwrap()
87    }
88}
89
90/// Implementation of `v1::StatefulOutputPin` trait for `v2::StatefulOutputPin` fallible pins
91/// where errors will panic.
92#[cfg(feature = "unproven")]
93#[allow(deprecated)]
94impl<T, E> v1::StatefulOutputPin for OldOutputPin<T>
95where
96    T: v2::StatefulOutputPin<Error = E>,
97    E: core::fmt::Debug,
98{
99    fn is_set_low(&self) -> bool {
100        self.pin.is_set_low().unwrap()
101    }
102
103    fn is_set_high(&self) -> bool {
104        self.pin.is_set_high().unwrap()
105    }
106}
107
108/// Wrapper to allow fallible `v2::InputPin` traits to be converted to `v1::InputPin` traits
109/// where errors will panic.
110#[cfg(feature = "unproven")]
111pub struct OldInputPin<T> {
112    pin: T,
113}
114
115#[cfg(feature = "unproven")]
116impl<T, E> OldInputPin<T>
117where
118    T: v2::InputPin<Error = E>,
119    E: core::fmt::Debug,
120{
121    /// Create an `OldInputPin` wrapper around a `v2::InputPin`.
122    pub fn new(pin: T) -> Self {
123        Self { pin }
124    }
125}
126
127#[cfg(feature = "unproven")]
128impl<T, E> From<T> for OldInputPin<T>
129where
130    T: v2::InputPin<Error = E>,
131    E: core::fmt::Debug,
132{
133    fn from(pin: T) -> Self {
134        OldInputPin { pin }
135    }
136}
137
138/// Implementation of `v1::InputPin` trait for `v2::InputPin` fallible pins
139/// where errors will panic.
140#[cfg(feature = "unproven")]
141#[allow(deprecated)]
142impl<T, E> v1::InputPin for OldInputPin<T>
143where
144    T: v2::InputPin<Error = E>,
145    E: core::fmt::Debug,
146{
147    fn is_low(&self) -> bool {
148        self.pin.is_low().unwrap()
149    }
150
151    fn is_high(&self) -> bool {
152        self.pin.is_high().unwrap()
153    }
154}
155
156#[cfg(test)]
157#[allow(deprecated)]
158mod tests {
159    use super::*;
160
161    #[allow(deprecated)]
162    use crate::digital::v1;
163    use crate::digital::v2;
164
165    use crate::digital::v1::OutputPin;
166
167    #[derive(Clone)]
168    struct NewOutputPinImpl {
169        state: bool,
170        res: Result<(), ()>,
171    }
172
173    impl v2::OutputPin for NewOutputPinImpl {
174        type Error = ();
175
176        fn set_low(&mut self) -> Result<(), Self::Error> {
177            self.state = false;
178            self.res
179        }
180        fn set_high(&mut self) -> Result<(), Self::Error> {
181            self.state = true;
182            self.res
183        }
184    }
185
186    #[allow(deprecated)]
187    struct OldOutputPinConsumer<T: v1::OutputPin> {
188        _pin: T,
189    }
190
191    #[allow(deprecated)]
192    impl<T> OldOutputPinConsumer<T>
193    where
194        T: v1::OutputPin,
195    {
196        pub fn new(pin: T) -> OldOutputPinConsumer<T> {
197            OldOutputPinConsumer { _pin: pin }
198        }
199    }
200
201    #[test]
202    fn v1_v2_output_explicit() {
203        let i = NewOutputPinImpl {
204            state: false,
205            res: Ok(()),
206        };
207        let _c: OldOutputPinConsumer<OldOutputPin<_>> = OldOutputPinConsumer::new(i.into());
208    }
209
210    #[test]
211    fn v1_v2_output_state() {
212        let mut o: OldOutputPin<_> = NewOutputPinImpl {
213            state: false,
214            res: Ok(()),
215        }
216        .into();
217
218        o.set_high();
219        assert_eq!(o.inner().state, true);
220
221        o.set_low();
222        assert_eq!(o.inner().state, false);
223    }
224
225    #[test]
226    #[should_panic]
227    fn v1_v2_output_panic() {
228        let mut o: OldOutputPin<_> = NewOutputPinImpl {
229            state: false,
230            res: Err(()),
231        }
232        .into();
233
234        o.set_high();
235    }
236
237    #[cfg(feature = "unproven")]
238    use crate::digital::v1::InputPin;
239
240    #[cfg(feature = "unproven")]
241    struct NewInputPinImpl {
242        state: Result<bool, ()>,
243    }
244
245    #[cfg(feature = "unproven")]
246    impl v2::InputPin for NewInputPinImpl {
247        type Error = ();
248
249        fn is_low(&self) -> Result<bool, Self::Error> {
250            self.state.map(|v| v == false)
251        }
252        fn is_high(&self) -> Result<bool, Self::Error> {
253            self.state.map(|v| v == true)
254        }
255    }
256
257    #[cfg(feature = "unproven")]
258    #[allow(deprecated)]
259    struct OldInputPinConsumer<T: v1::InputPin> {
260        _pin: T,
261    }
262
263    #[cfg(feature = "unproven")]
264    #[allow(deprecated)]
265    impl<T> OldInputPinConsumer<T>
266    where
267        T: v1::InputPin,
268    {
269        pub fn new(pin: T) -> OldInputPinConsumer<T> {
270            OldInputPinConsumer { _pin: pin }
271        }
272    }
273
274    #[cfg(feature = "unproven")]
275    #[test]
276    fn v1_v2_input_explicit() {
277        let i = NewInputPinImpl { state: Ok(false) };
278        let _c: OldInputPinConsumer<OldInputPin<_>> = OldInputPinConsumer::new(i.into());
279    }
280
281    #[cfg(feature = "unproven")]
282    #[test]
283    fn v1_v2_input_state() {
284        let i: OldInputPin<_> = NewInputPinImpl { state: Ok(false) }.into();
285
286        assert_eq!(i.is_low(), true);
287        assert_eq!(i.is_high(), false);
288    }
289
290    #[cfg(feature = "unproven")]
291    #[test]
292    #[should_panic]
293    fn v1_v2_input_panic() {
294        let i: OldInputPin<_> = NewInputPinImpl { state: Err(()) }.into();
295
296        i.is_low();
297    }
298}