autd3_core/link/
mod.rs

1mod buffer_pool;
2mod datagram;
3mod error;
4
5pub use buffer_pool::*;
6pub use datagram::*;
7pub use error::LinkError;
8
9use crate::geometry::Geometry;
10
11/// A trait that provides the interface with the device.
12pub trait Link: Send {
13    /// Opens the link.
14    fn open(&mut self, geometry: &Geometry) -> Result<(), LinkError>;
15
16    /// Closes the link.
17    fn close(&mut self) -> Result<(), LinkError>;
18
19    #[doc(hidden)]
20    fn update(&mut self, _: &Geometry) -> Result<(), LinkError> {
21        Ok(())
22    }
23
24    /// Allocate a sending buffer for the link.
25    fn alloc_tx_buffer(&mut self) -> Result<Vec<TxMessage>, LinkError>;
26
27    /// Sends a message to the device.
28    fn send(&mut self, tx: Vec<TxMessage>) -> Result<(), LinkError>;
29
30    /// Receives a message from the device.
31    fn receive(&mut self, rx: &mut [RxMessage]) -> Result<(), LinkError>;
32
33    /// Checks if the link is open.
34    #[must_use]
35    fn is_open(&self) -> bool;
36
37    /// Ensures that the link is open, returning an error if it is not.
38    fn ensure_is_open(&self) -> Result<(), LinkError> {
39        if self.is_open() {
40            Ok(())
41        } else {
42            Err(LinkError::closed())
43        }
44    }
45}
46
47impl Link for Box<dyn Link> {
48    fn open(&mut self, geometry: &Geometry) -> Result<(), LinkError> {
49        self.as_mut().open(geometry)
50    }
51
52    fn close(&mut self) -> Result<(), LinkError> {
53        self.as_mut().close()
54    }
55
56    fn update(&mut self, geometry: &Geometry) -> Result<(), LinkError> {
57        self.as_mut().update(geometry)
58    }
59
60    fn alloc_tx_buffer(&mut self) -> Result<Vec<TxMessage>, LinkError> {
61        self.as_mut().alloc_tx_buffer()
62    }
63
64    fn send(&mut self, tx: Vec<TxMessage>) -> Result<(), LinkError> {
65        self.as_mut().send(tx)
66    }
67
68    fn receive(&mut self, rx: &mut [RxMessage]) -> Result<(), LinkError> {
69        self.as_mut().receive(rx)
70    }
71
72    fn is_open(&self) -> bool {
73        self.as_ref().is_open()
74    }
75
76    fn ensure_is_open(&self) -> Result<(), LinkError> {
77        self.as_ref().ensure_is_open()
78    }
79}
80
81#[doc(hidden)]
82pub trait AsyncLink: Link {
83    fn open(
84        &mut self,
85        geometry: &Geometry,
86    ) -> impl std::future::Future<Output = Result<(), LinkError>> {
87        async { <Self as Link>::open(self, geometry) }
88    }
89
90    fn close(&mut self) -> impl std::future::Future<Output = Result<(), LinkError>> {
91        async { <Self as Link>::close(self) }
92    }
93
94    fn update(
95        &mut self,
96        geometry: &Geometry,
97    ) -> impl std::future::Future<Output = Result<(), LinkError>> {
98        async { <Self as Link>::update(self, geometry) }
99    }
100
101    fn alloc_tx_buffer(
102        &mut self,
103    ) -> impl std::future::Future<Output = Result<Vec<TxMessage>, LinkError>> {
104        async { <Self as Link>::alloc_tx_buffer(self) }
105    }
106
107    fn send(
108        &mut self,
109        tx: Vec<TxMessage>,
110    ) -> impl std::future::Future<Output = Result<(), LinkError>> {
111        async { <Self as Link>::send(self, tx) }
112    }
113
114    fn receive(
115        &mut self,
116        rx: &mut [RxMessage],
117    ) -> impl std::future::Future<Output = Result<(), LinkError>> {
118        async { <Self as Link>::receive(self, rx) }
119    }
120
121    #[must_use]
122    fn is_open(&self) -> bool {
123        <Self as Link>::is_open(self)
124    }
125
126    fn ensure_is_open(&self) -> Result<(), LinkError> {
127        <Self as Link>::ensure_is_open(self)
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use super::*;
134
135    struct MockLink {
136        is_open: bool,
137        open_called: bool,
138        close_called: bool,
139        update_called: bool,
140        alloc_called: bool,
141        send_called: bool,
142        receive_called: bool,
143    }
144
145    impl MockLink {
146        fn new() -> Self {
147            Self {
148                is_open: false,
149                open_called: false,
150                close_called: false,
151                update_called: false,
152                alloc_called: false,
153                send_called: false,
154                receive_called: false,
155            }
156        }
157    }
158
159    impl Link for MockLink {
160        fn open(&mut self, _geometry: &Geometry) -> Result<(), LinkError> {
161            self.open_called = true;
162            self.is_open = true;
163            Ok(())
164        }
165
166        fn close(&mut self) -> Result<(), LinkError> {
167            self.close_called = true;
168            self.is_open = false;
169            Ok(())
170        }
171
172        fn update(&mut self, _geometry: &Geometry) -> Result<(), LinkError> {
173            self.update_called = true;
174            Ok(())
175        }
176
177        fn alloc_tx_buffer(&mut self) -> Result<Vec<TxMessage>, LinkError> {
178            self.alloc_called = true;
179            Ok(vec![])
180        }
181
182        fn send(&mut self, _tx: Vec<TxMessage>) -> Result<(), LinkError> {
183            self.send_called = true;
184            Ok(())
185        }
186
187        fn receive(&mut self, _rx: &mut [RxMessage]) -> Result<(), LinkError> {
188            self.receive_called = true;
189            Ok(())
190        }
191
192        fn is_open(&self) -> bool {
193            self.is_open
194        }
195    }
196
197    impl AsyncLink for MockLink {}
198
199    #[test]
200    fn open() -> Result<(), LinkError> {
201        let mut link = MockLink::new();
202        let geometry = Geometry::new(vec![]);
203
204        assert!(!AsyncLink::is_open(&link));
205        futures_lite::future::block_on(AsyncLink::open(&mut link, &geometry))?;
206        assert!(link.open_called);
207        assert!(AsyncLink::is_open(&link));
208
209        Ok(())
210    }
211
212    #[test]
213    fn close() -> Result<(), LinkError> {
214        let mut link = MockLink::new();
215        link.is_open = true;
216
217        futures_lite::future::block_on(AsyncLink::close(&mut link))?;
218        assert!(link.close_called);
219        assert!(!AsyncLink::is_open(&link));
220
221        Ok(())
222    }
223
224    #[test]
225    fn update() -> Result<(), LinkError> {
226        let mut link = MockLink::new();
227        let geometry = Geometry::new(vec![]);
228
229        futures_lite::future::block_on(AsyncLink::update(&mut link, &geometry))?;
230        assert!(link.update_called);
231
232        Ok(())
233    }
234
235    #[test]
236    fn alloc_tx_buffer() -> Result<(), LinkError> {
237        let mut link = MockLink::new();
238
239        futures_lite::future::block_on(AsyncLink::alloc_tx_buffer(&mut link))?;
240        assert!(link.alloc_called);
241
242        Ok(())
243    }
244
245    #[test]
246    fn send() -> Result<(), LinkError> {
247        let mut link = MockLink::new();
248        let tx = vec![];
249
250        futures_lite::future::block_on(AsyncLink::send(&mut link, tx))?;
251        assert!(link.send_called);
252
253        Ok(())
254    }
255
256    #[test]
257    fn receive() -> Result<(), LinkError> {
258        let mut link = MockLink::new();
259        let mut rx = vec![];
260
261        futures_lite::future::block_on(AsyncLink::receive(&mut link, &mut rx))?;
262        assert!(link.receive_called);
263
264        Ok(())
265    }
266
267    #[test]
268    fn is_open() {
269        let mut link = MockLink::new();
270
271        assert!(!AsyncLink::is_open(&link));
272        link.is_open = true;
273        assert!(AsyncLink::is_open(&link));
274    }
275
276    #[test]
277    fn ensure_is_open() {
278        let mut link = MockLink::new();
279
280        let result = AsyncLink::ensure_is_open(&link);
281        assert_eq!(Err(LinkError::closed()), result);
282        link.is_open = true;
283        assert!(AsyncLink::ensure_is_open(&link).is_ok());
284    }
285}