autd3_driver/datagram/
boxed.rs1use std::mem::MaybeUninit;
2
3use crate::{
4 datagram::Datagram,
5 error::AUTDDriverError,
6 firmware::operation::{BoxedOperation, OperationGenerator},
7};
8use autd3_core::{
9 datagram::{DatagramOption, Operation},
10 geometry::{Device, Geometry},
11};
12
13pub trait DOperationGenerator {
14 #[must_use]
15 fn dyn_generate(&mut self, device: &Device) -> (BoxedOperation, BoxedOperation);
16}
17
18pub struct DynOperationGenerator {
19 g: Box<dyn DOperationGenerator>,
20}
21
22impl OperationGenerator for DynOperationGenerator {
23 type O1 = BoxedOperation;
24 type O2 = BoxedOperation;
25
26 fn generate(&mut self, device: &Device) -> (Self::O1, Self::O2) {
27 self.g.dyn_generate(device)
28 }
29}
30
31impl<G: OperationGenerator> DOperationGenerator for G
32where
33 G::O1: 'static,
34 G::O2: 'static,
35 AUTDDriverError: From<<G::O1 as Operation>::Error> + From<<G::O2 as Operation>::Error>,
36{
37 fn dyn_generate(&mut self, device: &Device) -> (BoxedOperation, BoxedOperation) {
38 let (o1, o2) = self.generate(device);
39 (BoxedOperation::new(o1), BoxedOperation::new(o2))
40 }
41}
42
43pub trait DDatagram: std::fmt::Debug {
44 fn dyn_operation_generator(
45 &mut self,
46 geometry: &Geometry,
47 parallel: bool,
48 ) -> Result<Box<dyn DOperationGenerator>, AUTDDriverError>;
49 #[must_use]
50 fn dyn_option(&self) -> DatagramOption;
51 fn dyn_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
52}
53
54impl<E, G: DOperationGenerator + 'static, T: Datagram<G = G, Error = E>> DDatagram
55 for MaybeUninit<T>
56where
57 AUTDDriverError: From<E>,
58{
59 fn dyn_operation_generator(
60 &mut self,
61 geometry: &Geometry,
62 parallel: bool,
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, parallel)?))
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
84#[cfg(feature = "lightweight")]
85unsafe impl Send for BoxedDatagram {}
86#[cfg(feature = "lightweight")]
87unsafe impl Sync for BoxedDatagram {}
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 fn new<E, G: OperationGenerator + 'static, D: Datagram<G = G, Error = E> + 'static>(
97 d: D,
98 ) -> Self
99 where
100 AUTDDriverError: From<E>,
101 AUTDDriverError: From<<G::O1 as Operation>::Error> + From<<G::O2 as Operation>::Error>,
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 parallel: bool,
117 ) -> Result<Self::G, Self::Error> {
118 let Self { mut d } = self;
119 Ok(DynOperationGenerator {
120 g: d.dyn_operation_generator(geometry, parallel)?,
121 })
122 }
123
124 fn option(&self) -> DatagramOption {
125 self.d.dyn_option()
126 }
127}
128
129pub trait IntoBoxedDatagram {
131 #[must_use]
133 fn into_boxed(self) -> BoxedDatagram;
134}
135
136impl<
137 E,
138 G: OperationGenerator + 'static,
139 #[cfg(not(feature = "lightweight"))] D: Datagram<Error = E, G = G> + 'static,
140 #[cfg(feature = "lightweight")] D: Datagram<Error = E, G = G> + Send + Sync + 'static,
141> IntoBoxedDatagram for D
142where
143 AUTDDriverError: From<E>,
144 AUTDDriverError: From<<G::O1 as Operation>::Error> + From<<G::O2 as Operation>::Error>,
145{
146 fn into_boxed(self) -> BoxedDatagram {
147 BoxedDatagram::new(self)
148 }
149}
150
151#[cfg(test)]
152mod tests {
153
154 use super::*;
155
156 struct TestDatagram;
158 struct TestOperationGenerator;
159
160 impl OperationGenerator for TestOperationGenerator {
161 type O1 = autd3_core::datagram::NullOp;
162 type O2 = autd3_core::datagram::NullOp;
163
164 fn generate(&mut self, _device: &Device) -> (Self::O1, Self::O2) {
165 unimplemented!()
166 }
167 }
168
169 impl Datagram for TestDatagram {
170 type G = TestOperationGenerator;
171 type Error = AUTDDriverError;
172
173 fn operation_generator(
174 self,
175 _geometry: &Geometry,
176 _parallel: bool,
177 ) -> Result<Self::G, Self::Error> {
178 Ok(Self::G {})
179 }
180 }
181 impl std::fmt::Debug for TestDatagram {
184 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
185 write!(f, "test")
186 }
187 }
188
189 #[test]
190 fn boxed_fmt() {
191 let d = TestDatagram;
192 let bd = BoxedDatagram::new(d);
193 assert_eq!(format!("{:?}", bd), "test");
194 }
195}