autd3_driver/firmware/driver/operation/
boxed.rs1use std::mem::MaybeUninit;
2
3use crate::{
4 error::AUTDDriverError,
5 firmware::driver::{Operation, Version},
6};
7
8use autd3_core::{
9 datagram::{DatagramOption, DeviceFilter},
10 derive::{Datagram, FirmwareLimits},
11 geometry::{Device, Geometry},
12};
13
14pub trait DOperation: Send + Sync {
15 #[must_use]
16 fn required_size(&self, device: &Device) -> usize;
17 fn pack(&mut self, device: &Device, tx: &mut [u8]) -> Result<usize, AUTDDriverError>;
18 #[must_use]
19 fn is_done(&self) -> bool;
20}
21
22#[doc(hidden)]
23pub struct BoxedOperation {
24 pub(crate) inner: Box<dyn DOperation>,
25}
26
27#[doc(hidden)]
28pub trait DOperationGenerator {
29 #[must_use]
30 fn dyn_generate(
31 &mut self,
32 device: &Device,
33 version: Version,
34 ) -> Option<(BoxedOperation, BoxedOperation)>;
35}
36
37pub struct DynOperationGenerator {
38 pub(crate) g: Box<dyn DOperationGenerator>,
39}
40
41pub trait DDatagram: std::fmt::Debug {
42 fn dyn_operation_generator(
43 &mut self,
44 geometry: &Geometry,
45 filter: &DeviceFilter,
46 limits: &FirmwareLimits,
47 ) -> Result<Box<dyn DOperationGenerator>, AUTDDriverError>;
48 #[must_use]
49 fn dyn_option(&self) -> DatagramOption;
50 fn dyn_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
51}
52
53impl<E, G: DOperationGenerator + 'static, T: Datagram<G = G, Error = E>> DDatagram
54 for MaybeUninit<T>
55where
56 AUTDDriverError: From<E>,
57{
58 fn dyn_operation_generator(
59 &mut self,
60 geometry: &Geometry,
61 filter: &DeviceFilter,
62 limits: &FirmwareLimits,
63 ) -> Result<Box<dyn DOperationGenerator>, AUTDDriverError> {
64 let mut tmp = MaybeUninit::<T>::uninit();
65 std::mem::swap(&mut tmp, self);
66 let d = unsafe { tmp.assume_init() };
67 Ok(Box::new(d.operation_generator(geometry, filter, limits)?))
68 }
69
70 fn dyn_option(&self) -> DatagramOption {
71 unsafe { self.assume_init_ref() }.option()
72 }
73
74 fn dyn_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 unsafe { self.assume_init_ref() }.fmt(f)
76 }
77}
78
79pub struct BoxedDatagram {
81 d: Box<dyn DDatagram>,
82}
83
84impl std::fmt::Debug for BoxedDatagram {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 self.d.dyn_fmt(f)
87 }
88}
89
90impl BoxedDatagram {
91 pub fn new<E, G: DOperationGenerator + 'static, D: Datagram<G = G, Error = E> + 'static>(
93 d: D,
94 ) -> Self
95 where
96 AUTDDriverError: From<E>,
97 {
98 BoxedDatagram {
99 d: Box::new(MaybeUninit::new(d)),
100 }
101 }
102}
103
104impl Datagram for BoxedDatagram {
105 type G = DynOperationGenerator;
106 type Error = AUTDDriverError;
107
108 fn operation_generator(
109 self,
110 geometry: &Geometry,
111 filter: &DeviceFilter,
112 limits: &FirmwareLimits,
113 ) -> Result<Self::G, Self::Error> {
114 let Self { mut d } = self;
115 Ok(DynOperationGenerator {
116 g: d.dyn_operation_generator(geometry, filter, limits)?,
117 })
118 }
119
120 fn option(&self) -> DatagramOption {
121 self.d.dyn_option()
122 }
123}
124
125impl<E, O: Operation<Error = E>> DOperation for O
126where
127 AUTDDriverError: From<E>,
128{
129 fn required_size(&self, device: &Device) -> usize {
130 O::required_size(self, device)
131 }
132
133 fn pack(&mut self, device: &Device, tx: &mut [u8]) -> Result<usize, AUTDDriverError> {
134 Ok(O::pack(self, device, tx)?)
135 }
136
137 fn is_done(&self) -> bool {
138 O::is_done(self)
139 }
140}
141
142impl Operation for BoxedOperation {
143 type Error = AUTDDriverError;
144
145 fn required_size(&self, device: &Device) -> usize {
146 self.inner.required_size(device)
147 }
148
149 fn pack(&mut self, device: &Device, tx: &mut [u8]) -> Result<usize, Self::Error> {
150 self.inner.pack(device, tx)
151 }
152
153 fn is_done(&self) -> bool {
154 self.inner.is_done()
155 }
156}
157
158#[cfg(test)]
159pub mod tests {
160 use super::*;
161
162 use rand::Rng;
163
164 use autd3_core::geometry::{Point3, Transducer, UnitQuaternion};
165
166 #[derive(Clone, Copy)]
167 pub struct TestOp {
168 pub req_size: usize,
169 pub pack_size: usize,
170 pub done: bool,
171 }
172
173 impl Operation for TestOp {
174 type Error = AUTDDriverError;
175
176 fn required_size(&self, _device: &Device) -> usize {
177 self.req_size
178 }
179
180 fn pack(&mut self, _device: &Device, _tx: &mut [u8]) -> Result<usize, Self::Error> {
181 Ok(self.pack_size)
182 }
183
184 fn is_done(&self) -> bool {
185 self.done
186 }
187 }
188
189 #[test]
190 fn test_boxed_operation() {
191 let mut rng = rand::rng();
192
193 let mut op = TestOp {
194 req_size: rng.random::<u32>() as usize,
195 pack_size: rng.random::<u32>() as usize,
196 done: rng.random(),
197 };
198 let mut boxed_op = BoxedOperation {
199 inner: Box::new(op),
200 };
201
202 let device = Device::new(
203 UnitQuaternion::identity(),
204 vec![Transducer::new(Point3::origin())],
205 );
206
207 assert_eq!(
208 Operation::required_size(&op, &device),
209 Operation::required_size(&boxed_op, &device)
210 );
211 assert_eq!(
212 Operation::pack(&mut op, &device, &mut []),
213 Operation::pack(&mut boxed_op, &device, &mut [])
214 );
215 assert_eq!(Operation::is_done(&op), Operation::is_done(&boxed_op));
216 }
217}