autd3_driver/datagram/modulation/
boxed.rs1use std::mem::MaybeUninit;
2
3use autd3_core::derive::*;
4use autd3_derive::Modulation;
5
6pub trait DModulation {
8 fn dyn_calc(&mut self) -> Result<Vec<u8>, ModulationError>;
9 fn dyn_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
10}
11
12impl<
13 #[cfg(not(feature = "lightweight"))] T: Modulation,
14 #[cfg(feature = "lightweight")] T: Modulation + Send + Sync,
15> DModulation for MaybeUninit<T>
16{
17 fn dyn_calc(&mut self) -> Result<Vec<u8>, ModulationError> {
18 let mut tmp: MaybeUninit<T> = MaybeUninit::uninit();
19 std::mem::swap(&mut tmp, self);
20 let g = unsafe { tmp.assume_init() };
22 g.calc()
23 }
24
25 fn dyn_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 unsafe { self.assume_init_ref() }.fmt(f)
28 }
29}
30
31#[derive(Modulation)]
35pub struct BoxedModulation {
36 m: Box<dyn DModulation>,
37 sampling_config: SamplingConfig,
38}
39
40#[cfg(feature = "lightweight")]
41unsafe impl Send for BoxedModulation {}
42#[cfg(feature = "lightweight")]
43unsafe impl Sync for BoxedModulation {}
44
45impl std::fmt::Debug for BoxedModulation {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 self.m.as_ref().dyn_fmt(f)
48 }
49}
50
51impl Modulation for BoxedModulation {
52 fn calc(self) -> Result<Vec<u8>, ModulationError> {
53 let Self { mut m, .. } = self;
54 m.dyn_calc()
55 }
56
57 fn sampling_config(&self) -> SamplingConfig {
58 self.sampling_config
59 }
60}
61
62pub trait IntoBoxedModulation {
64 #[must_use]
66 fn into_boxed(self) -> BoxedModulation;
67}
68
69impl<
70 #[cfg(not(feature = "lightweight"))] M: Modulation + 'static,
71 #[cfg(feature = "lightweight")] M: Modulation + Send + Sync + 'static,
72> IntoBoxedModulation for M
73{
74 fn into_boxed(self) -> BoxedModulation {
75 let sampling_config = self.sampling_config();
76 BoxedModulation {
77 m: Box::new(MaybeUninit::new(self)),
78 sampling_config,
79 }
80 }
81}
82
83#[cfg(test)]
84pub mod tests {
85 use super::*;
86 use crate::datagram::modulation::tests::TestModulation;
87
88 #[test]
89 fn boxed_modulation_unsafe() {
90 let m = TestModulation {
91 sampling_config: SamplingConfig::FREQ_4K,
92 };
93
94 let mb = m.clone().into_boxed();
95
96 assert_eq!(format!("{:?}", m), format!("{:?}", mb));
97 assert_eq!(SamplingConfig::FREQ_4K, mb.sampling_config());
98 assert_eq!(Ok(vec![0; 2]), mb.calc());
99 }
100}