use std::{marker::PhantomData, time::Duration};
use autd3_driver::Operation;
use crate::{error::AUTDInternalError, geometry::*};
pub trait Datagram<T: Transducer> {
type H: Operation;
type B: Operation;
fn operation(
&mut self,
geometry: &Geometry<T>,
) -> Result<(Self::H, Self::B), AUTDInternalError>;
fn timeout(&self) -> Option<Duration> {
None
}
}
pub struct DatagramWithTimeout<T: Transducer, D: Datagram<T>> {
datagram: D,
timeout: Duration,
phantom: std::marker::PhantomData<T>,
}
impl<T: Transducer, D: Datagram<T>> Datagram<T> for DatagramWithTimeout<T, D> {
type H = D::H;
type B = D::B;
fn operation(
&mut self,
geometry: &Geometry<T>,
) -> Result<(Self::H, Self::B), AUTDInternalError> {
self.datagram.operation(geometry)
}
fn timeout(&self) -> Option<Duration> {
Some(self.timeout)
}
}
pub trait DatagramT<T: Transducer, D: Datagram<T>> {
fn with_timeout(self, timeout: Duration) -> DatagramWithTimeout<T, D>;
}
impl<T: Transducer, D: Datagram<T>> DatagramT<T, D> for D {
fn with_timeout(self, timeout: Duration) -> DatagramWithTimeout<T, D> {
DatagramWithTimeout {
datagram: self,
timeout,
phantom: PhantomData,
}
}
}
impl<T: Transducer, B> Datagram<T> for Box<B>
where
B: Datagram<T>,
{
type H = B::H;
type B = B::B;
fn operation(
&mut self,
geometry: &Geometry<T>,
) -> Result<(Self::H, Self::B), AUTDInternalError> {
B::operation(self, geometry)
}
fn timeout(&self) -> Option<Duration> {
B::timeout(self)
}
}
impl<T: Transducer, B> Datagram<T> for &mut B
where
B: Datagram<T>,
{
type H = B::H;
type B = B::B;
fn operation(
&mut self,
geometry: &Geometry<T>,
) -> Result<(Self::H, Self::B), AUTDInternalError> {
B::operation(self, geometry)
}
fn timeout(&self) -> Option<Duration> {
B::timeout(self)
}
}
impl<T: Transducer, H, B> Datagram<T> for (H, B)
where
H: Datagram<T, B = autd3_driver::NullBody>,
B: Datagram<T, H = autd3_driver::NullHeader>,
{
type H = H::H;
type B = B::B;
fn operation(
&mut self,
geometry: &Geometry<T>,
) -> Result<(Self::H, Self::B), AUTDInternalError> {
let (h, _) = self.0.operation(geometry)?;
let (_, b) = self.1.operation(geometry)?;
Ok((h, b))
}
}
#[derive(Default)]
pub struct NullHeader {}
impl NullHeader {
pub fn new() -> Self {
Self {}
}
}
impl<T: Transducer> Datagram<T> for NullHeader {
type H = autd3_driver::NullHeader;
type B = autd3_driver::NullBody;
fn operation(&mut self, _: &Geometry<T>) -> Result<(Self::H, Self::B), AUTDInternalError> {
Ok((Self::H::default(), Self::B::default()))
}
}
#[derive(Default)]
pub struct NullBody {}
impl NullBody {
pub fn new() -> Self {
Self {}
}
}
impl<T: Transducer> Datagram<T> for NullBody {
type H = autd3_driver::NullHeader;
type B = autd3_driver::NullBody;
fn operation(&mut self, _: &Geometry<T>) -> Result<(Self::H, Self::B), AUTDInternalError> {
Ok((Self::H::default(), Self::B::default()))
}
}