hadusos 0.2.1

Half-duplex session over serial.
Documentation
use super::*;
use core::time::Duration;
use crossbeam::channel::{self, Receiver, RecvError, SendError, Sender};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Instant;

struct MockSerial {
    send: Sender<u8>,
    recv: Receiver<u8>,
}

impl MockSerial {
    const fn new(send: Sender<u8>, recv: Receiver<u8>) -> Self {
        Self { send, recv }
    }
}

impl Serial for MockSerial {
    type ReadError = RecvError;
    type WriteError = SendError<u8>;

    fn read_byte_with_timeout(
        &mut self,
        timeout_ms: u32,
    ) -> Result<u8, SerialError<Self::ReadError, Self::WriteError>> {
        self.recv
            .recv_timeout(Duration::from_millis(timeout_ms as u64))
            .map_err(|e| match e {
                channel::RecvTimeoutError::Timeout => SerialError::Timeout,
                channel::RecvTimeoutError::Disconnected => SerialError::ReadError(RecvError),
            })
    }

    fn write_byte(
        &mut self,
        byte: u8,
    ) -> Result<(), SerialError<Self::ReadError, Self::WriteError>> {
        self.send.send(byte).map_err(|e| SerialError::WriteError(e))
    }
}

struct MockTimer {
    start: Instant,
}

impl MockTimer {
    fn new() -> Self {
        Self {
            start: Instant::now(),
        }
    }
}

impl Timer for MockTimer {
    fn get_timestamp_ms(&mut self) -> u32 {
        self.start.elapsed().as_millis() as u32
    }
}

#[test]
fn send_receive_test() {
    let (send0, recv1) = channel::unbounded();
    let (send1, recv0) = channel::unbounded();

    let serial0 = MockSerial::new(send0, recv0);
    let serial1 = MockSerial::new(send1, recv1);

    let timer0 = MockTimer::new();
    let timer1 = MockTimer::new();

    let trans0 = Arc::new(Mutex::new(Session::new(serial0, timer0)));
    let trans1 = Arc::new(Mutex::new(Session::new(serial1, timer1)));

    let _trans0_cloned = Arc::clone(&trans0);
    let _trans1_cloned = Arc::clone(&trans1);

    fn client(trans: &mut Session<MockSerial, MockTimer>) {
        let msg = "hello_world!".as_bytes();
        let mut large_msg = Vec::new();
        for _ in 0..1000 {
            large_msg.extend_from_slice(msg);
        }
        trans.send(&large_msg, 1000).unwrap();
    }

    fn server(trans: &mut Session<MockSerial, MockTimer>) {
        let msg = "hello_world!".as_bytes();
        let mut large_msg = Vec::new();
        for _ in 0..1000 {
            large_msg.extend_from_slice(msg);
        }

        let len = trans.listen(1000).unwrap();
        let mut buf = vec![0u8; len as usize].into_boxed_slice();
        trans.receive(&mut buf, 10000).unwrap();

        assert!(buf.as_ref() == large_msg.as_slice())
    }

    let t0 = thread::spawn(move || client(&mut *trans0.lock().unwrap()));
    let t1 = thread::spawn(move || server(&mut *trans1.lock().unwrap()));

    t0.join().unwrap();
    t1.join().unwrap();
}