use core::marker::PhantomData;
use crate::FieldSet;
pub trait CommandInterface {
type Error;
type AddressType: Copy;
fn dispatch_command(
&mut self,
address: Self::AddressType,
size_bits_in: u32,
input: &[u8],
size_bits_out: u32,
output: &mut [u8],
) -> Result<(), Self::Error>;
}
pub trait AsyncCommandInterface {
type Error;
type AddressType: Copy;
async fn dispatch_command(
&mut self,
address: Self::AddressType,
size_bits_in: u32,
input: &[u8],
size_bits_out: u32,
output: &mut [u8],
) -> Result<(), Self::Error>;
}
pub struct CommandOperation<'i, Interface, AddressType: Copy, InFieldSet, OutFieldSet> {
interface: &'i mut Interface,
address: AddressType,
_phantom: PhantomData<(InFieldSet, OutFieldSet)>,
}
impl<'i, Interface, AddressType: Copy, InFieldSet, OutFieldSet>
CommandOperation<'i, Interface, AddressType, InFieldSet, OutFieldSet>
{
#[doc(hidden)]
pub fn new(interface: &'i mut Interface, address: AddressType) -> Self {
Self {
interface,
address,
_phantom: PhantomData,
}
}
}
impl<Interface, AddressType: Copy> CommandOperation<'_, Interface, AddressType, (), ()>
where
Interface: CommandInterface<AddressType = AddressType>,
{
pub fn dispatch(self) -> Result<(), Interface::Error> {
self.interface
.dispatch_command(self.address, 0, &[], 0, &mut [])
}
}
impl<Interface, AddressType: Copy, InFieldSet: FieldSet>
CommandOperation<'_, Interface, AddressType, InFieldSet, ()>
where
Interface: CommandInterface<AddressType = AddressType>,
{
pub fn dispatch(self, f: impl FnOnce(&mut InFieldSet)) -> Result<(), Interface::Error> {
let mut in_fields = InFieldSet::new_with_zero();
f(&mut in_fields);
self.interface.dispatch_command(
self.address,
InFieldSet::SIZE_BITS,
InFieldSet::BUFFER::from(in_fields).as_ref(),
0,
&mut [],
)
}
}
impl<Interface, AddressType: Copy, OutFieldSet: FieldSet>
CommandOperation<'_, Interface, AddressType, (), OutFieldSet>
where
Interface: CommandInterface<AddressType = AddressType>,
{
pub fn dispatch(self) -> Result<OutFieldSet, Interface::Error> {
let mut buffer = OutFieldSet::BUFFER::from(OutFieldSet::new_with_zero());
self.interface.dispatch_command(
self.address,
0,
&[],
OutFieldSet::SIZE_BITS,
buffer.as_mut(),
)?;
Ok(buffer.into())
}
}
impl<Interface, AddressType: Copy, InFieldSet: FieldSet, OutFieldSet: FieldSet>
CommandOperation<'_, Interface, AddressType, InFieldSet, OutFieldSet>
where
Interface: CommandInterface<AddressType = AddressType>,
{
pub fn dispatch(
self,
f: impl FnOnce(&mut InFieldSet),
) -> Result<OutFieldSet, Interface::Error> {
let mut in_fields = InFieldSet::new_with_zero();
f(&mut in_fields);
let mut buffer = OutFieldSet::BUFFER::from(OutFieldSet::new_with_zero());
self.interface.dispatch_command(
self.address,
InFieldSet::SIZE_BITS,
InFieldSet::BUFFER::from(in_fields).as_ref(),
OutFieldSet::SIZE_BITS,
buffer.as_mut(),
)?;
Ok(buffer.into())
}
}
impl<'i, Interface, AddressType: Copy> CommandOperation<'i, Interface, AddressType, (), ()>
where
Interface: AsyncCommandInterface<AddressType = AddressType>,
{
pub async fn dispatch_async(self) -> Result<(), Interface::Error> {
self.interface
.dispatch_command(self.address, 0, &[], 0, &mut [])
.await
}
}
impl<'i, Interface, AddressType: Copy, InFieldSet: FieldSet>
CommandOperation<'i, Interface, AddressType, InFieldSet, ()>
where
Interface: AsyncCommandInterface<AddressType = AddressType>,
{
pub async fn dispatch_async(
self,
f: impl FnOnce(&mut InFieldSet),
) -> Result<(), Interface::Error> {
let mut in_fields = InFieldSet::new_with_zero();
f(&mut in_fields);
self.interface
.dispatch_command(
self.address,
InFieldSet::SIZE_BITS,
InFieldSet::BUFFER::from(in_fields).as_ref(),
0,
&mut [],
)
.await
}
}
impl<'i, Interface, AddressType: Copy, OutFieldSet: FieldSet>
CommandOperation<'i, Interface, AddressType, (), OutFieldSet>
where
Interface: AsyncCommandInterface<AddressType = AddressType>,
{
pub async fn dispatch_async(self) -> Result<OutFieldSet, Interface::Error> {
let mut buffer = OutFieldSet::BUFFER::from(OutFieldSet::new_with_zero());
self.interface
.dispatch_command(
self.address,
0,
&[],
OutFieldSet::SIZE_BITS,
buffer.as_mut(),
)
.await?;
Ok(buffer.into())
}
}
impl<'i, Interface, AddressType: Copy, InFieldSet: FieldSet, OutFieldSet: FieldSet>
CommandOperation<'i, Interface, AddressType, InFieldSet, OutFieldSet>
where
Interface: AsyncCommandInterface<AddressType = AddressType>,
{
pub async fn dispatch_async(
self,
f: impl FnOnce(&mut InFieldSet),
) -> Result<OutFieldSet, Interface::Error> {
let mut in_fields = InFieldSet::new_with_zero();
f(&mut in_fields);
let mut buffer = OutFieldSet::BUFFER::from(OutFieldSet::new_with_zero());
self.interface
.dispatch_command(
self.address,
InFieldSet::SIZE_BITS,
InFieldSet::BUFFER::from(in_fields).as_ref(),
OutFieldSet::SIZE_BITS,
buffer.as_mut(),
)
.await?;
Ok(buffer.into())
}
}