autd3-rs 0.6.1

Core async client library for the AUTD3 phased-array kit.
Documentation
use std::rc::Rc;

use crate::commands::operation::{Distribution, Nop, Operation};
use crate::error::Error;
use crate::geometry::Device;
use crate::mirror::FirmwareState;
use crate::protocol::{Cmd, PAYLOAD_BYTES};

pub(crate) type EachOps<'a> = Vec<Vec<Box<dyn Operation + 'a>>>;

pub(crate) fn each_frames(devices: &[Vec<Box<dyn Operation + '_>>]) -> usize {
    devices.iter().map(Vec::len).max().unwrap_or(0)
}

pub(crate) fn each_encode(
    devices: &[Vec<Box<dyn Operation + '_>>],
    device: &Device,
    frame: usize,
    out: &mut [u8; PAYLOAD_BYTES],
) -> Result<Cmd, Error> {
    match devices.get(device.idx()).and_then(|ops| ops.get(frame)) {
        Some(op) => op.encode(device, out),
        None => Nop.encode(device, out),
    }
}

pub(crate) fn each_reflect(
    devices: &[Vec<Box<dyn Operation + '_>>],
    device: usize,
    state: &mut FirmwareState,
) -> Result<(), Error> {
    if let Some(ops) = devices.get(device) {
        for op in ops {
            op.reflect(device, state)?;
        }
    }
    Ok(())
}

pub(crate) struct EachFrame<'a> {
    devices: Rc<EachOps<'a>>,
    frame: usize,
}

impl<'a> EachFrame<'a> {
    pub(crate) fn flatten(devices: EachOps<'a>) -> impl Iterator<Item = Self> {
        let frames = each_frames(&devices);
        let devices = Rc::new(devices);
        (0..frames).map(move |frame| Self {
            devices: Rc::clone(&devices),
            frame,
        })
    }
}

impl crate::sealed::Sealed for EachFrame<'_> {}

impl Operation for EachFrame<'_> {
    fn distribution(&self) -> Distribution {
        Distribution::PerDevice
    }

    fn encode(&self, device: &Device, out: &mut [u8; PAYLOAD_BYTES]) -> Result<Cmd, Error> {
        each_encode(&self.devices, device, self.frame, out)
    }

    fn reflect(&self, device: usize, state: &mut FirmwareState) -> Result<(), Error> {
        match self.devices.get(device).and_then(|ops| ops.get(self.frame)) {
            Some(op) => op.reflect(device, state),
            None => Ok(()),
        }
    }
}