use std::cell::RefCell;
use arbitrary::{Arbitrary, Unstructured};
use embedded_hal::digital::{
self, ErrorKind, ErrorType, InputPin, OutputPin, PinState, StatefulOutputPin,
};
#[derive(Debug, Arbitrary)]
pub struct Error;
impl digital::Error for Error {
fn kind(&self) -> ErrorKind {
ErrorKind::Other
}
}
#[derive(Debug, Arbitrary)]
pub struct ArbitraryInputPin {
pin_states: RefCell<Vec<Result<bool, Error>>>,
}
impl ErrorType for ArbitraryInputPin {
type Error = Error;
}
impl InputPin for ArbitraryInputPin {
fn is_high(&mut self) -> Result<bool, Self::Error> {
match self.pin_states.try_borrow_mut() {
Ok(mut pin_states) => match pin_states.pop() {
Some(result) => result,
None => Err(Error),
},
Err(_) => Err(Error),
}
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
self.is_high().map(|x| !x)
}
}
#[derive(Debug, Arbitrary)]
pub struct ArbitraryOutputPin {
maybe_error: RefCell<Vec<Option<Error>>>,
#[arbitrary(with = |u: &mut Unstructured| Ok(if bool::arbitrary(u)? {PinState::High} else {PinState::Low}))]
state: PinState,
}
impl OutputPin for ArbitraryOutputPin {
fn set_low(&mut self) -> Result<(), Self::Error> {
match self.maybe_error.try_borrow_mut().map_err(|_| Error)?.pop() {
Some(Some(error)) => Err(error),
_ => {
self.state = PinState::Low;
Ok(())
}
}
}
fn set_high(&mut self) -> Result<(), Self::Error> {
match self.maybe_error.try_borrow_mut().map_err(|_| Error)?.pop() {
Some(Some(error)) => Err(error),
_ => {
self.state = PinState::High;
Ok(())
}
}
}
}
impl StatefulOutputPin for ArbitraryOutputPin {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
match self.maybe_error.try_borrow_mut().map_err(|_| Error)?.pop() {
Some(Some(error)) => Err(error),
_ => Ok(self.state == PinState::High),
}
}
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
match self.maybe_error.try_borrow_mut().map_err(|_| Error)?.pop() {
Some(Some(error)) => Err(error),
_ => Ok(self.state == PinState::Low),
}
}
}
impl ErrorType for ArbitraryOutputPin {
type Error = Error;
}