embedded_hal_fuzz/
digital.rs

1//! To make use of this module you can simply pass
2//! this in as a value from the fuzz_target macro e.g.
3//! ```rust
4//! use libfuzzer_sys::fuzz_target;
5//! use embedded_hal_fuzz::digital::{ArbitraryInputPin, ArbitraryOutputPin};
6//! use embedded_hal::digital::{InputPin, OutputPin};
7//! use arbitrary::Arbitrary;
8//! #[derive(Debug, Arbitrary)]
9//! struct Ctx {
10//!   input_pin : ArbitraryInputPin,
11//!   output_pin : ArbitraryOutputPin,
12//! }
13//! fuzz_target!(|ctx: Ctx| {
14//!   let Ctx {input_pin, mut output_pin } = ctx;
15//!   let _ = output_pin.set_high();
16//! });
17//! ```
18use std::cell::RefCell;
19
20use arbitrary::{Arbitrary, Unstructured};
21use embedded_hal::digital::{
22    self, ErrorKind, ErrorType, InputPin, OutputPin, PinState, StatefulOutputPin,
23};
24
25#[derive(Debug, Arbitrary)]
26pub struct Error;
27
28impl digital::Error for Error {
29    fn kind(&self) -> ErrorKind {
30        ErrorKind::Other
31    }
32}
33
34/// Creates a fuzzed input pin driver, this type is intended to be constructed
35/// the arbitrary crate e.g.
36/// ```rust
37/// use arbitrary::{Arbitrary, Unstructured};
38/// use embedded_hal_fuzz::digital::ArbitraryInputPin;
39/// let raw_fuzzed_data = &[1u8, 2, 3, 4, 5][..];
40/// let mut u = Unstructured::new(raw_fuzzed_data);
41/// let arbitrary_input_pin = ArbitraryInputPin::arbitrary(&mut u);
42/// ```
43#[derive(Debug, Arbitrary)]
44pub struct ArbitraryInputPin {
45    pin_states: RefCell<Vec<Result<bool, Error>>>,
46}
47
48impl ErrorType for ArbitraryInputPin {
49    type Error = Error;
50}
51
52impl InputPin for ArbitraryInputPin {
53    fn is_high(&mut self) -> Result<bool, Self::Error> {
54        match self.pin_states.try_borrow_mut() {
55            Ok(mut pin_states) => match pin_states.pop() {
56                Some(result) => result,
57                None => Err(Error),
58            },
59            Err(_) => Err(Error),
60        }
61    }
62    fn is_low(&mut self) -> Result<bool, Self::Error> {
63        self.is_high().map(|x| !x)
64    }
65}
66
67/// Creates a fuzzed output pin driver, this type is intended to be constructed
68/// the arbitrary crate e.g.
69/// ```rust
70/// use arbitrary::{Arbitrary, Unstructured};
71/// use embedded_hal_fuzz::digital::ArbitraryOutputPin;
72/// let raw_fuzzed_data = &[1u8, 2, 3, 4, 5][..];
73/// let mut u = Unstructured::new(raw_fuzzed_data);
74/// let arbitrary_output_pin = ArbitraryOutputPin::arbitrary(&mut u);
75/// ```
76#[derive(Debug, Arbitrary)]
77pub struct ArbitraryOutputPin {
78    maybe_error: RefCell<Vec<Option<Error>>>,
79    #[arbitrary(with = |u: &mut Unstructured| Ok(if bool::arbitrary(u)? {PinState::High} else {PinState::Low}))]
80    state: PinState,
81}
82
83impl OutputPin for ArbitraryOutputPin {
84    fn set_low(&mut self) -> Result<(), Self::Error> {
85        match self.maybe_error.try_borrow_mut().map_err(|_| Error)?.pop() {
86            Some(Some(error)) => Err(error),
87            _ => {
88                self.state = PinState::Low;
89                Ok(())
90            }
91        }
92    }
93    fn set_high(&mut self) -> Result<(), Self::Error> {
94        match self.maybe_error.try_borrow_mut().map_err(|_| Error)?.pop() {
95            Some(Some(error)) => Err(error),
96            _ => {
97                self.state = PinState::High;
98                Ok(())
99            }
100        }
101    }
102}
103
104impl StatefulOutputPin for ArbitraryOutputPin {
105    fn is_set_high(&mut self) -> Result<bool, Self::Error> {
106        match self.maybe_error.try_borrow_mut().map_err(|_| Error)?.pop() {
107            Some(Some(error)) => Err(error),
108            _ => Ok(self.state == PinState::High),
109        }
110    }
111
112    fn is_set_low(&mut self) -> Result<bool, Self::Error> {
113        match self.maybe_error.try_borrow_mut().map_err(|_| Error)?.pop() {
114            Some(Some(error)) => Err(error),
115            _ => Ok(self.state == PinState::Low),
116        }
117    }
118}
119
120impl ErrorType for ArbitraryOutputPin {
121    type Error = Error;
122}