use core::marker::PhantomData;
use crate::{Address, Block, Fieldset, FieldsetMetadata, NotFieldset, NotRepeating, Repeating};
pub trait CommandInterfaceBase {
type Error;
type AddressType: Address;
}
impl<T: CommandInterfaceBase> CommandInterfaceBase for &mut T {
type Error = T::Error;
type AddressType = T::AddressType;
}
#[diagnostic::on_unimplemented(
label = "cannot use blocking command operations when the device interface doesn't know how to dispatch commands",
note = "to enable command operations, implement the trait on this type"
)]
pub trait CommandInterface: CommandInterfaceBase {
fn dispatch_command(
&mut self,
address: Self::AddressType,
input: &mut [u8],
_input_metadata: &FieldsetMetadata,
output: &mut [u8],
_output_metadata: &FieldsetMetadata,
) -> Result<(), Self::Error>;
}
#[diagnostic::do_not_recommend]
impl<T: CommandInterface> CommandInterface for &mut T {
fn dispatch_command(
&mut self,
address: Self::AddressType,
input: &mut [u8],
input_metadata: &FieldsetMetadata,
output: &mut [u8],
output_metadata: &FieldsetMetadata,
) -> Result<(), Self::Error> {
(*self).dispatch_command(address, input, input_metadata, output, output_metadata)
}
}
#[diagnostic::on_unimplemented(
label = "cannot use async command operations when the device interface doesn't know how to dispatch commands",
note = "to enable command operations, implement the trait on this type"
)]
pub trait AsyncCommandInterface: CommandInterfaceBase {
async fn dispatch_command(
&mut self,
address: Self::AddressType,
input: &mut [u8],
_input_metadata: &FieldsetMetadata,
output: &mut [u8],
_output_metadata: &FieldsetMetadata,
) -> Result<(), Self::Error>;
}
#[diagnostic::do_not_recommend]
impl<T: AsyncCommandInterface> AsyncCommandInterface for &mut T {
fn dispatch_command(
&mut self,
address: Self::AddressType,
input: &mut [u8],
input_metadata: &FieldsetMetadata,
output: &mut [u8],
output_metadata: &FieldsetMetadata,
) -> impl Future<Output = Result<(), Self::Error>> {
(*self).dispatch_command(address, input, input_metadata, output, output_metadata)
}
}
pub struct CommandOperation<'b, B, AddressType, InFieldset, OutFieldset, Repeat>
where
B: Block,
B::Interface: CommandInterfaceBase<AddressType = AddressType>,
AddressType: Address,
{
block: &'b mut B,
address: AddressType,
_phantom: PhantomData<(InFieldset, OutFieldset, Repeat)>,
}
impl<'d, B, AddressType, InFieldset, OutFieldset, Repeat>
CommandOperation<'d, B, AddressType, InFieldset, OutFieldset, Repeat>
where
B: Block,
B::Interface: CommandInterfaceBase<AddressType = AddressType>,
AddressType: Address,
{
#[doc(hidden)]
pub fn new(block: &'d mut B, address: AddressType) -> Self {
Self {
block,
address,
_phantom: PhantomData,
}
}
pub fn dispatch(self) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: CommandInterface,
InFieldset: NotFieldset,
OutFieldset: NotFieldset,
Repeat: NotRepeating,
{
self.block.interface().dispatch_command(
self.address,
&mut [],
&FieldsetMetadata::DEFAULT,
&mut [],
&FieldsetMetadata::DEFAULT,
)
}
#[track_caller]
pub fn dispatch_at(
self,
index: Repeat::Index,
) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: CommandInterface,
InFieldset: NotFieldset,
OutFieldset: NotFieldset,
Repeat: Repeating,
{
self.block.interface().dispatch_command(
Repeat::calc_address(self.address, index),
&mut [],
&FieldsetMetadata::DEFAULT,
&mut [],
&FieldsetMetadata::DEFAULT,
)
}
pub fn dispatch_async(
self,
) -> impl Future<Output = Result<(), <B::Interface as CommandInterfaceBase>::Error>>
where
B::Interface: AsyncCommandInterface,
InFieldset: NotFieldset,
OutFieldset: NotFieldset,
Repeat: NotRepeating,
{
self.block.interface().dispatch_command(
self.address,
&mut [],
&FieldsetMetadata::DEFAULT,
&mut [],
&FieldsetMetadata::DEFAULT,
)
}
pub fn dispatch_at_async(
self,
index: Repeat::Index,
) -> impl Future<Output = Result<(), <B::Interface as CommandInterfaceBase>::Error>>
where
B::Interface: AsyncCommandInterface,
InFieldset: NotFieldset,
OutFieldset: NotFieldset,
Repeat: Repeating,
{
self.block.interface().dispatch_command(
Repeat::calc_address(self.address, index),
&mut [],
&FieldsetMetadata::DEFAULT,
&mut [],
&FieldsetMetadata::DEFAULT,
)
}
pub fn dispatch_in(
self,
f: impl FnOnce(&mut InFieldset),
) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: CommandInterface,
InFieldset: Fieldset,
OutFieldset: NotFieldset,
Repeat: NotRepeating,
{
let mut in_fields = InFieldset::ZERO;
f(&mut in_fields);
self.block.interface().dispatch_command(
self.address,
in_fields.as_slice_mut(),
&InFieldset::METADATA,
&mut [],
&FieldsetMetadata::DEFAULT,
)
}
#[track_caller]
pub fn dispatch_in_at(
self,
index: Repeat::Index,
f: impl FnOnce(&mut InFieldset),
) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: CommandInterface,
InFieldset: Fieldset,
OutFieldset: NotFieldset,
Repeat: Repeating,
{
let mut in_fields = InFieldset::ZERO;
f(&mut in_fields);
self.block.interface().dispatch_command(
Repeat::calc_address(self.address, index),
in_fields.as_slice_mut(),
&InFieldset::METADATA,
&mut [],
&FieldsetMetadata::DEFAULT,
)
}
pub async fn dispatch_in_async(
self,
f: impl FnOnce(&mut InFieldset),
) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: AsyncCommandInterface,
InFieldset: Fieldset,
OutFieldset: NotFieldset,
Repeat: NotRepeating,
{
let mut in_fields = InFieldset::ZERO;
f(&mut in_fields);
self.block
.interface()
.dispatch_command(
self.address,
in_fields.as_slice_mut(),
&InFieldset::METADATA,
&mut [],
&FieldsetMetadata::DEFAULT,
)
.await
}
pub async fn dispatch_in_at_async(
self,
index: Repeat::Index,
f: impl FnOnce(&mut InFieldset),
) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: AsyncCommandInterface,
InFieldset: Fieldset,
OutFieldset: NotFieldset,
Repeat: Repeating,
{
let mut in_fields = InFieldset::ZERO;
f(&mut in_fields);
self.block
.interface()
.dispatch_command(
Repeat::calc_address(self.address, index),
in_fields.as_slice_mut(),
&InFieldset::METADATA,
&mut [],
&FieldsetMetadata::DEFAULT,
)
.await
}
pub fn dispatch_out(self) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: CommandInterface,
InFieldset: NotFieldset,
OutFieldset: Fieldset,
Repeat: NotRepeating,
{
let mut out_fields = OutFieldset::ZERO;
self.block.interface().dispatch_command(
self.address,
&mut [],
&FieldsetMetadata::DEFAULT,
out_fields.as_slice_mut(),
&OutFieldset::METADATA,
)?;
Ok(out_fields)
}
#[track_caller]
pub fn dispatch_out_at(
self,
index: Repeat::Index,
) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: CommandInterface,
InFieldset: NotFieldset,
OutFieldset: Fieldset,
Repeat: Repeating,
{
let mut out_fields = OutFieldset::ZERO;
self.block.interface().dispatch_command(
Repeat::calc_address(self.address, index),
&mut [],
&FieldsetMetadata::DEFAULT,
out_fields.as_slice_mut(),
&OutFieldset::METADATA,
)?;
Ok(out_fields)
}
pub async fn dispatch_out_async(
self,
) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: AsyncCommandInterface,
InFieldset: NotFieldset,
OutFieldset: Fieldset,
Repeat: NotRepeating,
{
let mut out_fields = OutFieldset::ZERO;
self.block
.interface()
.dispatch_command(
self.address,
&mut [],
&FieldsetMetadata::DEFAULT,
out_fields.as_slice_mut(),
&OutFieldset::METADATA,
)
.await?;
Ok(out_fields)
}
pub async fn dispatch_out_at_async(
self,
index: Repeat::Index,
) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: AsyncCommandInterface,
InFieldset: NotFieldset,
OutFieldset: Fieldset,
Repeat: Repeating,
{
let mut out_fields = OutFieldset::ZERO;
self.block
.interface()
.dispatch_command(
Repeat::calc_address(self.address, index),
&mut [],
&FieldsetMetadata::DEFAULT,
out_fields.as_slice_mut(),
&OutFieldset::METADATA,
)
.await?;
Ok(out_fields)
}
pub fn dispatch_inout(
self,
f: impl FnOnce(&mut InFieldset),
) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: CommandInterface,
InFieldset: Fieldset,
OutFieldset: Fieldset,
Repeat: NotRepeating,
{
let mut in_fields = InFieldset::ZERO;
f(&mut in_fields);
let mut out_fields = OutFieldset::ZERO;
self.block.interface().dispatch_command(
self.address,
in_fields.as_slice_mut(),
&InFieldset::METADATA,
out_fields.as_slice_mut(),
&OutFieldset::METADATA,
)?;
Ok(out_fields)
}
#[track_caller]
pub fn dispatch_inout_at(
self,
index: Repeat::Index,
f: impl FnOnce(&mut InFieldset),
) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: CommandInterface,
InFieldset: Fieldset,
OutFieldset: Fieldset,
Repeat: Repeating,
{
let mut in_fields = InFieldset::ZERO;
f(&mut in_fields);
let mut out_fields = OutFieldset::ZERO;
self.block.interface().dispatch_command(
Repeat::calc_address(self.address, index),
in_fields.as_slice_mut(),
&InFieldset::METADATA,
out_fields.as_slice_mut(),
&OutFieldset::METADATA,
)?;
Ok(out_fields)
}
pub async fn dispatch_inout_async(
self,
f: impl FnOnce(&mut InFieldset),
) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: AsyncCommandInterface,
InFieldset: Fieldset,
OutFieldset: Fieldset,
Repeat: NotRepeating,
{
let mut in_fields = InFieldset::ZERO;
f(&mut in_fields);
let mut out_fields = OutFieldset::ZERO;
self.block
.interface()
.dispatch_command(
self.address,
in_fields.as_slice_mut(),
&InFieldset::METADATA,
out_fields.as_slice_mut(),
&OutFieldset::METADATA,
)
.await?;
Ok(out_fields)
}
pub async fn dispatch_inout_at_async(
self,
index: Repeat::Index,
f: impl FnOnce(&mut InFieldset),
) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
where
B::Interface: AsyncCommandInterface,
InFieldset: Fieldset,
OutFieldset: Fieldset,
Repeat: Repeating,
{
let mut in_fields = InFieldset::ZERO;
f(&mut in_fields);
let mut out_fields = OutFieldset::ZERO;
self.block
.interface()
.dispatch_command(
Repeat::calc_address(self.address, index),
in_fields.as_slice_mut(),
&InFieldset::METADATA,
out_fields.as_slice_mut(),
&OutFieldset::METADATA,
)
.await?;
Ok(out_fields)
}
}