light_cli/
output.rs

1use core;
2
3use nb;
4use hal::serial::Write;
5
6use heapless::consts::*;
7use heapless::spsc::Queue;
8
9pub struct LightCliOutput<'a, E: 'a> {
10    rb: Queue<u8, U128>,
11    writer: &'a mut Write<u8, Error=E>
12}
13
14impl<'a, E> core::fmt::Write for LightCliOutput<'a, E> {
15    fn write_str(&mut self, s: &str) -> core::fmt::Result {
16        for c in s.as_bytes() {
17            loop {
18                if self.rb.enqueue(c.clone()).is_ok() {
19                    break;
20                } else {
21                    match self.flush() {
22                        Err(nb::Error::Other(_)) => return Err(core::fmt::Error),
23                        _ => () // otherwise either non blocking or ok, so try to repeat
24                    }
25                }
26            }
27        }
28        Ok(())
29    }
30}
31
32impl<'a, E> LightCliOutput<'a, E> {
33    /// Creates a now buffered console output instance. 
34    /// 
35    /// # Arguments
36    /// * `writer`: The serial output instance, implementing the [`Write<u8>`] interface.
37    /// 
38    /// [`Write<u8>`]: ../embedded_hal/serial/trait.Write.html
39    pub fn new(writer: &'a mut Write<u8, Error = E>) -> Self {
40        Self {
41            rb: Queue::new(),
42            writer: writer
43        }
44    }
45
46    fn peek(&self) -> Option<u8> {
47        match self.rb.iter().next() {
48            None => None,
49            Some(v) => Some(v.clone())
50        }
51    }
52
53    /// Tries to send as many characters as it can until the interface
54    /// starts blocking or there are no charactors to submit. 
55    /// 
56    /// # Remarks 
57    /// 
58    /// If the function returns Ok, then the buffer has succesfully been flushed
59    /// whereas the error `WouldBlock` indicates that it is not empty
60    /// but would have blocked if it tried to submit the character.
61    /// 
62    /// To completely empty the buffer, use `block!(cl_output.flush()).unwrap()`.
63    pub fn flush(&mut self) -> nb::Result<(), E> {
64        let mut co = self.peek();
65        
66        loop {
67            match co {
68                None => return Ok(()),
69                Some(c) => {
70                    let res = self.writer.write(c.clone());
71                    match res {
72                        Err(nb::Error::WouldBlock) => return Err(nb::Error::WouldBlock),
73                        Err(nb::Error::Other(o)) => return Err(nb::Error::Other(o)),
74                        Ok(()) => {
75                            self.rb.dequeue().unwrap();
76                            co = self.peek();
77                        },
78                    }
79                }
80            }
81        }
82    }
83}