embedded-hal 0.2.7

A Hardware Abstraction Layer (HAL) for embedded systems
Documentation
//! v2 compatibility shims
//!
//! This module adds implicit forward support to v1 digital traits,
//! allowing v1 implementations to be directly used with v2 consumers.
//!
//! ```
//! extern crate embedded_hal;
//! use embedded_hal::digital::{v1, v2};
//!
//! struct OldOutputPinImpl { }
//!
//! impl v1::OutputPin for OldOutputPinImpl {
//!     fn set_low(&mut self) { }
//!     fn set_high(&mut self) { }
//! }
//!
//! struct NewOutputPinConsumer<T: v2::OutputPin> {
//!     _pin: T,
//! }
//!
//! impl <T>NewOutputPinConsumer<T>
//! where T: v2::OutputPin {
//!     pub fn new(pin: T) -> NewOutputPinConsumer<T> {
//!         NewOutputPinConsumer{ _pin: pin }
//!     }
//! }
//!
//! fn main() {
//!     let pin = OldOutputPinImpl{};
//!     let _consumer = NewOutputPinConsumer::new(pin);
//! }
//! ```
//!

#[allow(deprecated)]
use super::v1;
use super::v2;

/// Implementation of fallible `v2::OutputPin` for `v1::OutputPin` traits
#[allow(deprecated)]
impl<T> v2::OutputPin for T
where
    T: v1::OutputPin,
{
    // TODO: update to ! when never_type is stabilized
    type Error = ();

    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 fallible `v2::StatefulOutputPin` for `v1::StatefulOutputPin` digital traits
#[cfg(feature = "unproven")]
#[allow(deprecated)]
impl<T> v2::StatefulOutputPin for T
where
    T: v1::StatefulOutputPin + v1::OutputPin,
{
    fn is_set_low(&self) -> Result<bool, Self::Error> {
        Ok(self.is_set_low())
    }

    fn is_set_high(&self) -> Result<bool, Self::Error> {
        Ok(self.is_set_high())
    }
}

#[cfg(feature = "unproven")]
#[allow(deprecated)]
impl<T> v2::toggleable::Default for T where T: v1::toggleable::Default {}

/// Implementation of fallible `v2::InputPin` for `v1::InputPin` digital traits
#[cfg(feature = "unproven")]
#[allow(deprecated)]
impl<T> v2::InputPin for T
where
    T: v1::InputPin,
{
    // TODO: update to ! when never_type is stabilized
    type Error = ();

    fn is_low(&self) -> Result<bool, Self::Error> {
        Ok(self.is_low())
    }

    fn is_high(&self) -> Result<bool, Self::Error> {
        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;
        }
    }

    #[allow(deprecated)]
    #[cfg(feature = "unproven")]
    impl v1::StatefulOutputPin for OldOutputPinImpl {
        fn is_set_low(&self) -> bool {
            self.state == false
        }

        fn is_set_high(&self) -> bool {
            self.state == true
        }
    }

    #[allow(deprecated)]
    #[cfg(feature = "unproven")]
    impl v1::toggleable::Default for OldOutputPinImpl {}

    struct NewOutputPinConsumer<T: v2::OutputPin> {
        _pin: T,
    }

    impl<T> NewOutputPinConsumer<T>
    where
        T: v2::OutputPin,
    {
        pub fn new(pin: T) -> NewOutputPinConsumer<T> {
            NewOutputPinConsumer { _pin: pin }
        }
    }

    #[cfg(feature = "unproven")]
    struct NewToggleablePinConsumer<T: v2::ToggleableOutputPin> {
        _pin: T,
    }

    #[cfg(feature = "unproven")]
    impl<T> NewToggleablePinConsumer<T>
    where
        T: v2::ToggleableOutputPin,
    {
        pub fn new(pin: T) -> NewToggleablePinConsumer<T> {
            NewToggleablePinConsumer { _pin: pin }
        }
    }

    #[test]
    #[cfg(feature = "unproven")]
    fn v2_v1_toggleable_implicit() {
        let i = OldOutputPinImpl { state: false };
        let _c = NewToggleablePinConsumer::new(i);
    }

    #[test]
    fn v2_v1_output_implicit() {
        let i = OldOutputPinImpl { state: false };
        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 {
        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<T: v2::InputPin> {
        _pin: T,
    }

    #[cfg(feature = "unproven")]
    impl<T> NewInputPinConsumer<T>
    where
        T: v2::InputPin,
    {
        pub fn new(pin: T) -> NewInputPinConsumer<T> {
            NewInputPinConsumer { _pin: pin }
        }
    }

    #[cfg(feature = "unproven")]
    #[test]
    #[cfg(feature = "unproven")]
    fn v2_v1_input_implicit() {
        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);
    }
}