use super::Backend;
use crate::std::{
convert::Infallible,
sync::atomic::{AtomicU32, Ordering},
};
#[derive(Debug)]
pub struct MockBackend<'a> {
responses: &'a [(&'a [u8], &'a [u8])],
step: AtomicU32,
}
impl<'a> MockBackend<'a> {
pub fn new(responses: &'a [(&'a [u8], &'a [u8])]) -> Self {
Self {
responses,
step: 0.into(),
}
}
}
impl<'a> Backend for MockBackend<'a> {
type Error = Infallible;
async fn exchange_raw(&self, output: &mut [u8], input: &[u8]) -> Result<usize, Self::Error> {
let (expected_input, response) = {
let n = self.step.fetch_add(1, Ordering::SeqCst) as usize;
let responses = &self.responses[n..];
responses[0]
};
assert_eq!(expected_input, input);
let n = response.len();
output[..n].copy_from_slice(response);
Ok(n)
}
}
#[allow(unused_macros)]
macro_rules! mock_backend {
( $( ( $request:expr, $response:expr ) ),* ) => {
$crate::io::MockBackend::new(&[
$(
(&hex_literal::hex!($request), &hex_literal::hex!($response))
),*
])
};
}
pub(crate) use mock_backend;
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_mock_backend() {
let mb = MockBackend::new(&[(&[0xAF], b"\x00Hello, World!")]);
let mut out = [0; 0xff];
let n = mb.exchange_raw(&mut out, &[0xAF]).await.unwrap();
assert_eq!(b"Hello, World!", &out[1..n]);
}
}