1use core::marker::PhantomData;
2
3use crate::{Address, Block, Fieldset, FieldsetMetadata, NotFieldset, NotRepeating, Repeating};
4
5pub trait CommandInterfaceBase {
7 type Error;
9 type AddressType: Address;
11}
12
13impl<T: CommandInterfaceBase> CommandInterfaceBase for &mut T {
14 type Error = T::Error;
15 type AddressType = T::AddressType;
16}
17
18#[diagnostic::on_unimplemented(
19 label = "cannot use blocking command operations when the device interface doesn't know how to dispatch commands",
20 note = "to enable command operations, implement the trait on this type"
21)]
22pub trait CommandInterface: CommandInterfaceBase {
26 fn dispatch_command(
33 &mut self,
34 address: Self::AddressType,
35 input: &mut [u8],
36 _input_metadata: &FieldsetMetadata,
37 output: &mut [u8],
38 _output_metadata: &FieldsetMetadata,
39 ) -> Result<(), Self::Error>;
40}
41
42#[diagnostic::do_not_recommend]
43impl<T: CommandInterface> CommandInterface for &mut T {
44 fn dispatch_command(
45 &mut self,
46 address: Self::AddressType,
47 input: &mut [u8],
48 input_metadata: &FieldsetMetadata,
49 output: &mut [u8],
50 output_metadata: &FieldsetMetadata,
51 ) -> Result<(), Self::Error> {
52 (*self).dispatch_command(address, input, input_metadata, output, output_metadata)
53 }
54}
55
56#[diagnostic::on_unimplemented(
57 label = "cannot use async command operations when the device interface doesn't know how to dispatch commands",
58 note = "to enable command operations, implement the trait on this type"
59)]
60pub trait AsyncCommandInterface: CommandInterfaceBase {
64 async fn dispatch_command(
71 &mut self,
72 address: Self::AddressType,
73 input: &mut [u8],
74 _input_metadata: &FieldsetMetadata,
75 output: &mut [u8],
76 _output_metadata: &FieldsetMetadata,
77 ) -> Result<(), Self::Error>;
78}
79
80#[diagnostic::do_not_recommend]
81impl<T: AsyncCommandInterface> AsyncCommandInterface for &mut T {
82 fn dispatch_command(
83 &mut self,
84 address: Self::AddressType,
85 input: &mut [u8],
86 input_metadata: &FieldsetMetadata,
87 output: &mut [u8],
88 output_metadata: &FieldsetMetadata,
89 ) -> impl Future<Output = Result<(), Self::Error>> {
90 (*self).dispatch_command(address, input, input_metadata, output, output_metadata)
91 }
92}
93
94pub struct CommandOperation<'b, B, AddressType, InFieldset, OutFieldset, Repeat>
96where
97 B: Block,
98 B::Interface: CommandInterfaceBase<AddressType = AddressType>,
99 AddressType: Address,
100{
101 block: &'b mut B,
102 address: AddressType,
103 _phantom: PhantomData<(InFieldset, OutFieldset, Repeat)>,
104}
105
106impl<'d, B, AddressType, InFieldset, OutFieldset, Repeat>
107 CommandOperation<'d, B, AddressType, InFieldset, OutFieldset, Repeat>
108where
109 B: Block,
110 B::Interface: CommandInterfaceBase<AddressType = AddressType>,
111 AddressType: Address,
112{
113 #[doc(hidden)]
114 pub fn new(block: &'d mut B, address: AddressType) -> Self {
115 Self {
116 block,
117 address,
118 _phantom: PhantomData,
119 }
120 }
121
122 pub fn dispatch(self) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
124 where
125 B::Interface: CommandInterface,
126 InFieldset: NotFieldset,
127 OutFieldset: NotFieldset,
128 Repeat: NotRepeating,
129 {
130 self.block.interface().dispatch_command(
131 self.address,
132 &mut [],
133 &FieldsetMetadata::DEFAULT,
134 &mut [],
135 &FieldsetMetadata::DEFAULT,
136 )
137 }
138
139 #[track_caller]
141 pub fn dispatch_at(
142 self,
143 index: Repeat::Index,
144 ) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
145 where
146 B::Interface: CommandInterface,
147 InFieldset: NotFieldset,
148 OutFieldset: NotFieldset,
149 Repeat: Repeating,
150 {
151 self.block.interface().dispatch_command(
152 Repeat::calc_address(self.address, index),
153 &mut [],
154 &FieldsetMetadata::DEFAULT,
155 &mut [],
156 &FieldsetMetadata::DEFAULT,
157 )
158 }
159
160 pub fn dispatch_async(
162 self,
163 ) -> impl Future<Output = Result<(), <B::Interface as CommandInterfaceBase>::Error>>
164 where
165 B::Interface: AsyncCommandInterface,
166 InFieldset: NotFieldset,
167 OutFieldset: NotFieldset,
168 Repeat: NotRepeating,
169 {
170 self.block.interface().dispatch_command(
171 self.address,
172 &mut [],
173 &FieldsetMetadata::DEFAULT,
174 &mut [],
175 &FieldsetMetadata::DEFAULT,
176 )
177 }
178
179 pub fn dispatch_at_async(
181 self,
182 index: Repeat::Index,
183 ) -> impl Future<Output = Result<(), <B::Interface as CommandInterfaceBase>::Error>>
184 where
185 B::Interface: AsyncCommandInterface,
186 InFieldset: NotFieldset,
187 OutFieldset: NotFieldset,
188 Repeat: Repeating,
189 {
190 self.block.interface().dispatch_command(
191 Repeat::calc_address(self.address, index),
192 &mut [],
193 &FieldsetMetadata::DEFAULT,
194 &mut [],
195 &FieldsetMetadata::DEFAULT,
196 )
197 }
198
199 pub fn dispatch_in(
201 self,
202 f: impl FnOnce(&mut InFieldset),
203 ) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
204 where
205 B::Interface: CommandInterface,
206 InFieldset: Fieldset,
207 OutFieldset: NotFieldset,
208 Repeat: NotRepeating,
209 {
210 let mut in_fields = InFieldset::ZERO;
211 f(&mut in_fields);
212
213 self.block.interface().dispatch_command(
214 self.address,
215 in_fields.as_slice_mut(),
216 &InFieldset::METADATA,
217 &mut [],
218 &FieldsetMetadata::DEFAULT,
219 )
220 }
221
222 #[track_caller]
224 pub fn dispatch_in_at(
225 self,
226 index: Repeat::Index,
227 f: impl FnOnce(&mut InFieldset),
228 ) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
229 where
230 B::Interface: CommandInterface,
231 InFieldset: Fieldset,
232 OutFieldset: NotFieldset,
233 Repeat: Repeating,
234 {
235 let mut in_fields = InFieldset::ZERO;
236 f(&mut in_fields);
237
238 self.block.interface().dispatch_command(
239 Repeat::calc_address(self.address, index),
240 in_fields.as_slice_mut(),
241 &InFieldset::METADATA,
242 &mut [],
243 &FieldsetMetadata::DEFAULT,
244 )
245 }
246
247 pub async fn dispatch_in_async(
249 self,
250 f: impl FnOnce(&mut InFieldset),
251 ) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
252 where
253 B::Interface: AsyncCommandInterface,
254 InFieldset: Fieldset,
255 OutFieldset: NotFieldset,
256 Repeat: NotRepeating,
257 {
258 let mut in_fields = InFieldset::ZERO;
259 f(&mut in_fields);
260
261 self.block
262 .interface()
263 .dispatch_command(
264 self.address,
265 in_fields.as_slice_mut(),
266 &InFieldset::METADATA,
267 &mut [],
268 &FieldsetMetadata::DEFAULT,
269 )
270 .await
271 }
272
273 pub async fn dispatch_in_at_async(
275 self,
276 index: Repeat::Index,
277 f: impl FnOnce(&mut InFieldset),
278 ) -> Result<(), <B::Interface as CommandInterfaceBase>::Error>
279 where
280 B::Interface: AsyncCommandInterface,
281 InFieldset: Fieldset,
282 OutFieldset: NotFieldset,
283 Repeat: Repeating,
284 {
285 let mut in_fields = InFieldset::ZERO;
286 f(&mut in_fields);
287
288 self.block
289 .interface()
290 .dispatch_command(
291 Repeat::calc_address(self.address, index),
292 in_fields.as_slice_mut(),
293 &InFieldset::METADATA,
294 &mut [],
295 &FieldsetMetadata::DEFAULT,
296 )
297 .await
298 }
299
300 pub fn dispatch_out(self) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
302 where
303 B::Interface: CommandInterface,
304 InFieldset: NotFieldset,
305 OutFieldset: Fieldset,
306 Repeat: NotRepeating,
307 {
308 let mut out_fields = OutFieldset::ZERO;
309
310 self.block.interface().dispatch_command(
311 self.address,
312 &mut [],
313 &FieldsetMetadata::DEFAULT,
314 out_fields.as_slice_mut(),
315 &OutFieldset::METADATA,
316 )?;
317
318 Ok(out_fields)
319 }
320
321 #[track_caller]
323 pub fn dispatch_out_at(
324 self,
325 index: Repeat::Index,
326 ) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
327 where
328 B::Interface: CommandInterface,
329 InFieldset: NotFieldset,
330 OutFieldset: Fieldset,
331 Repeat: Repeating,
332 {
333 let mut out_fields = OutFieldset::ZERO;
334
335 self.block.interface().dispatch_command(
336 Repeat::calc_address(self.address, index),
337 &mut [],
338 &FieldsetMetadata::DEFAULT,
339 out_fields.as_slice_mut(),
340 &OutFieldset::METADATA,
341 )?;
342
343 Ok(out_fields)
344 }
345
346 pub async fn dispatch_out_async(
348 self,
349 ) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
350 where
351 B::Interface: AsyncCommandInterface,
352 InFieldset: NotFieldset,
353 OutFieldset: Fieldset,
354 Repeat: NotRepeating,
355 {
356 let mut out_fields = OutFieldset::ZERO;
357
358 self.block
359 .interface()
360 .dispatch_command(
361 self.address,
362 &mut [],
363 &FieldsetMetadata::DEFAULT,
364 out_fields.as_slice_mut(),
365 &OutFieldset::METADATA,
366 )
367 .await?;
368
369 Ok(out_fields)
370 }
371
372 pub async fn dispatch_out_at_async(
374 self,
375 index: Repeat::Index,
376 ) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
377 where
378 B::Interface: AsyncCommandInterface,
379 InFieldset: NotFieldset,
380 OutFieldset: Fieldset,
381 Repeat: Repeating,
382 {
383 let mut out_fields = OutFieldset::ZERO;
384
385 self.block
386 .interface()
387 .dispatch_command(
388 Repeat::calc_address(self.address, index),
389 &mut [],
390 &FieldsetMetadata::DEFAULT,
391 out_fields.as_slice_mut(),
392 &OutFieldset::METADATA,
393 )
394 .await?;
395
396 Ok(out_fields)
397 }
398
399 pub fn dispatch_inout(
401 self,
402 f: impl FnOnce(&mut InFieldset),
403 ) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
404 where
405 B::Interface: CommandInterface,
406 InFieldset: Fieldset,
407 OutFieldset: Fieldset,
408 Repeat: NotRepeating,
409 {
410 let mut in_fields = InFieldset::ZERO;
411 f(&mut in_fields);
412
413 let mut out_fields = OutFieldset::ZERO;
414
415 self.block.interface().dispatch_command(
416 self.address,
417 in_fields.as_slice_mut(),
418 &InFieldset::METADATA,
419 out_fields.as_slice_mut(),
420 &OutFieldset::METADATA,
421 )?;
422
423 Ok(out_fields)
424 }
425
426 #[track_caller]
428 pub fn dispatch_inout_at(
429 self,
430 index: Repeat::Index,
431 f: impl FnOnce(&mut InFieldset),
432 ) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
433 where
434 B::Interface: CommandInterface,
435 InFieldset: Fieldset,
436 OutFieldset: Fieldset,
437 Repeat: Repeating,
438 {
439 let mut in_fields = InFieldset::ZERO;
440 f(&mut in_fields);
441
442 let mut out_fields = OutFieldset::ZERO;
443
444 self.block.interface().dispatch_command(
445 Repeat::calc_address(self.address, index),
446 in_fields.as_slice_mut(),
447 &InFieldset::METADATA,
448 out_fields.as_slice_mut(),
449 &OutFieldset::METADATA,
450 )?;
451
452 Ok(out_fields)
453 }
454
455 pub async fn dispatch_inout_async(
457 self,
458 f: impl FnOnce(&mut InFieldset),
459 ) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
460 where
461 B::Interface: AsyncCommandInterface,
462 InFieldset: Fieldset,
463 OutFieldset: Fieldset,
464 Repeat: NotRepeating,
465 {
466 let mut in_fields = InFieldset::ZERO;
467 f(&mut in_fields);
468
469 let mut out_fields = OutFieldset::ZERO;
470
471 self.block
472 .interface()
473 .dispatch_command(
474 self.address,
475 in_fields.as_slice_mut(),
476 &InFieldset::METADATA,
477 out_fields.as_slice_mut(),
478 &OutFieldset::METADATA,
479 )
480 .await?;
481
482 Ok(out_fields)
483 }
484
485 pub async fn dispatch_inout_at_async(
487 self,
488 index: Repeat::Index,
489 f: impl FnOnce(&mut InFieldset),
490 ) -> Result<OutFieldset, <B::Interface as CommandInterfaceBase>::Error>
491 where
492 B::Interface: AsyncCommandInterface,
493 InFieldset: Fieldset,
494 OutFieldset: Fieldset,
495 Repeat: Repeating,
496 {
497 let mut in_fields = InFieldset::ZERO;
498 f(&mut in_fields);
499
500 let mut out_fields = OutFieldset::ZERO;
501
502 self.block
503 .interface()
504 .dispatch_command(
505 Repeat::calc_address(self.address, index),
506 in_fields.as_slice_mut(),
507 &InFieldset::METADATA,
508 out_fields.as_slice_mut(),
509 &OutFieldset::METADATA,
510 )
511 .await?;
512
513 Ok(out_fields)
514 }
515}