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// ****************************************************************************