Skip to main content

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#[cfg(feature = "async")]
82/// A trait that provides the interface with the device.
83pub trait AsyncLink {
84    /// Opens the link.
85    fn open(
86        &mut self,
87        geometry: &Geometry,
88    ) -> impl std::future::Future<Output = Result<(), LinkError>>;
89
90    /// Closes the link.
91    fn close(&mut self) -> impl std::future::Future<Output = Result<(), LinkError>>;
92
93    #[doc(hidden)]
94    fn update(&mut self, _: &Geometry) -> impl std::future::Future<Output = Result<(), LinkError>>;
95
96    /// Allocate a sending buffer for the link.
97    fn alloc_tx_buffer(
98        &mut self,
99    ) -> impl std::future::Future<Output = Result<Vec<TxMessage>, LinkError>>;
100
101    /// Sends a message to the device.
102    fn send(
103        &mut self,
104        tx: Vec<TxMessage>,
105    ) -> impl std::future::Future<Output = Result<(), LinkError>>;
106
107    /// Receives a message from the device.
108    fn receive(
109        &mut self,
110        rx: &mut [RxMessage],
111    ) -> impl std::future::Future<Output = Result<(), LinkError>>;
112
113    /// Checks if the link is open.
114    #[must_use]
115    fn is_open(&self) -> bool;
116
117    /// Ensures that the link is open, returning an error if it is not.
118    fn ensure_is_open(&self) -> Result<(), LinkError>;
119}
120
121#[cfg(test)]
122mod tests {
123    use super::*;
124
125    struct MockLink {
126        is_open: bool,
127        open_called: bool,
128        close_called: bool,
129        update_called: bool,
130        alloc_called: bool,
131        send_called: bool,
132        receive_called: bool,
133    }
134
135    impl MockLink {
136        fn new() -> Self {
137            Self {
138                is_open: false,
139                open_called: false,
140                close_called: false,
141                update_called: false,
142                alloc_called: false,
143                send_called: false,
144                receive_called: false,
145            }
146        }
147    }
148
149    impl Link for MockLink {
150        fn open(&mut self, _geometry: &Geometry) -> Result<(), LinkError> {
151            self.open_called = true;
152            self.is_open = true;
153            Ok(())
154        }
155
156        fn close(&mut self) -> Result<(), LinkError> {
157            self.close_called = true;
158            self.is_open = false;
159            Ok(())
160        }
161
162        fn update(&mut self, _geometry: &Geometry) -> Result<(), LinkError> {
163            self.update_called = true;
164            Ok(())
165        }
166
167        fn alloc_tx_buffer(&mut self) -> Result<Vec<TxMessage>, LinkError> {
168            self.alloc_called = true;
169            Ok(vec![])
170        }
171
172        fn send(&mut self, _tx: Vec<TxMessage>) -> Result<(), LinkError> {
173            self.send_called = true;
174            Ok(())
175        }
176
177        fn receive(&mut self, _rx: &mut [RxMessage]) -> Result<(), LinkError> {
178            self.receive_called = true;
179            Ok(())
180        }
181
182        fn is_open(&self) -> bool {
183            self.is_open
184        }
185    }
186
187    #[test]
188    fn open() -> Result<(), LinkError> {
189        let mut link = MockLink::new();
190        let geometry = Geometry::new(vec![]);
191
192        assert!(!Link::is_open(&link));
193        Link::open(&mut link, &geometry)?;
194        assert!(link.open_called);
195        assert!(Link::is_open(&link));
196
197        Ok(())
198    }
199
200    #[test]
201    fn close() -> Result<(), LinkError> {
202        let mut link = MockLink::new();
203        link.is_open = true;
204
205        Link::close(&mut link)?;
206        assert!(link.close_called);
207        assert!(!Link::is_open(&link));
208
209        Ok(())
210    }
211
212    #[test]
213    fn update() -> Result<(), LinkError> {
214        let mut link = MockLink::new();
215        let geometry = Geometry::new(vec![]);
216
217        Link::update(&mut link, &geometry)?;
218        assert!(link.update_called);
219
220        Ok(())
221    }
222
223    #[test]
224    fn alloc_tx_buffer() -> Result<(), LinkError> {
225        let mut link = MockLink::new();
226
227        Link::alloc_tx_buffer(&mut link)?;
228        assert!(link.alloc_called);
229
230        Ok(())
231    }
232
233    #[test]
234    fn send() -> Result<(), LinkError> {
235        let mut link = MockLink::new();
236        let tx = vec![];
237
238        Link::send(&mut link, tx)?;
239        assert!(link.send_called);
240
241        Ok(())
242    }
243
244    #[test]
245    fn receive() -> Result<(), LinkError> {
246        let mut link = MockLink::new();
247        let mut rx = vec![];
248
249        Link::receive(&mut link, &mut rx)?;
250        assert!(link.receive_called);
251
252        Ok(())
253    }
254
255    #[test]
256    fn is_open() {
257        let mut link = MockLink::new();
258
259        assert!(!Link::is_open(&link));
260        link.is_open = true;
261        assert!(Link::is_open(&link));
262    }
263
264    #[test]
265    fn ensure_is_open() {
266        let mut link = MockLink::new();
267
268        let result = Link::ensure_is_open(&link);
269        assert_eq!(Err(LinkError::closed()), result);
270        link.is_open = true;
271        assert!(Link::ensure_is_open(&link).is_ok());
272    }
273}