From da8b3d42c70d9e06e57e15d6e1d5d60b8bf81fec Mon Sep 17 00:00:00 2001 From: Ryan Kurte Date: Tue, 18 Dec 2018 11:06:02 +1300 Subject: [PATCH 01/11] Working on compatibility shims for digital traits --- Cargo.toml | 2 + src/digital/mod.rs | 159 ++++----------------------------------- src/digital/v1.rs | 145 +++++++++++++++++++++++++++++++++++ src/digital/v1_compat.rs | 102 +++++++++++++++++++++++++ src/digital/v2.rs | 4 +- src/digital/v2_compat.rs | 101 +++++++++++++++++++++++++ src/lib.rs | 2 +- 7 files changed, 369 insertions(+), 146 deletions(-) create mode 100644 src/digital/v1.rs create mode 100644 src/digital/v1_compat.rs create mode 100644 src/digital/v2_compat.rs diff --git a/Cargo.toml b/Cargo.toml index d1f6fb673..68110b00a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,8 @@ futures = "0.1.17" [features] unproven = ["nb/unstable"] +v1-compat = [] +v2-compat = [] [package.metadata.docs.rs] features = ["unproven"] diff --git a/src/digital/mod.rs b/src/digital/mod.rs index 5784f0fbe..da499c51f 100644 --- a/src/digital/mod.rs +++ b/src/digital/mod.rs @@ -1,155 +1,26 @@ //! Digital I/O //! -//! The traits in this module are now deprecated. Please use the new versions included -//! in `digital::v2`. +//! -/// Single digital push-pull output pin -/// -/// *This version of the trait is now deprecated. Please use the new `OutputPin` trait in -/// `digital::v2::OutputPin`*. +// Depreciated / infallible traits #[deprecated(since = "0.2.2", note = "Deprecated because the methods cannot return errors. \ Users should use the traits in digital::v2.")] -pub trait OutputPin { - /// Drives the pin low - /// - /// *NOTE* the actual electrical state of the pin may not actually be low, e.g. due to external - /// electrical sources - fn set_low(&mut self); +pub mod v1; - /// Drives the pin high - /// - /// *NOTE* the actual electrical state of the pin may not actually be high, e.g. due to external - /// electrical sources - fn set_high(&mut self); -} - -/// Push-pull output pin that can read its output state -/// -/// *This trait is available if embedded-hal is built with the `"unproven"` feature.* -/// -/// *This version of the trait is now deprecated. Please use the new `StatefulOutputPin` trait in -/// `digital::v2::StatefulOutputPin`*. -#[deprecated(since = "0.2.2", note = "Deprecated because the methods cannot return errors. \ - Users should use the traits in digital::v2.")] -#[cfg(feature = "unproven")] -pub trait StatefulOutputPin { - /// Is the pin in drive high mode? - /// - /// *NOTE* this does *not* read the electrical state of the pin - fn is_set_high(&self) -> bool; - - /// Is the pin in drive low mode? - /// - /// *NOTE* this does *not* read the electrical state of the pin - fn is_set_low(&self) -> bool; -} - -/// Output pin that can be toggled -/// -/// *This trait is available if embedded-hal is built with the `"unproven"` feature.* -/// -/// *This version of the trait is now deprecated. Please use the new `ToggleableOutputPin` -/// trait in `digital::v2::ToggleableOutputPin`*. -/// -/// See [toggleable](toggleable) to use a software implementation if -/// both [OutputPin](trait.OutputPin.html) and -/// [StatefulOutputPin](trait.StatefulOutputPin.html) are -/// implemented. Otherwise, implement this using hardware mechanisms. -#[deprecated(since = "0.2.2", note = "Deprecated because the methods cannot return errors. \ - Users should use the traits in digital::v2.")] -#[cfg(feature = "unproven")] -pub trait ToggleableOutputPin { - /// Toggle pin output. - fn toggle(&mut self); -} +// New / fallible traits +pub mod v2; -/// If you can read **and** write the output state, a pin is -/// toggleable by software. -/// -/// *This version of the module is now deprecated. Please use the new `toggleable` module in -/// `digital::v2::toggleable`*. -/// -/// ``` -/// use embedded_hal::digital::{OutputPin, StatefulOutputPin, ToggleableOutputPin}; -/// use embedded_hal::digital::toggleable; -/// -/// /// A virtual output pin that exists purely in software -/// struct MyPin { -/// state: bool -/// } -/// -/// impl OutputPin for MyPin { -/// fn set_low(&mut self) { -/// self.state = false; -/// } -/// fn set_high(&mut self) { -/// self.state = true; -/// } -/// } -/// -/// impl StatefulOutputPin for MyPin { -/// fn is_set_low(&self) -> bool { -/// !self.state -/// } -/// fn is_set_high(&self) -> bool { -/// self.state -/// } -/// } -/// -/// /// Opt-in to the software implementation. -/// impl toggleable::Default for MyPin {} -/// -/// let mut pin = MyPin { state: false }; -/// pin.toggle(); -/// assert!(pin.is_set_high()); -/// pin.toggle(); -/// assert!(pin.is_set_low()); -/// ``` -#[deprecated(since = "0.2.2", note = "Deprecated because the methods cannot return errors. \ - Users should use the traits in digital::v2.")] -#[cfg(feature = "unproven")] -pub mod toggleable { - #[allow(deprecated)] - use super::{OutputPin, StatefulOutputPin, ToggleableOutputPin}; +// Compatibility shims, only one can be active at a time to avoid recursive errors - /// Software-driven `toggle()` implementation. - /// - /// *This trait is available if embedded-hal is built with the `"unproven"` feature.* - #[allow(deprecated)] - pub trait Default: OutputPin + StatefulOutputPin {} +// v2 -> v1 compatibility shims +#[cfg(feature = "v1-compat")] +pub mod v1_compat; - #[allow(deprecated)] - impl

ToggleableOutputPin for P - where - P: Default, - { - /// Toggle pin output - fn toggle(&mut self) { - if self.is_set_low() { - self.set_high(); - } else { - self.set_low(); - } - } - } -} +// v1 -> v2 compatibility shims +#[cfg(feature = "v2-compat")] +pub mod v2_compat; -/// Single digital input pin -/// -/// *This trait is available if embedded-hal is built with the `"unproven"` feature.* -/// -/// *This version of the trait is now deprecated. Please use the new `InputPin` trait in -/// `digital::v2::InputPin`*. -#[deprecated(since = "0.2.2", note = "Deprecated because the methods cannot return errors. \ - Users should use the traits in digital::v2.")] -#[cfg(feature = "unproven")] -pub trait InputPin { - /// Is the input pin high? - fn is_high(&self) -> bool; - - /// Is the input pin low? - fn is_low(&self) -> bool; -} +// Re-export old traits so this isn't a breaking change +#[allow(deprecated)] +pub use self::v1::*; -/// Improved version of the digital traits where the methods can also return an error. -pub mod v2; diff --git a/src/digital/v1.rs b/src/digital/v1.rs new file mode 100644 index 000000000..d7bbfacaa --- /dev/null +++ b/src/digital/v1.rs @@ -0,0 +1,145 @@ +//! Digital I/O +//! +//! The traits in this module are now deprecated. Please use the new versions included +//! in `digital::v2`. + +#![allow(deprecated)] + +/// Single digital push-pull output pin +/// +/// *This version of the trait is now deprecated. Please use the new `OutputPin` trait in +/// `digital::v2::OutputPin`*. + +pub trait OutputPin { + /// Drives the pin low + /// + /// *NOTE* the actual electrical state of the pin may not actually be low, e.g. due to external + /// electrical sources + fn set_low(&mut self); + + /// Drives the pin high + /// + /// *NOTE* the actual electrical state of the pin may not actually be high, e.g. due to external + /// electrical sources + fn set_high(&mut self); +} + +/// Push-pull output pin that can read its output state +/// +/// *This trait is available if embedded-hal is built with the `"unproven"` feature.* +/// +/// *This version of the trait is now deprecated. Please use the new `StatefulOutputPin` trait in +/// `digital::v2::StatefulOutputPin`*. +#[cfg(feature = "unproven")] +pub trait StatefulOutputPin { + /// Is the pin in drive high mode? + /// + /// *NOTE* this does *not* read the electrical state of the pin + fn is_set_high(&self) -> bool; + + /// Is the pin in drive low mode? + /// + /// *NOTE* this does *not* read the electrical state of the pin + fn is_set_low(&self) -> bool; +} + +/// Output pin that can be toggled +/// +/// *This trait is available if embedded-hal is built with the `"unproven"` feature.* +/// +/// *This version of the trait is now deprecated. Please use the new `ToggleableOutputPin` +/// trait in `digital::v2::ToggleableOutputPin`*. +/// +/// See [toggleable](toggleable) to use a software implementation if +/// both [OutputPin](trait.OutputPin.html) and +/// [StatefulOutputPin](trait.StatefulOutputPin.html) are +/// implemented. Otherwise, implement this using hardware mechanisms. +#[cfg(feature = "unproven")] +pub trait ToggleableOutputPin { + /// Toggle pin output. + fn toggle(&mut self); +} + +/// If you can read **and** write the output state, a pin is +/// toggleable by software. +/// +/// *This version of the module is now deprecated. Please use the new `toggleable` module in +/// `digital::v2::toggleable`*. +/// +/// ``` +/// use embedded_hal::digital::{OutputPin, StatefulOutputPin, ToggleableOutputPin}; +/// use embedded_hal::digital::toggleable; +/// +/// /// A virtual output pin that exists purely in software +/// struct MyPin { +/// state: bool +/// } +/// +/// impl OutputPin for MyPin { +/// fn set_low(&mut self) { +/// self.state = false; +/// } +/// fn set_high(&mut self) { +/// self.state = true; +/// } +/// } +/// +/// impl StatefulOutputPin for MyPin { +/// fn is_set_low(&self) -> bool { +/// !self.state +/// } +/// fn is_set_high(&self) -> bool { +/// self.state +/// } +/// } +/// +/// /// Opt-in to the software implementation. +/// impl toggleable::Default for MyPin {} +/// +/// let mut pin = MyPin { state: false }; +/// pin.toggle(); +/// assert!(pin.is_set_high()); +/// pin.toggle(); +/// assert!(pin.is_set_low()); +/// ``` +#[cfg(feature = "unproven")] +pub mod toggleable { + #[allow(deprecated)] + use super::{OutputPin, StatefulOutputPin, ToggleableOutputPin}; + + /// Software-driven `toggle()` implementation. + /// + /// *This trait is available if embedded-hal is built with the `"unproven"` feature.* + #[allow(deprecated)] + pub trait Default: OutputPin + StatefulOutputPin {} + + #[allow(deprecated)] + impl

ToggleableOutputPin for P + where + P: Default, + { + /// Toggle pin output + fn toggle(&mut self) { + if self.is_set_low() { + self.set_high(); + } else { + self.set_low(); + } + } + } +} + +/// Single digital input pin +/// +/// *This trait is available if embedded-hal is built with the `"unproven"` feature.* +/// +/// *This version of the trait is now deprecated. Please use the new `InputPin` trait in +/// `digital::v2::InputPin`*. +#[cfg(feature = "unproven")] +pub trait InputPin { + /// Is the input pin high? + fn is_high(&self) -> bool; + + /// Is the input pin low? + fn is_low(&self) -> bool; +} diff --git a/src/digital/v1_compat.rs b/src/digital/v1_compat.rs new file mode 100644 index 000000000..5c4a95457 --- /dev/null +++ b/src/digital/v1_compat.rs @@ -0,0 +1,102 @@ +//! v1 compatibility shims +//! this module adds reverse support for v2 digital traits +//! only on of v1_compat or v2_compat may be included at a given time + +#[allow(deprecated)] +use super::v1; +use super::v2; + +/// Implementation of v1 OutputPin trait for v2 fallible output pins +#[allow(deprecated)] +impl v1::OutputPin for T +where + T: v2::OutputPin, + ERR: core::fmt::Debug, +{ + fn set_low(&mut self) { + self.set_low().unwrap() + } + + fn set_high(&mut self) { + self.set_high().unwrap() + } +} + +/// Implementation of v1 StatefulOutputPin trait for v2 fallible pins +#[cfg(feature = "unproven")] +#[allow(deprecated)] +impl v1::StatefulOutputPin for T +where + T: v2::StatefulOutputPin, + ERR: core::fmt::Debug, +{ + fn is_set_low(&self) -> bool { + self.is_set_low().unwrap() + } + + fn is_set_high(&self) -> bool { + self.is_set_high().unwrap() + } +} + +/// Implementation of v0.2 InputPin trait for v0.3 fallible pins +#[cfg(feature = "unproven")] +#[allow(deprecated)] +impl v1::InputPin for T +where + T: v2::InputPin, + ERR: core::fmt::Debug, +{ + fn is_low(&self) -> bool { + self.is_low().unwrap() + } + + fn is_high(&self) -> bool { + self.is_high().unwrap() + } +} + +#[cfg(test)] +#[allow(deprecated)] +mod tests { + #[allow(deprecated)] + use crate::digital::v1; + use crate::digital::v2; + + struct NewOutputPinImpl { + state: bool + } + + impl v2::OutputPin for NewOutputPinImpl { + type Error = (); + + fn set_low(&mut self) -> Result<(), Self::Error> { + self.state = false; + Ok(()) + } + fn set_high(&mut self) -> Result<(), Self::Error>{ + self.state = true; + Ok(()) + } + } + + #[allow(deprecated)] + struct OldOutputPinConsumer { + _pin: T, + } + + #[allow(deprecated)] + impl OldOutputPinConsumer + where T: v1::OutputPin { + pub fn new(pin: T) -> OldOutputPinConsumer { + OldOutputPinConsumer{ _pin: pin } + } + } + + #[test] + fn new_old() { + let i = NewOutputPinImpl{state: false}; + let _c = OldOutputPinConsumer::new(i); + } + +} \ No newline at end of file diff --git a/src/digital/v2.rs b/src/digital/v2.rs index 460005eb0..388dd8a4f 100644 --- a/src/digital/v2.rs +++ b/src/digital/v2.rs @@ -1,4 +1,6 @@ -/// Digital I/O +//! Digital I/O +//! +//! Version 2 / vallible traits. Infallable implementations should set Error to `!`. /// Single digital push-pull output pin pub trait OutputPin { diff --git a/src/digital/v2_compat.rs b/src/digital/v2_compat.rs new file mode 100644 index 000000000..e7116d2f0 --- /dev/null +++ b/src/digital/v2_compat.rs @@ -0,0 +1,101 @@ +//! v2 compatibility shims +//! this module adds forward support to v1 digital traits +//! only on of v1_compat or v2_compat may be included at a given time + +#[allow(deprecated)] +use super::v1; +use super::v2; + +/// Implementation of v2 fallible OutputPin for v1 traits +#[allow(deprecated)] +impl v2::OutputPin for T +where + T: v1::OutputPin, +{ + type Error = (); + + /// Toggle pin output + fn set_low(&mut self) -> Result<(), Self::Error> { + Ok(self.set_low()) + } + + fn set_high(&mut self) -> Result<(), Self::Error> { + Ok(self.set_high()) + } +} + +/// Implementation of v2 fallible StatefulOutputPin for v1 digital traits +#[cfg(feature = "unproven")] +#[allow(deprecated)] +impl v2::StatefulOutputPin for T +where + T: v1::StatefulOutputPin + v1::OutputPin, +{ + /// Toggle pin output + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } + + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } +} + +#[cfg(feature = "unproven")] +#[allow(deprecated)] +impl v2::InputPin for T +where + T: v1::InputPin +{ + type Error = (); + + /// Toggle pin output + fn is_low(&self) -> Result { + Ok(self.is_low()) + } + + fn is_high(&self) -> Result { + Ok(self.is_high()) + } +} + +#[cfg(test)] +mod tests { + + #[allow(deprecated)] + use crate::digital::v1; + use crate::digital::v2; + + #[allow(deprecated)] + struct OldOutputPinImpl { + state: bool + } + + #[allow(deprecated)] + impl v1::OutputPin for OldOutputPinImpl { + fn set_low(&mut self) { + self.state = false; + } + fn set_high(&mut self) { + self.state = true; + } + } + + struct NewOutputPinConsumer { + _pin: T, + } + + impl NewOutputPinConsumer + where T: v2::OutputPin { + pub fn new(pin: T) -> NewOutputPinConsumer { + NewOutputPinConsumer{ _pin: pin } + } + } + + #[test] + fn old_new() { + let i = OldOutputPinImpl{state: false}; + let _c = NewOutputPinConsumer::new(i); + } + +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 1a903081a..1140e8ec1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -683,7 +683,7 @@ //! ``` #![deny(missing_docs)] -#![deny(warnings)] +//#![deny(warnings)] #![no_std] #[macro_use] From 11f83aade3e22aa6e6978909f76a274c0d2fa9ee Mon Sep 17 00:00:00 2001 From: Ryan Kurte Date: Thu, 28 Feb 2019 09:56:34 +1300 Subject: [PATCH 02/11] Fixed v1/v2 compatibility. v1 -> v2 promotion now implicit, v2 -> v1 regression must be explicit with `.into()` --- Cargo.toml | 2 - src/digital/mod.rs | 7 +-- src/digital/v1_compat.rs | 103 +++++++++++++++++++++++++++++++++------ src/digital/v2_compat.rs | 39 ++++++++++++++- 4 files changed, 131 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 68110b00a..d1f6fb673 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,8 +26,6 @@ futures = "0.1.17" [features] unproven = ["nb/unstable"] -v1-compat = [] -v2-compat = [] [package.metadata.docs.rs] features = ["unproven"] diff --git a/src/digital/mod.rs b/src/digital/mod.rs index da499c51f..bd0ed0774 100644 --- a/src/digital/mod.rs +++ b/src/digital/mod.rs @@ -1,6 +1,7 @@ //! Digital I/O //! //! +//! // Depreciated / infallible traits #[deprecated(since = "0.2.2", note = "Deprecated because the methods cannot return errors. \ @@ -12,12 +13,12 @@ pub mod v2; // Compatibility shims, only one can be active at a time to avoid recursive errors -// v2 -> v1 compatibility shims -#[cfg(feature = "v1-compat")] +// v2 -> v1 compatibility wrappers +// These require explicit casts from v2 -> v1 pub mod v1_compat; // v1 -> v2 compatibility shims -#[cfg(feature = "v2-compat")] +// These are implicit over v1 implementations pub mod v2_compat; // Re-export old traits so this isn't a breaking change diff --git a/src/digital/v1_compat.rs b/src/digital/v1_compat.rs index 5c4a95457..be96cb408 100644 --- a/src/digital/v1_compat.rs +++ b/src/digital/v1_compat.rs @@ -1,64 +1,98 @@ -//! v1 compatibility shims +//! v1 compatibility wrapper //! this module adds reverse support for v2 digital traits -//! only on of v1_compat or v2_compat may be included at a given time +//! v2 traits must be explicitly cast to the v1 version using `.into()`. #[allow(deprecated)] use super::v1; use super::v2; +/// Wrapper to allow v2 fallible OutputPin traits to be converted to v1 traits +pub struct OldOutputPin { + pin: T, +} + +impl From for OldOutputPin +where + T: v2::OutputPin, + ERR: core::fmt::Debug, +{ + fn from(pin: T) -> Self { + OldOutputPin{pin} + } +} + /// Implementation of v1 OutputPin trait for v2 fallible output pins #[allow(deprecated)] -impl v1::OutputPin for T +impl v1::OutputPin for OldOutputPin where T: v2::OutputPin, ERR: core::fmt::Debug, { fn set_low(&mut self) { - self.set_low().unwrap() + self.pin.set_low().unwrap() } fn set_high(&mut self) { - self.set_high().unwrap() + self.pin.set_high().unwrap() } } /// Implementation of v1 StatefulOutputPin trait for v2 fallible pins #[cfg(feature = "unproven")] #[allow(deprecated)] -impl v1::StatefulOutputPin for T +impl v1::StatefulOutputPin for OldOutputPin where T: v2::StatefulOutputPin, ERR: core::fmt::Debug, { fn is_set_low(&self) -> bool { - self.is_set_low().unwrap() + self.pin.is_set_low().unwrap() } fn is_set_high(&self) -> bool { - self.is_set_high().unwrap() + self.pin.is_set_high().unwrap() + } +} + +/// Wrapper to allow v2 fallible InputPin traits to be converted to v1 traits +#[cfg(feature = "unproven")] +pub struct OldInputPin { + pin: T, +} + +#[cfg(feature = "unproven")] +impl From for OldInputPin +where + T: v2::InputPin, + ERR: core::fmt::Debug, +{ + fn from(pin: T) -> Self { + OldInputPin{pin} } } /// Implementation of v0.2 InputPin trait for v0.3 fallible pins #[cfg(feature = "unproven")] #[allow(deprecated)] -impl v1::InputPin for T +impl v1::InputPin for OldInputPin where T: v2::InputPin, ERR: core::fmt::Debug, { fn is_low(&self) -> bool { - self.is_low().unwrap() + self.pin.is_low().unwrap() } fn is_high(&self) -> bool { - self.is_high().unwrap() + self.pin.is_high().unwrap() } } #[cfg(test)] #[allow(deprecated)] mod tests { + use super::*; + #[allow(deprecated)] use crate::digital::v1; use crate::digital::v2; @@ -87,16 +121,57 @@ mod tests { #[allow(deprecated)] impl OldOutputPinConsumer - where T: v1::OutputPin { + where T: v1::OutputPin + { pub fn new(pin: T) -> OldOutputPinConsumer { OldOutputPinConsumer{ _pin: pin } } } #[test] - fn new_old() { + fn v1_v2_output_explicit() { let i = NewOutputPinImpl{state: false}; - let _c = OldOutputPinConsumer::new(i); + let _c: OldOutputPinConsumer> = OldOutputPinConsumer::new(i.into()); + } + + #[cfg(feature = "unproven")] + struct NewInputPinImpl { + state: bool, + } + + #[cfg(feature = "unproven")] + impl v2::InputPin for NewInputPinImpl { + type Error = (); + + fn is_low(&self) -> Result { + Ok(!self.state) + } + fn is_high(&self) -> Result{ + Ok(self.state) + } + } + + #[cfg(feature = "unproven")] + #[allow(deprecated)] + struct OldInputPinConsumer { + _pin: T, + } + + #[cfg(feature = "unproven")] + #[allow(deprecated)] + impl OldInputPinConsumer + where T: v1::InputPin + { + pub fn new(pin: T) -> OldInputPinConsumer { + OldInputPinConsumer{ _pin: pin } + } + } + + #[cfg(feature = "unproven")] + #[test] + fn v1_v2_input_explicit() { + let i = NewInputPinImpl{state: false}; + let _c: OldInputPinConsumer> = OldInputPinConsumer::new(i.into()); } } \ No newline at end of file diff --git a/src/digital/v2_compat.rs b/src/digital/v2_compat.rs index e7116d2f0..f622265c2 100644 --- a/src/digital/v2_compat.rs +++ b/src/digital/v2_compat.rs @@ -93,7 +93,44 @@ mod tests { } #[test] - fn old_new() { + fn v2_v1_output_implicit() { + let i = OldOutputPinImpl{state: false}; + let _c = NewOutputPinConsumer::new(i); + } + + #[cfg(feature = "unproven")] + #[allow(deprecated)] + struct OldInputPinImpl { + state: bool + } + + #[cfg(feature = "unproven")] + #[allow(deprecated)] + impl v1::InputPin for OldInputPinImpl { + fn is_low(&self) -> bool { + !self.state + } + fn is_high(&self) -> bool { + self.state + } + } + + #[cfg(feature = "unproven")] + struct NewInputPinConsumer { + _pin: T, + } + + #[cfg(feature = "unproven")] + impl NewInputPinConsumer + where T: v2::InputPin { + pub fn new(pin: T) -> NewInputPinConsumer { + NewInputPinConsumer{ _pin: pin } + } + } + + #[cfg(feature = "unproven")] + #[test] + fn v2_v1_input_implicit() { let i = OldOutputPinImpl{state: false}; let _c = NewOutputPinConsumer::new(i); } From 24854c83d49a9eb11ca154213fab51da111c9250 Mon Sep 17 00:00:00 2001 From: Ryan Kurte Date: Thu, 28 Feb 2019 09:58:47 +1300 Subject: [PATCH 03/11] Added constructors --- src/digital/v1_compat.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/digital/v1_compat.rs b/src/digital/v1_compat.rs index be96cb408..b9dfc1264 100644 --- a/src/digital/v1_compat.rs +++ b/src/digital/v1_compat.rs @@ -11,6 +11,17 @@ pub struct OldOutputPin { pin: T, } +impl OldOutputPin +where + T: v2::OutputPin, + ERR: core::fmt::Debug, +{ + /// Create a new OldOutputPin wrapper around a v2::OutputPin + pub fn new(pin: T) -> Self { + Self{pin} + } +} + impl From for OldOutputPin where T: v2::OutputPin, @@ -60,6 +71,18 @@ pub struct OldInputPin { pin: T, } +#[cfg(feature = "unproven")] +impl OldInputPin +where + T: v2::OutputPin, + ERR: core::fmt::Debug, +{ + /// Create an OldInputPin wrapper around a v2::InputPin + pub fn new(pin: T) -> Self { + Self{pin} + } +} + #[cfg(feature = "unproven")] impl From for OldInputPin where From ae11cf3fcfb8d6cf03875e4d8964443d7711a46f Mon Sep 17 00:00:00 2001 From: Ryan Kurte Date: Thu, 28 Feb 2019 11:35:10 +1300 Subject: [PATCH 04/11] updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfa9671e4..2f7ef0201 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). fallible and their methods now return a `Result` type as setting an output pin and reading an input pin could potentially fail. See [here](https://github.com/rust-embedded/embedded-hal/issues/95) for more info. +- Compatibility shims between `digital::v1` and `digital::v2` traits allowing v1 traits + to be implicitly promoted to v2, and for v2 traits to be explicitly cast to v1 wrappers. ### Changed - The current versions of the `OutputPin`, `StatefulOutputPin`, `ToggleableOutputPin` From e3c4d12b8e5175f5dd00095f9331557edad60017 Mon Sep 17 00:00:00 2001 From: Ryan Kurte Date: Thu, 28 Feb 2019 11:38:15 +1300 Subject: [PATCH 05/11] remove old incompatibilty warning --- src/digital/mod.rs | 2 -- src/digital/v2_compat.rs | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/digital/mod.rs b/src/digital/mod.rs index bd0ed0774..21e38899d 100644 --- a/src/digital/mod.rs +++ b/src/digital/mod.rs @@ -11,8 +11,6 @@ pub mod v1; // New / fallible traits pub mod v2; -// Compatibility shims, only one can be active at a time to avoid recursive errors - // v2 -> v1 compatibility wrappers // These require explicit casts from v2 -> v1 pub mod v1_compat; diff --git a/src/digital/v2_compat.rs b/src/digital/v2_compat.rs index f622265c2..a50d9841b 100644 --- a/src/digital/v2_compat.rs +++ b/src/digital/v2_compat.rs @@ -1,6 +1,5 @@ //! v2 compatibility shims -//! this module adds forward support to v1 digital traits -//! only on of v1_compat or v2_compat may be included at a given time +//! this module adds implicit forward support to v1 digital traits #[allow(deprecated)] use super::v1; From f8e85ca8d13fda3f65332e27677d5e8447dc9297 Mon Sep 17 00:00:00 2001 From: Ryan Kurte Date: Mon, 4 Mar 2019 15:05:55 +1300 Subject: [PATCH 06/11] made suggested changes / improved and fixed tests --- src/digital/v1_compat.rs | 111 ++++++++++++++++++++++++++++----------- src/digital/v2_compat.rs | 25 ++++++++- src/lib.rs | 2 +- 3 files changed, 105 insertions(+), 33 deletions(-) diff --git a/src/digital/v1_compat.rs b/src/digital/v1_compat.rs index b9dfc1264..5d99c9575 100644 --- a/src/digital/v1_compat.rs +++ b/src/digital/v1_compat.rs @@ -11,21 +11,26 @@ pub struct OldOutputPin { pin: T, } -impl OldOutputPin +impl OldOutputPin where - T: v2::OutputPin, - ERR: core::fmt::Debug, + T: v2::OutputPin, + E: core::fmt::Debug, { /// Create a new OldOutputPin wrapper around a v2::OutputPin pub fn new(pin: T) -> Self { Self{pin} } + + /// Fetch a reference to the inner v2::OutputPin impl + pub fn inner(&self) -> &T { + &self.pin + } } -impl From for OldOutputPin +impl From for OldOutputPin where - T: v2::OutputPin, - ERR: core::fmt::Debug, + T: v2::OutputPin, + E: core::fmt::Debug, { fn from(pin: T) -> Self { OldOutputPin{pin} @@ -34,10 +39,10 @@ where /// Implementation of v1 OutputPin trait for v2 fallible output pins #[allow(deprecated)] -impl v1::OutputPin for OldOutputPin +impl v1::OutputPin for OldOutputPin where - T: v2::OutputPin, - ERR: core::fmt::Debug, + T: v2::OutputPin, + E: core::fmt::Debug, { fn set_low(&mut self) { self.pin.set_low().unwrap() @@ -51,10 +56,10 @@ where /// Implementation of v1 StatefulOutputPin trait for v2 fallible pins #[cfg(feature = "unproven")] #[allow(deprecated)] -impl v1::StatefulOutputPin for OldOutputPin +impl v1::StatefulOutputPin for OldOutputPin where - T: v2::StatefulOutputPin, - ERR: core::fmt::Debug, + T: v2::StatefulOutputPin, + E: core::fmt::Debug, { fn is_set_low(&self) -> bool { self.pin.is_set_low().unwrap() @@ -72,22 +77,27 @@ pub struct OldInputPin { } #[cfg(feature = "unproven")] -impl OldInputPin +impl OldInputPin where - T: v2::OutputPin, - ERR: core::fmt::Debug, + T: v2::OutputPin, + E: core::fmt::Debug, { /// Create an OldInputPin wrapper around a v2::InputPin pub fn new(pin: T) -> Self { Self{pin} } + + /// Fetch a reference to the inner v2::InputPin impl + pub fn inner(&self) -> &T { + &self.pin + } } #[cfg(feature = "unproven")] -impl From for OldInputPin +impl From for OldInputPin where - T: v2::InputPin, - ERR: core::fmt::Debug, + T: v2::InputPin, + E: core::fmt::Debug, { fn from(pin: T) -> Self { OldInputPin{pin} @@ -97,10 +107,10 @@ where /// Implementation of v0.2 InputPin trait for v0.3 fallible pins #[cfg(feature = "unproven")] #[allow(deprecated)] -impl v1::InputPin for OldInputPin +impl v1::InputPin for OldInputPin where - T: v2::InputPin, - ERR: core::fmt::Debug, + T: v2::InputPin, + E: core::fmt::Debug, { fn is_low(&self) -> bool { self.pin.is_low().unwrap() @@ -120,8 +130,12 @@ mod tests { use crate::digital::v1; use crate::digital::v2; - struct NewOutputPinImpl { - state: bool + use crate::digital::v1::{InputPin, OutputPin}; + + #[derive(Clone)] + struct NewOutputPinImpl { + state: bool, + res: Result<(), ()> } impl v2::OutputPin for NewOutputPinImpl { @@ -129,11 +143,11 @@ mod tests { fn set_low(&mut self) -> Result<(), Self::Error> { self.state = false; - Ok(()) + self.res } fn set_high(&mut self) -> Result<(), Self::Error>{ self.state = true; - Ok(()) + self.res } } @@ -153,13 +167,32 @@ mod tests { #[test] fn v1_v2_output_explicit() { - let i = NewOutputPinImpl{state: false}; + let i = NewOutputPinImpl{state: false, res: Ok(())}; let _c: OldOutputPinConsumer> = OldOutputPinConsumer::new(i.into()); } + #[test] + fn v1_v2_output_state() { + let mut o: OldOutputPin<_> = NewOutputPinImpl{state: false, res: Ok(())}.into(); + + o.set_high(); + assert_eq!(o.inner().state, true); + + o.set_low(); + assert_eq!(o.inner().state, false); + } + + #[test] + #[should_panic] + fn v1_v2_output_panic() { + let mut o: OldOutputPin<_> = NewOutputPinImpl{state: false, res: Err(())}.into(); + + o.set_high(); + } + #[cfg(feature = "unproven")] struct NewInputPinImpl { - state: bool, + state: Result, } #[cfg(feature = "unproven")] @@ -167,10 +200,10 @@ mod tests { type Error = (); fn is_low(&self) -> Result { - Ok(!self.state) + self.state.map(|v| v == false) } fn is_high(&self) -> Result{ - Ok(self.state) + self.state.map(|v| v == true) } } @@ -193,8 +226,26 @@ mod tests { #[cfg(feature = "unproven")] #[test] fn v1_v2_input_explicit() { - let i = NewInputPinImpl{state: false}; + let i = NewInputPinImpl{state: Ok(false)}; let _c: OldInputPinConsumer> = OldInputPinConsumer::new(i.into()); } + #[cfg(feature = "unproven")] + #[test] + fn v1_v2_input_state() { + let i: OldInputPin<_> = NewInputPinImpl{state: Ok(false)}.into(); + + assert_eq!(i.is_low(), true); + assert_eq!(i.is_high(), false); + } + + #[cfg(feature = "unproven")] + #[test] + #[should_panic] + fn v1_v2_input_panic() { + let i: OldInputPin<_> = NewInputPinImpl{state: Err(())}.into(); + + i.is_low(); + } + } \ No newline at end of file diff --git a/src/digital/v2_compat.rs b/src/digital/v2_compat.rs index a50d9841b..5a983f552 100644 --- a/src/digital/v2_compat.rs +++ b/src/digital/v2_compat.rs @@ -11,6 +11,7 @@ impl v2::OutputPin for T where T: v1::OutputPin, { + // TODO: update to ! when never_type is stabilized type Error = (); /// Toggle pin output @@ -46,6 +47,7 @@ impl v2::InputPin for T where T: v1::InputPin { + // TODO: update to ! when never_type is stabilized type Error = (); /// Toggle pin output @@ -97,6 +99,17 @@ mod tests { let _c = NewOutputPinConsumer::new(i); } + #[test] + fn v2_v1_output_state() { + let mut o = OldOutputPinImpl{state: false}; + + v2::OutputPin::set_high(&mut o).unwrap(); + assert_eq!(o.state, true); + + v2::OutputPin::set_low(&mut o).unwrap(); + assert_eq!(o.state, false); + } + #[cfg(feature = "unproven")] #[allow(deprecated)] struct OldInputPinImpl { @@ -130,8 +143,16 @@ mod tests { #[cfg(feature = "unproven")] #[test] fn v2_v1_input_implicit() { - let i = OldOutputPinImpl{state: false}; - let _c = NewOutputPinConsumer::new(i); + let i = OldInputPinImpl{state: false}; + let _c = NewInputPinConsumer::new(i); } + #[cfg(feature = "unproven")] + #[test] + fn v2_v1_input_state() { + let mut i = OldInputPinImpl{state: false}; + + assert_eq!(v2::InputPin::is_high(&mut i).unwrap(), false); + assert_eq!(v2::InputPin::is_low(&mut i).unwrap(), true); + } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 1140e8ec1..1a903081a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -683,7 +683,7 @@ //! ``` #![deny(missing_docs)] -//#![deny(warnings)] +#![deny(warnings)] #![no_std] #[macro_use] From a157a54d86c7e51814958dde0ff8c570ada55f07 Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Mon, 4 Mar 2019 15:07:34 +1300 Subject: [PATCH 07/11] Apply suggestions from code review Co-Authored-By: ryankurte --- src/digital/v1_compat.rs | 10 ++++++---- src/digital/v2.rs | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/digital/v1_compat.rs b/src/digital/v1_compat.rs index 5d99c9575..d890bbb88 100644 --- a/src/digital/v1_compat.rs +++ b/src/digital/v1_compat.rs @@ -53,7 +53,8 @@ where } } -/// Implementation of v1 StatefulOutputPin trait for v2 fallible pins +/// Implementation of `v1::StatefulOutputPin` trait for `v2::StatefulOutputPin` fallible pins +/// where errors will panic. #[cfg(feature = "unproven")] #[allow(deprecated)] impl v1::StatefulOutputPin for OldOutputPin @@ -82,7 +83,7 @@ where T: v2::OutputPin, E: core::fmt::Debug, { - /// Create an OldInputPin wrapper around a v2::InputPin + /// Create an `OldInputPin` wrapper around a `v2::InputPin`. pub fn new(pin: T) -> Self { Self{pin} } @@ -104,7 +105,8 @@ where } } -/// Implementation of v0.2 InputPin trait for v0.3 fallible pins +/// Implementation of `v1::InputPin` trait for `v2::InputPin` fallible pins +/// where errors will panic. #[cfg(feature = "unproven")] #[allow(deprecated)] impl v1::InputPin for OldInputPin @@ -248,4 +250,4 @@ mod tests { i.is_low(); } -} \ No newline at end of file +} diff --git a/src/digital/v2.rs b/src/digital/v2.rs index 388dd8a4f..2d25c50f1 100644 --- a/src/digital/v2.rs +++ b/src/digital/v2.rs @@ -1,6 +1,6 @@ //! Digital I/O //! -//! Version 2 / vallible traits. Infallable implementations should set Error to `!`. +//! Version 2 / fallible traits. Infallable implementations should set Error to `!`. /// Single digital push-pull output pin pub trait OutputPin { From 7cbdc3fe7df2823f0b703f9ff561c9f82ca5b619 Mon Sep 17 00:00:00 2001 From: Ryan Kurte Date: Mon, 4 Mar 2019 15:12:26 +1300 Subject: [PATCH 08/11] Clean up comments --- src/digital/v1_compat.rs | 12 ++++++------ src/digital/v2_compat.rs | 11 +++++------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/digital/v1_compat.rs b/src/digital/v1_compat.rs index d890bbb88..ebfa1b204 100644 --- a/src/digital/v1_compat.rs +++ b/src/digital/v1_compat.rs @@ -6,7 +6,7 @@ use super::v1; use super::v2; -/// Wrapper to allow v2 fallible OutputPin traits to be converted to v1 traits +/// Wrapper to allow fallible `v2::OutputPin` traits to be converted to `v1::OutputPin` traits pub struct OldOutputPin { pin: T, } @@ -16,12 +16,12 @@ where T: v2::OutputPin, E: core::fmt::Debug, { - /// Create a new OldOutputPin wrapper around a v2::OutputPin + /// Create a new OldOutputPin wrapper around a `v2::OutputPin` pub fn new(pin: T) -> Self { Self{pin} } - /// Fetch a reference to the inner v2::OutputPin impl + /// Fetch a reference to the inner `v2::OutputPin` impl pub fn inner(&self) -> &T { &self.pin } @@ -37,7 +37,7 @@ where } } -/// Implementation of v1 OutputPin trait for v2 fallible output pins +/// Implementation of `v1::OutputPin` trait for fallible `v2::OutputPin` output pins #[allow(deprecated)] impl v1::OutputPin for OldOutputPin where @@ -71,7 +71,7 @@ where } } -/// Wrapper to allow v2 fallible InputPin traits to be converted to v1 traits +/// Wrapper to allow fallible `v2::InputPin` traits to be converted to `v1::InputPin` traits #[cfg(feature = "unproven")] pub struct OldInputPin { pin: T, @@ -88,7 +88,7 @@ where Self{pin} } - /// Fetch a reference to the inner v2::InputPin impl + /// Fetch a reference to the inner `v2::InputPin` impl pub fn inner(&self) -> &T { &self.pin } diff --git a/src/digital/v2_compat.rs b/src/digital/v2_compat.rs index 5a983f552..779c089d3 100644 --- a/src/digital/v2_compat.rs +++ b/src/digital/v2_compat.rs @@ -5,7 +5,7 @@ use super::v1; use super::v2; -/// Implementation of v2 fallible OutputPin for v1 traits +/// Implementation of fallible `v2::OutputPin` for `v1::OutputPin` traits #[allow(deprecated)] impl v2::OutputPin for T where @@ -14,24 +14,22 @@ where // TODO: update to ! when never_type is stabilized type Error = (); - /// Toggle pin output fn set_low(&mut self) -> Result<(), Self::Error> { Ok(self.set_low()) } - fn set_high(&mut self) -> Result<(), Self::Error> { + fn set_high(&mut self) -> Result<(), Self::Error> { Ok(self.set_high()) } } -/// Implementation of v2 fallible StatefulOutputPin for v1 digital traits +/// Implementation of fallible `v2::StatefulOutputPin` for `v1::StatefulOutputPin` digital traits #[cfg(feature = "unproven")] #[allow(deprecated)] impl v2::StatefulOutputPin for T where T: v1::StatefulOutputPin + v1::OutputPin, { - /// Toggle pin output fn is_set_low(&self) -> Result { Ok(self.is_set_low()) } @@ -41,6 +39,8 @@ where } } + +/// Implementation of fallible `v2::InputPin` for `v1::InputPin` digital traits #[cfg(feature = "unproven")] #[allow(deprecated)] impl v2::InputPin for T @@ -50,7 +50,6 @@ where // TODO: update to ! when never_type is stabilized type Error = (); - /// Toggle pin output fn is_low(&self) -> Result { Ok(self.is_low()) } From c74f8d173e0e461b7e872ca4c86010515d3140a7 Mon Sep 17 00:00:00 2001 From: Ryan Kurte Date: Mon, 4 Mar 2019 15:15:13 +1300 Subject: [PATCH 09/11] made panic notes more consistent --- src/digital/v1_compat.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/digital/v1_compat.rs b/src/digital/v1_compat.rs index ebfa1b204..f819da08e 100644 --- a/src/digital/v1_compat.rs +++ b/src/digital/v1_compat.rs @@ -1,6 +1,7 @@ //! v1 compatibility wrapper //! this module adds reverse support for v2 digital traits -//! v2 traits must be explicitly cast to the v1 version using `.into()`. +//! v2 traits must be explicitly cast to the v1 version using `.into()`, +//! and will panic on internal errors #[allow(deprecated)] use super::v1; @@ -38,6 +39,7 @@ where } /// Implementation of `v1::OutputPin` trait for fallible `v2::OutputPin` output pins +/// where errors will panic. #[allow(deprecated)] impl v1::OutputPin for OldOutputPin where @@ -72,6 +74,7 @@ where } /// Wrapper to allow fallible `v2::InputPin` traits to be converted to `v1::InputPin` traits +/// where errors will panic. #[cfg(feature = "unproven")] pub struct OldInputPin { pin: T, From bf5ecee83a4f7d6e3c33cfd6b3da3e8812387b4e Mon Sep 17 00:00:00 2001 From: Ryan Kurte Date: Tue, 5 Mar 2019 10:11:38 +1300 Subject: [PATCH 10/11] removed .inner from external interface, fixed test without unproven --- src/digital/v1_compat.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/digital/v1_compat.rs b/src/digital/v1_compat.rs index f819da08e..aed9aaf7a 100644 --- a/src/digital/v1_compat.rs +++ b/src/digital/v1_compat.rs @@ -23,7 +23,8 @@ where } /// Fetch a reference to the inner `v2::OutputPin` impl - pub fn inner(&self) -> &T { + #[cfg(test)] + fn inner(&self) -> &T { &self.pin } } @@ -91,10 +92,6 @@ where Self{pin} } - /// Fetch a reference to the inner `v2::InputPin` impl - pub fn inner(&self) -> &T { - &self.pin - } } #[cfg(feature = "unproven")] @@ -135,7 +132,7 @@ mod tests { use crate::digital::v1; use crate::digital::v2; - use crate::digital::v1::{InputPin, OutputPin}; + use crate::digital::v1::OutputPin; #[derive(Clone)] struct NewOutputPinImpl { @@ -195,6 +192,9 @@ mod tests { o.set_high(); } + #[cfg(feature = "unproven")] + use crate::digital::v1::InputPin; + #[cfg(feature = "unproven")] struct NewInputPinImpl { state: Result, From dbf815c0f2ad4a311cbbca808c901fac27a8f266 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Wed, 6 Mar 2019 07:53:09 +1300 Subject: [PATCH 11/11] Apply suggestions from code review Co-Authored-By: ryankurte --- src/digital/mod.rs | 2 +- src/digital/v2.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/digital/mod.rs b/src/digital/mod.rs index 21e38899d..4e67f9851 100644 --- a/src/digital/mod.rs +++ b/src/digital/mod.rs @@ -3,7 +3,7 @@ //! //! -// Depreciated / infallible traits +// Deprecated / infallible traits #[deprecated(since = "0.2.2", note = "Deprecated because the methods cannot return errors. \ Users should use the traits in digital::v2.")] pub mod v1; diff --git a/src/digital/v2.rs b/src/digital/v2.rs index 2d25c50f1..748807225 100644 --- a/src/digital/v2.rs +++ b/src/digital/v2.rs @@ -1,6 +1,6 @@ //! Digital I/O //! -//! Version 2 / fallible traits. Infallable implementations should set Error to `!`. +//! Version 2 / fallible traits. Infallible implementations should set Error to `!`. /// Single digital push-pull output pin pub trait OutputPin {