embedded-update 0.12.0

Firmware updates for embedded devices supporting multiple update services
#![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait))]
#![cfg_attr(feature = "nightly", allow(incomplete_features))]

use {
    embedded_update::{device, service, FirmwareUpdater},
    tokio::sync::mpsc,
};

#[tokio::test]
async fn test_serial_chain() {
    let mut t1 = Timer;
    let mut t2 = Timer;
    let (src, dest) = Link::new();
    let firmware = service::InMemory::new(b"2", &[1; 1024]);
    let mut updater_1 = FirmwareUpdater::new(firmware, Default::default());

    let mut serial_device = device::Serial::new(src);

    let u1_fut = updater_1.run(&mut serial_device, &mut t1);

    let serial_service = service::Serial::new(dest);

    let mut updater_2 = FirmwareUpdater::new(serial_service, Default::default());
    let mut device = device::Simulator::new(b"1");

    let u2_fut = updater_2.run(&mut device, &mut t2);

    let (r1, r2) = tokio::join!(u1_fut, u2_fut);
    assert!(r1.is_ok());
    assert!(r2.is_ok());
    assert_eq!(device.version(), b"2");
}

type Frame = [u8; 1024];

struct Link {
    tx: mpsc::Sender<Frame>,
    rx: mpsc::Receiver<Frame>,
}

impl Link {
    pub fn new() -> (Link, Link) {
        let (src_tx, src_rx) = mpsc::channel(4);
        let (dest_tx, dest_rx) = mpsc::channel(4);
        let src = Link {
            tx: src_tx,
            rx: dest_rx,
        };

        let dest = Link {
            tx: dest_tx,
            rx: src_rx,
        };
        (src, dest)
    }
}

impl embedded_io::ErrorType for Link {
    type Error = std::io::Error;
}

impl embedded_io_async::Read for Link {
    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        if let Some(m) = self.rx.recv().await {
            let to_copy = core::cmp::min(m.len(), buf.len());
            buf[..to_copy].copy_from_slice(&m[..to_copy]);
            Ok(to_copy)
        } else {
            Ok(0)
        }
    }
}

impl embedded_io_async::Write for Link {
    async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
        for chunk in buf.chunks(1024) {
            let mut b = [0; 1024];
            b[..chunk.len()].copy_from_slice(chunk);
            self.tx.send(b).await.unwrap();
        }
        Ok(buf.len())
    }

    async fn flush(&mut self) -> Result<(), Self::Error> {
        todo!()
    }
}

pub struct Timer;

impl embedded_hal_async::delay::DelayUs for Timer {
    async fn delay_us(&mut self, i: u32) {
        tokio::time::sleep(tokio::time::Duration::from_micros(i as u64)).await;
    }

    async fn delay_ms(&mut self, i: u32) {
        tokio::time::sleep(tokio::time::Duration::from_millis(i as u64)).await;
    }
}