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