embedded_serial/
lib.rs

1//! # Embedded Serial traits
2//!
3//! Traits to describe Serial port (UART) functionality.
4//!
5//! A serial port is taken here to mean a device which can send and/or receive
6//! data one octet at a time, in order. Octets are represented using the `u8`
7//! type. We are careful here to talk only in octets, not characters (although
8//! if you ASCII or UTF-8 encode your strings, they become a sequence of
9//! octets).
10//!
11//! This crate contains traits that are suitable for embedded development.
12//! This allows developers to produce crates that depend upon generic UART
13//! functionality (for example, an AT command interface), allowing the
14//! application developer to combine the crate with the specific UART
15//! available on their board.
16//!
17//! It is similar to the C idea of using the functions `getc` and `putc` to
18//! decouple the IO device from the library, but in a more Rustic fashion.
19//!
20//! Here's an example with the `MutBlockingTx` trait.
21//!
22//! ```
23//! use embedded_serial::MutBlockingTx;
24//!
25//! struct SomeStruct<T> { uart: T };
26//!
27//! impl<T> SomeStruct<T> where T: MutBlockingTx {
28//!     fn new(uart: T) -> SomeStruct<T> {
29//!         SomeStruct { uart: uart }
30//!     }
31//!
32//!     fn write_data(&mut self) -> Result<(), <T as MutBlockingTx>::Error> {
33//!         self.uart.puts(b"AT\n").map_err(|e| e.1)?;
34//!         Ok(())
35//!     }
36//! }
37//! ```
38//!
39//! Here's an example with the `MutBlockingTxWithTimeout` trait.
40//!
41//! ```
42//! struct SomeStruct<T> { uart: T };
43//!
44//! use embedded_serial::MutBlockingTxWithTimeout;
45//!
46//! impl<T> SomeStruct<T> where T: MutBlockingTxWithTimeout {
47//!     fn new(uart: T) -> SomeStruct<T> {
48//!         SomeStruct { uart: uart }
49//!     }
50//!
51//!     fn write_data(&mut self, timeout: &<T as MutBlockingTxWithTimeout>::Timeout) -> Result<bool, <T as MutBlockingTxWithTimeout>::Error> {
52//!         let len = self.uart.puts_wait(b"AT\n", timeout).map_err(|e| e.1)?;
53//!         Ok(len == 3)
54//!     }
55//! }
56//! ```
57//!
58//! Here's an example with the `MutNonBlockingTx` trait. You would call the `write_data` function until it returned `Ok(true)`.
59//!
60//! ```
61//! use embedded_serial::MutNonBlockingTx;
62//!
63//! struct SomeStruct<T> {
64//!     sent: Option<usize>,
65//!     uart: T
66//! };
67//!
68//! impl<T> SomeStruct<T> where T: MutNonBlockingTx {
69//!
70//!     fn new(uart: T) -> SomeStruct<T> {
71//!         SomeStruct { uart: uart, sent: Some(0) }
72//!     }
73//!
74//!     fn write_data(&mut self) -> Result<bool, <T as MutNonBlockingTx>::Error> {
75//!         let data = b"AT\n";
76//!         if let Some(len) = self.sent {
77//!             match self.uart.puts_try(&data[len..]) {
78//!                 // Sent some or more of the data
79//!                 Ok(sent) => {
80//!                     let total = len + sent;
81//!                     self.sent = if total == data.len() {
82//!                         None
83//!                     } else {
84//!                         Some(total)
85//!                     };
86//!                     Ok(false)
87//!                 }
88//!                 // Sent some of the data but errored out
89//!                 Err((sent, e)) => {
90//!                     let total = len + sent;
91//!                     self.sent = if total == data.len() {
92//!                         None
93//!                     } else {
94//!                         Some(total)
95//!                     };
96//!                     Err(e)
97//!                 }
98//!             }
99//!         } else {
100//!             Ok(true)
101//!         }
102//!     }
103//! }
104//! ```
105//!
106//! In this example, we read three octets from a blocking serial port.
107//!
108//! ```
109//! use embedded_serial::MutBlockingRx;
110//!
111//! pub struct SomeStruct<T> { uart: T }
112//!
113//! impl<T> SomeStruct<T> where T: MutBlockingRx {
114//!     pub fn new(uart: T) -> SomeStruct<T> {
115//!         SomeStruct { uart: uart }
116//!     }
117//!
118//!     pub fn read_response(&mut self) -> Result<(), <T as MutBlockingRx>::Error> {
119//!         let mut buffer = [0u8; 3];
120//!         // If we got an error, we don't care any many we actually received.
121//!         self.uart.gets(&mut buffer).map_err(|e| e.1)?;
122//!         // process data in buffer here
123//!         Ok(())
124//!     }
125//! }
126//! ```
127//!
128//! In this example, we read three octets from a blocking serial port, with a timeout.
129//!
130//! ```
131//! use embedded_serial::MutBlockingRxWithTimeout;
132//!
133//! pub struct SomeStruct<T> { uart: T }
134//!
135//! impl<T> SomeStruct<T> where T: MutBlockingRxWithTimeout {
136//!     pub fn new(uart: T) -> SomeStruct<T> {
137//!         SomeStruct { uart: uart }
138//!     }
139//!
140//!     pub fn read_response(&mut self, timeout: &<T as MutBlockingRxWithTimeout>::Timeout) -> Result<bool, <T as MutBlockingRxWithTimeout>::Error> {
141//!         let mut buffer = [0u8; 3];
142//!         // If we got an error, we don't care any many we actually received.
143//!         let len = self.uart.gets_wait(&mut buffer, timeout).map_err(|e| e.1)?;
144//!         // process data in buffer here
145//!         Ok(len == buffer.len())
146//!     }
147//! }
148//! ```
149//!
150//! In this example, we read 16 octets from a non-blocking serial port into a
151//! vector which grows to contain exactly as much as we have read so far. You
152//! would call the `read_data` function until it returned `Ok(true)`. This differs
153//! from the other examples in that we have an immutable reference to our UART
154//! instead of owning it.
155//!
156//! ```
157//! use embedded_serial::ImmutNonBlockingRx;
158//!
159//! struct SomeStruct<'a, T> where T: 'a {
160//!     buffer: Vec<u8>,
161//!     uart: &'a T
162//! };
163//!
164//! const CHUNK_SIZE: usize = 4;
165//! const WANTED: usize = 16;
166//!
167//! impl<'a, T> SomeStruct<'a, T> where T: ImmutNonBlockingRx {
168//!
169//!     fn new(uart: &T) -> SomeStruct<T> {
170//!         SomeStruct { uart: uart, buffer: Vec::new() }
171//!     }
172//!
173//!     fn read_data(&mut self) -> Result<bool, <T as ImmutNonBlockingRx>::Error> {
174//!         let mut buffer = [0u8; CHUNK_SIZE];
175//!         if self.buffer.len() < WANTED {
176//!             let needed = WANTED - self.buffer.len();
177//!             let this_time = if needed < CHUNK_SIZE { needed } else { CHUNK_SIZE };
178//!             match self.uart.gets_try(&mut buffer[0..needed]) {
179//!                 // Read some or more of the data
180//!                 Ok(read) => {
181//!                     self.buffer.extend(&buffer[0..read]);
182//!                     Ok(self.buffer.len() == WANTED)
183//!                 }
184//!                 // Sent some of the data but errored out
185//!                 Err((read, e)) => {
186//!                     self.buffer.extend(&buffer[0..read]);
187//!                     Err(e)
188//!                 }
189//!             }
190//!         } else {
191//!             Ok(true)
192//!         }
193//!     }
194//! }
195//! ```
196
197#![no_std]
198#![deny(missing_docs)]
199
200// Earlier names for the traits, which assume mutability.
201pub use MutBlockingTx as BlockingTx;
202pub use MutBlockingTxWithTimeout as BlockingTxWithTimeout;
203pub use MutNonBlockingTx as NonBlockingTx;
204pub use MutBlockingRx as BlockingRx;
205pub use MutBlockingRxWithTimeout as BlockingRxWithTimeout;
206pub use MutNonBlockingRx as NonBlockingRx;
207
208/// Implementors of this trait offer octet based serial data transmission
209/// using a blocking API and requiring a mutable reference to self.
210pub trait MutBlockingTx {
211    /// The error type returned if a function fails.
212    type Error;
213
214    /// Write a single octet to the port's transmitter,
215    /// blocking until the octet can be stored in the buffer
216    /// (not necessarily that the octet has been transmitted).
217    ///
218    /// In some implementations, this can result in an Error.
219    /// If not, use `type Error = !`.
220    fn putc(&mut self, ch: u8) -> Result<(), Self::Error>;
221
222    /// Write a complete string to the UART.
223    /// If this returns `Ok(())`, all the data was sent.
224    /// Otherwise you get number of octets sent and the error.
225    fn puts<I: ?Sized>(&mut self, data: &I) -> Result<(), (usize, Self::Error)>
226        where I: AsRef<[u8]>
227    {
228        for (count, octet) in data.as_ref().iter().enumerate() {
229            self.putc(*octet).map_err(|e| (count, e))?;
230        }
231        Ok(())
232    }
233}
234
235/// Implementors of this trait offer octet based serial data transmission
236/// using a blocking API with an upper bound on blocking time, and requiring a
237/// mutable reference to self.
238pub trait MutBlockingTxWithTimeout {
239    /// The type used to specify the timeout.
240    type Timeout;
241    /// The error type returned if a function fails.
242    type Error;
243
244    /// Write a single octet to the port's transmitter, blocking until the
245    /// octet can be stored in the buffer (not necessarily that the
246    /// octet has been transmitted) or some timeout occurs.
247    ///
248    /// In some implementations, this can result in an Error.
249    /// If not, use `type Error = !`.
250    ///
251    /// If it times out, `Ok(None)` is returned.
252    /// If it sends the data, `Ok(Some(ch))` is returned.
253    /// If it fails, `Err(...)` is returned.
254    fn putc_wait(&mut self, ch: u8, timeout: &Self::Timeout) -> Result<Option<u8>, Self::Error>;
255
256    /// Attempts to write a complete string to the UART.
257    /// Returns number of octets written, or an error and the number of octets written.
258    /// The timeout applies to each octet individually.
259    ///
260    /// A result of `Ok(data.len())` means all the data was sent.
261    /// A result of `Ok(size < data.len())` means only some of the data was sent then there was a timeout.
262    /// A result of `Err(size, e)` means some (or all) of the data was sent then there was an error.
263    fn puts_wait<I: ?Sized>(&mut self,
264                            data: &I,
265                            timeout: &Self::Timeout)
266                            -> Result<usize, (usize, Self::Error)>
267        where I: AsRef<[u8]>
268    {
269        let mut count: usize = 0;
270        for octet in data.as_ref() {
271            // If we get an error, return it (with the number of bytes sent),
272            // else if we get None, we timed out so abort.
273            if self.putc_wait(*octet, timeout).map_err(|e| (count, e))?.is_none() {
274                break;
275            }
276            count += 1;
277        }
278        Ok(count)
279    }
280}
281
282/// Implementors of this trait offer octet based serial data transmission
283/// using a non-blocking API and requiring a mutable reference to self.
284pub trait MutNonBlockingTx {
285    /// The error type returned if function fails.
286    type Error;
287
288    /// Try and write a single octet to the port's transmitter.
289    /// Will return `Ok(None)` if the FIFO/buffer was full
290    /// and the octet couldn't be stored or `Ok(Some(ch))`
291    /// if it was stored OK.
292    ///
293    /// In some implementations, this can result in an Error.
294    /// If not, use `type Error = !`.
295    fn putc_try(&mut self, ch: u8) -> Result<Option<u8>, Self::Error>;
296
297    /// Write as much of a complete string to the UART as possible.
298    /// Returns the number of octets sent, plus the result from the
299    /// last `putc` call. Aborts early if `putc` fails in any way.
300    fn puts_try<I: ?Sized>(&mut self, data: &I) -> Result<usize, (usize, Self::Error)>
301        where I: AsRef<[u8]>
302    {
303        let mut count = 0;
304        for octet in data.as_ref() {
305            // If we get an error, return it (with the number of bytes sent),
306            // else if we get None, we timed out so abort.
307            if self.putc_try(*octet).map_err(|e| (count, e))?.is_none() {
308                break;
309            }
310            count += 1;
311        }
312        Ok(count)
313    }
314}
315
316/// Implementors of this trait offer octet based serial data reception
317/// using a blocking API and requiring a mutable reference to self.
318pub trait MutBlockingRx {
319    /// The error type returned if a function fails.
320    type Error;
321
322    /// Read a single octet from the port's receiver,
323    /// blocking until the octet can be read from the buffer.
324    ///
325    /// In some implementations, this can result in an Error.
326    /// If not, use `type Error = !`.
327    fn getc(&mut self) -> Result<u8, Self::Error>;
328
329    /// Read a specified number of octets into the given buffer, blocking
330    /// until that many have been read.
331    ///
332    /// In some implementations, this can result in an Error.
333    /// If not, use `type Error = !`.
334    fn gets<I: ?Sized>(&mut self, buffer: &mut I) -> Result<(), (usize, Self::Error)>
335        where I: AsMut<[u8]>
336    {
337        for (count, space) in buffer.as_mut().iter_mut().enumerate() {
338            *space = self.getc().map_err(|e| (count, e))?;
339        }
340        Ok(())
341    }
342}
343
344/// Implementors of this trait offer octet based serial data reception using a
345/// blocking API with an upper bound on blocking time, and requiring a mutable
346/// reference to self.
347pub trait MutBlockingRxWithTimeout {
348    /// The type used to specify the timeout.
349    type Timeout;
350    /// The error type returned if `getc` fails.
351    type Error;
352
353    /// Read a single octet from the port's receiver,
354    /// blocking until the octet can be read from the buffer.
355    ///
356    /// In some implementations, this can result in an Error.
357    /// If not, use `type Error = !`.
358    ///
359    /// If it times out, Ok(None) is returned.
360    /// If it receives data, Ok(Some(data)) is returned.
361    /// If it fails, Err(...) is returned.
362    fn getc_wait(&mut self, timeout: &Self::Timeout) -> Result<Option<u8>, Self::Error>;
363
364    /// Read a specified number of octets into the given buffer, blocking
365    /// until that many have been read or a timeout occurs.
366    ///
367    /// In some implementations, this can result in an Error.
368    /// If not, use `type Error = !`.
369    ///
370    /// If the result is `Ok(size)` but `size <= buffer.len()`, you had a timeout.
371    fn gets_wait<I: ?Sized>(&mut self,
372                            buffer: &mut I,
373                            timeout: &Self::Timeout)
374                            -> Result<usize, (usize, Self::Error)>
375        where I: AsMut<[u8]>
376    {
377        let mut count: usize = 0;
378        for space in buffer.as_mut() {
379            *space = match self.getc_wait(timeout) {
380                Err(e) => return Err((count, e)),
381                Ok(None) => return Ok(count),
382                Ok(Some(ch)) => ch,
383            };
384            count += 1;
385        }
386        Ok(count)
387    }
388}
389
390/// Implementors of this trait offer octet based serial data reception using a
391/// non-blocking API, and requiring a mutable reference to self.
392pub trait MutNonBlockingRx {
393    /// The error type returned if `getc` fails.
394    type Error;
395
396    /// Attempt to read a single octet from the port's receiver; if the buffer
397    /// is empty return None.
398    ///
399    /// In some implementations, this can result in an Error. If not, use
400    /// `type Error = !`.
401    ///
402    /// If it times out, Ok(None) is returned.
403    /// If it receives data, Ok(Some(data)) is returned.
404    /// If it fails, Err(...) is returned.
405    fn getc_try(&mut self) -> Result<Option<u8>, Self::Error>;
406
407    /// Read a specified number of octets into the given buffer, or until the
408    /// data runs out.
409    ///
410    /// In some implementations, this can result in an Error.
411    /// If not, use `type Error = !`.
412    ///
413    /// If the result is `Ok(size)` but `size <= buffer.len()`, you ran out of data.
414    fn gets_try<I: ?Sized>(&mut self, buffer: &mut I) -> Result<usize, (usize, Self::Error)>
415        where I: AsMut<[u8]>
416    {
417        let mut count: usize = 0;
418        for space in buffer.as_mut() {
419            *space = match self.getc_try() {
420                Err(e) => return Err((count, e)),
421                Ok(None) => return Ok(count),
422                Ok(Some(ch)) => ch,
423            };
424            count += 1;
425        }
426        Ok(count)
427    }
428}
429
430/// Implementors of this trait offer octet based serial data transmission
431/// using a blocking API and only requiring an immutable reference to self.
432pub trait ImmutBlockingTx {
433    /// The error type returned if a function fails.
434    type Error;
435
436    /// Write a single octet to the port's transmitter,
437    /// blocking until the octet can be stored in the buffer
438    /// (not necessarily that the octet has been transmitted).
439    ///
440    /// In some implementations, this can result in an Error.
441    /// If not, use `type Error = !`.
442    fn putc(&self, ch: u8) -> Result<(), Self::Error>;
443
444    /// Write a complete string to the UART.
445    /// If this returns `Ok(())`, all the data was sent.
446    /// Otherwise you get number of octets sent and the error.
447    fn puts<I: ?Sized>(&self, data: &I) -> Result<(), (usize, Self::Error)>
448        where I: AsRef<[u8]>
449    {
450        for (count, octet) in data.as_ref().iter().enumerate() {
451            self.putc(*octet).map_err(|e| (count, e))?;
452        }
453        Ok(())
454    }
455}
456
457/// Implementors of this trait offer octet based serial data transmission
458/// using a blocking API with an upper bound on blocking time, and requiring a
459/// mutable reference to self.
460pub trait ImmutBlockingTxWithTimeout {
461    /// The type used to specify the timeout.
462    type Timeout;
463    /// The error type returned if a function fails.
464    type Error;
465
466    /// Write a single octet to the port's transmitter, blocking until the
467    /// octet can be stored in the buffer (not necessarily that the
468    /// octet has been transmitted) or some timeout occurs.
469    ///
470    /// In some implementations, this can result in an Error.
471    /// If not, use `type Error = !`.
472    ///
473    /// If it times out, `Ok(None)` is returned.
474    /// If it sends the data, `Ok(Some(ch))` is returned.
475    /// If it fails, `Err(...)` is returned.
476    fn putc_wait(&self, ch: u8, timeout: &Self::Timeout) -> Result<Option<u8>, Self::Error>;
477
478    /// Attempts to write a complete string to the UART.
479    /// Returns number of octets written, or an error and the number of octets written.
480    /// The timeout applies to each octet individually.
481    ///
482    /// A result of `Ok(data.len())` means all the data was sent.
483    /// A result of `Ok(size < data.len())` means only some of the data was sent then there was a timeout.
484    /// A result of `Err(size, e)` means some (or all) of the data was sent then there was an error.
485    fn puts_wait<I: ?Sized>(&self,
486                            data: &I,
487                            timeout: &Self::Timeout)
488                            -> Result<usize, (usize, Self::Error)>
489        where I: AsRef<[u8]>
490    {
491        let mut count: usize = 0;
492        for octet in data.as_ref() {
493            // If we get an error, return it (with the number of bytes sent),
494            // else if we get None, we timed out so abort.
495            if self.putc_wait(*octet, timeout).map_err(|e| (count, e))?.is_none() {
496                break;
497            }
498            count += 1;
499        }
500        Ok(count)
501    }
502}
503
504/// Implementors of this trait offer octet based serial data transmission
505/// using a non-blocking API and requiring a mutable reference to self.
506pub trait ImmutNonBlockingTx {
507    /// The error type returned if function fails.
508    type Error;
509
510    /// Try and write a single octet to the port's transmitter.
511    /// Will return `Ok(None)` if the FIFO/buffer was full
512    /// and the octet couldn't be stored or `Ok(Some(ch))`
513    /// if it was stored OK.
514    ///
515    /// In some implementations, this can result in an Error.
516    /// If not, use `type Error = !`.
517    fn putc_try(&self, ch: u8) -> Result<Option<u8>, Self::Error>;
518
519    /// Write as much of a complete string to the UART as possible.
520    /// Returns the number of octets sent, plus the result from the
521    /// last `putc` call. Aborts early if `putc` fails in any way.
522    fn puts_try<I: ?Sized>(&self, data: &I) -> Result<usize, (usize, Self::Error)>
523        where I: AsRef<[u8]>
524    {
525        let mut count: usize = 0;
526        for octet in data.as_ref() {
527            // If we get an error, return it (with the number of bytes sent),
528            // else if we get None, we timed out so abort.
529            if self.putc_try(*octet).map_err(|e| (count, e))?.is_none() {
530                break;
531            }
532            count += 1;
533        }
534        Ok(count)
535    }
536}
537
538/// Implementors of this trait offer octet based serial data reception
539/// using a blocking API and requiring a mutable reference to self.
540pub trait ImmutBlockingRx {
541    /// The error type returned if a function fails.
542    type Error;
543
544    /// Read a single octet from the port's receiver,
545    /// blocking until the octet can be read from the buffer.
546    ///
547    /// In some implementations, this can result in an Error.
548    /// If not, use `type Error = !`.
549    fn getc(&self) -> Result<u8, Self::Error>;
550
551    /// Read a specified number of octets into the given buffer, blocking
552    /// until that many have been read.
553    ///
554    /// In some implementations, this can result in an Error.
555    /// If not, use `type Error = !`.
556    fn gets<I: ?Sized>(&self, buffer: &mut I) -> Result<(), (usize, Self::Error)>
557        where I: AsMut<[u8]>
558    {
559        for (count, space) in buffer.as_mut().iter_mut().enumerate() {
560            *space = self.getc().map_err(|e| (count, e))?;
561        }
562        Ok(())
563    }
564}
565
566/// Implementors of this trait offer octet based serial data reception using a
567/// blocking API with an upper bound on blocking time, and requiring a mutable
568/// reference to self.
569pub trait ImmutBlockingRxWithTimeout {
570    /// The type used to specify the timeout.
571    type Timeout;
572    /// The error type returned if `getc` fails.
573    type Error;
574
575    /// Read a single octet from the port's receiver,
576    /// blocking until the octet can be read from the buffer.
577    ///
578    /// In some implementations, this can result in an Error.
579    /// If not, use `type Error = !`.
580    ///
581    /// If it times out, Ok(None) is returned.
582    /// If it receives data, Ok(Some(data)) is returned.
583    /// If it fails, Err(...) is returned.
584    fn getc_wait(&self, timeout: &Self::Timeout) -> Result<Option<u8>, Self::Error>;
585
586    /// Read a specified number of octets into the given buffer, blocking
587    /// until that many have been read or a timeout occurs.
588    ///
589    /// In some implementations, this can result in an Error.
590    /// If not, use `type Error = !`.
591    ///
592    /// If the result is `Ok(size)` but `size <= buffer.len()`, you had a timeout.
593    fn gets_wait<I: ?Sized>(&self,
594                            buffer: &mut I,
595                            timeout: &Self::Timeout)
596                            -> Result<usize, (usize, Self::Error)>
597        where I: AsMut<[u8]>
598    {
599        let mut count: usize = 0;
600        for space in buffer.as_mut() {
601            *space = match self.getc_wait(timeout) {
602                Err(e) => return Err((count, e)),
603                Ok(None) => return Ok(count),
604                Ok(Some(ch)) => ch,
605            };
606            count += 1;
607        }
608        Ok(count)
609    }
610}
611
612/// Implementors of this trait offer octet based serial data reception using a
613/// non-blocking API, and requiring a mutable reference to self.
614pub trait ImmutNonBlockingRx {
615    /// The error type returned if `getc` fails.
616    type Error;
617
618    /// Attempt to read a single octet from the port's receiver; if the buffer
619    /// is empty return None.
620    ///
621    /// In some implementations, this can result in an Error. If not, use
622    /// `type Error = !`.
623    ///
624    /// If it times out, Ok(None) is returned.
625    /// If it receives data, Ok(Some(data)) is returned.
626    /// If it fails, Err(...) is returned.
627    fn getc_try(&self) -> Result<Option<u8>, Self::Error>;
628
629    /// Read a specified number of octets into the given buffer, or until the
630    /// data runs out.
631    ///
632    /// In some implementations, this can result in an Error.
633    /// If not, use `type Error = !`.
634    ///
635    /// If the result is `Ok(size)` but `size <= buffer.len()`, you ran out of data.
636    fn gets_try<I: ?Sized>(&self, buffer: &mut I) -> Result<usize, (usize, Self::Error)>
637        where I: AsMut<[u8]>
638    {
639        let mut count: usize = 0;
640        for space in buffer.as_mut() {
641            *space = match self.getc_try() {
642                Err(e) => return Err((count, e)),
643                Ok(None) => return Ok(count),
644                Ok(Some(ch)) => ch,
645            };
646            count += 1;
647        }
648        Ok(count)
649    }
650}
651
652// ****************************************************************************
653//
654// End Of File
655//
656// ****************************************************************************