1use std::{
3 error::Error,
4 marker::PhantomData,
5 sync::mpsc::*,
6 time::{Duration, Instant},
7};
8
9use crate::byte_converter::FromByteSlice;
10
11#[derive(Debug, Copy, Clone)]
13pub enum BrickletError {
14 InvalidParameter,
16 FunctionNotSupported,
18 UnknownError,
20 NotConnected,
22 SuccessButResponseExpectedIsDisabled,
24}
25
26impl From<u8> for BrickletError {
27 fn from(byte: u8) -> BrickletError {
28 match byte {
29 1 => BrickletError::InvalidParameter,
30 2 => BrickletError::FunctionNotSupported,
31 _ => BrickletError::UnknownError,
32 }
33 }
34}
35
36impl std::fmt::Display for BrickletError {
37 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.description()) }
38}
39
40impl std::error::Error for BrickletError {
41 fn description(&self) -> &str {
42 match self {
43 BrickletError::InvalidParameter => "A parameter was invalid or had an unexpected length.",
44 BrickletError::FunctionNotSupported => "The brick or bricklet does not support the requested function.",
45 BrickletError::UnknownError => "UnknownError, Currently unused",
46 BrickletError::NotConnected => "The request can not be fulfulled, as there is currently no connection to a brick daemon.",
47 BrickletError::SuccessButResponseExpectedIsDisabled =>
48 "The request was sent, but response expected is disabled, so no response can be received. This is not an error.",
49 }
50 }
51}
52
53pub struct ConvertingReceiver<T: FromByteSlice> {
82 receiver: Receiver<Result<Vec<u8>, BrickletError>>,
83 sent_time: Instant,
84 timeout: Duration,
85 phantom: PhantomData<T>,
86}
87
88#[derive(Copy, Clone, Debug, PartialEq)]
90pub enum BrickletRecvTimeoutError {
91 QueueDisconnected,
93 QueueTimeout,
95 InvalidParameter,
97 FunctionNotSupported,
99 UnknownError,
101 MalformedPacket,
103 NotConnected,
105 SuccessButResponseExpectedIsDisabled,
107}
108
109impl std::fmt::Display for BrickletRecvTimeoutError {
110 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.description()) }
111}
112
113impl std::error::Error for BrickletRecvTimeoutError {
114 fn description(&self) -> &str {
115 match self {
116 BrickletRecvTimeoutError::QueueDisconnected =>
117 "The queue was disconnected. This usually happens if the ip connection is destroyed.",
118 BrickletRecvTimeoutError::QueueTimeout => "The request could not be responded to before the timeout was reached.",
119 BrickletRecvTimeoutError::InvalidParameter => "A parameter was invalid or had an unexpected length.",
120 BrickletRecvTimeoutError::FunctionNotSupported => "The brick or bricklet does not support the requested function.",
121 BrickletRecvTimeoutError::UnknownError => "UnknownError, Currently unused",
122 BrickletRecvTimeoutError::MalformedPacket =>
123 "The received packet had an unexpected length. Maybe a function was called on a wrong brick or bricklet?",
124 BrickletRecvTimeoutError::NotConnected =>
125 "The request can not be fulfulled, as there is currently no connection to a brick daemon.",
126 BrickletRecvTimeoutError::SuccessButResponseExpectedIsDisabled =>
127 "The request was sent, but response expected is disabled, so no response can be received. This is not an error.",
128 }
129 }
130}
131
132#[derive(Copy, Clone, Debug, PartialEq)]
134pub enum BrickletTryRecvError {
135 QueueDisconnected,
137 QueueEmpty,
139 InvalidParameter,
141 FunctionNotSupported,
143 UnknownError,
145 MalformedPacket,
147 NotConnected,
149 SuccessButResponseExpectedIsDisabled,
151}
152
153impl std::fmt::Display for BrickletTryRecvError {
154 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.description()) }
155}
156
157impl std::error::Error for BrickletTryRecvError {
158 fn description(&self) -> &str {
159 match self {
160 BrickletTryRecvError::QueueDisconnected =>
161 "The queue was disconnected. This usually happens if the ip connection is destroyed.",
162 BrickletTryRecvError::QueueEmpty => "There are currently no responses available.",
163 BrickletTryRecvError::InvalidParameter => "A parameter was invalid or had an unexpected length.",
164 BrickletTryRecvError::FunctionNotSupported => "The brick or bricklet does not support the requested function.",
165 BrickletTryRecvError::UnknownError => "UnknownError, Currently unused",
166 BrickletTryRecvError::MalformedPacket =>
167 "The received packet had an unexpected length. Maybe a function was called on a wrong brick or bricklet?",
168 BrickletTryRecvError::NotConnected =>
169 "The request can not be fulfulled, as there is currently no connection to a brick daemon.",
170 BrickletTryRecvError::SuccessButResponseExpectedIsDisabled =>
171 "The request was sent, but response expected is disabled, so no response can be received. This is not an error.",
172 }
173 }
174}
175
176impl<T: FromByteSlice> ConvertingReceiver<T> {
177 pub fn new(receiver: Receiver<Result<Vec<u8>, BrickletError>>, timeout: Duration) -> ConvertingReceiver<T> {
179 ConvertingReceiver { receiver, sent_time: Instant::now(), timeout, phantom: PhantomData }
180 }
181
182 pub fn try_recv(&self) -> Result<T, BrickletTryRecvError> {
192 let recv_result = self.receiver.try_recv();
193 match recv_result {
194 Ok(Ok(bytes)) =>
195 if T::bytes_expected() == bytes.len() {
196 Ok(T::from_le_byte_slice(&bytes))
197 } else {
198 Err(BrickletTryRecvError::MalformedPacket)
199 },
200 Ok(Err(BrickletError::InvalidParameter)) => Err(BrickletTryRecvError::InvalidParameter),
201 Ok(Err(BrickletError::FunctionNotSupported)) => Err(BrickletTryRecvError::FunctionNotSupported),
202 Ok(Err(BrickletError::UnknownError)) => Err(BrickletTryRecvError::UnknownError),
203 Ok(Err(BrickletError::NotConnected)) => Err(BrickletTryRecvError::NotConnected),
204 Ok(Err(BrickletError::SuccessButResponseExpectedIsDisabled)) => Err(BrickletTryRecvError::SuccessButResponseExpectedIsDisabled),
205 Err(TryRecvError::Disconnected) => Err(BrickletTryRecvError::QueueDisconnected),
206 Err(TryRecvError::Empty) => Err(BrickletTryRecvError::QueueEmpty),
207 }
208 }
209
210 pub fn recv(&self) -> Result<T, BrickletRecvTimeoutError> {
222 let recv_result = self.receiver.recv_timeout(self.sent_time + self.timeout - Instant::now());
223 match recv_result {
224 Ok(Ok(bytes)) =>
225 if T::bytes_expected() == bytes.len() {
226 Ok(T::from_le_byte_slice(&bytes))
227 } else {
228 Err(BrickletRecvTimeoutError::MalformedPacket)
229 },
230 Ok(Err(BrickletError::InvalidParameter)) => Err(BrickletRecvTimeoutError::InvalidParameter),
231 Ok(Err(BrickletError::FunctionNotSupported)) => Err(BrickletRecvTimeoutError::FunctionNotSupported),
232 Ok(Err(BrickletError::UnknownError)) => Err(BrickletRecvTimeoutError::UnknownError),
233 Ok(Err(BrickletError::NotConnected)) => Err(BrickletRecvTimeoutError::NotConnected),
234 Ok(Err(BrickletError::SuccessButResponseExpectedIsDisabled)) =>
235 Err(BrickletRecvTimeoutError::SuccessButResponseExpectedIsDisabled),
236 Err(RecvTimeoutError::Disconnected) => Err(BrickletRecvTimeoutError::QueueDisconnected),
237 Err(RecvTimeoutError::Timeout) => Err(BrickletRecvTimeoutError::QueueTimeout),
238 }
239 }
240 pub fn iter(&self) -> Iter<T> { Iter { rx: self } }
271
272 pub fn try_iter(&self) -> TryIter<T> { TryIter { rx: self } }
273}
274
275pub struct Iter<'a, T: 'a + FromByteSlice> {
276 rx: &'a ConvertingReceiver<T>,
277}
278
279pub struct TryIter<'a, T: 'a + FromByteSlice> {
280 rx: &'a ConvertingReceiver<T>,
281}
282
283pub struct IntoIter<T: FromByteSlice> {
284 rx: ConvertingReceiver<T>,
285}
286
287impl<'a, T: FromByteSlice> Iterator for Iter<'a, T> {
288 type Item = T;
289
290 fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
291}
292
293impl<'a, T: FromByteSlice> Iterator for TryIter<'a, T> {
294 type Item = T;
295
296 fn next(&mut self) -> Option<T> { self.rx.try_recv().ok() }
297}
298
299impl<'a, T: FromByteSlice> IntoIterator for &'a ConvertingReceiver<T> {
300 type Item = T;
301 type IntoIter = Iter<'a, T>;
302
303 fn into_iter(self) -> Iter<'a, T> { self.iter() }
304}
305
306impl<T: FromByteSlice> Iterator for IntoIter<T> {
307 type Item = T;
308 fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
309}
310
311impl<T: FromByteSlice> IntoIterator for ConvertingReceiver<T> {
312 type Item = T;
313 type IntoIter = IntoIter<T>;
314
315 fn into_iter(self) -> IntoIter<T> { IntoIter { rx: self } }
316}