1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use core;

use nb;
use heapless;

use hal::serial::Read;
use heapless::consts::*;
use heapless::spsc::Queue;
use heapless::String;

#[derive(Debug)]
pub enum Error{
    InvalidUTF8,
    InvalidCount,
    Overflow
}

pub struct Tokenizer<SLEN> where SLEN: heapless::ArrayLength<u8> {
    rb: Queue<u8, U64>,
    nextstr: String<SLEN>,
}

pub enum Token<'a> {
    NewLine,
    CarriageReturn,
    Equals,
    Space,
    Value(&'a str),
}

impl<SLEN> Tokenizer<SLEN>
where SLEN: heapless::ArrayLength<u8> {
    pub fn new() -> Self {
        Self {
            rb: Queue::new(),
            nextstr: String::new(),
        }
    }

    fn get_amount(&mut self, count : usize) -> nb::Result<char, Error> {
        if count > 4 {
            Err(nb::Error::Other(Error::InvalidCount))
        }
        else if self.rb.len() < count {
            Err(nb::Error::WouldBlock)
        } else {
            let mut v : u32 = 0;

            for _ in 0..count {
                let b = self.rb.dequeue().unwrap() as u32;

                if b >> 3 == 0b11110 {
                    v = (v << 3) | (b & 0b111)
                } else if b >> 4 == 0b1110 {
                    v = (v << 4) | (b & 0b1111)
                } else if b >> 5 == 0b110 {
                    v = (v << 5) | (b & 0b11111)
                } else if b >> 6 == 0b10 {
                    v = (v << 6) | (b & 0b111111)
                } else {
                    v = b
                }
            }
            Ok(core::char::from_u32(v).unwrap())
        }
    }

    fn get_char(&mut self) -> nb::Result<char, Error> {
        if self.rb.is_empty() {
            Err(nb::Error::WouldBlock)
        } else {
            let b = *self.rb.iter().next().unwrap();

            if b >> 3 == 0b11110 as u8 {
                Ok(self.get_amount(4).unwrap())
            } else if b >> 4 == 0b1110 as u8 {
                Ok(self.get_amount(3).unwrap())
            } else if b >> 5 == 0b110 as u8 {
                Ok(self.get_amount(2).unwrap())
            } else if b >> 6 == 0b10 as u8 {
                Err(nb::Error::Other(Error::InvalidUTF8))
            } else {
                Ok(self.rb.dequeue().unwrap() as char)
            }
        }
    } 

    pub fn get_tokens<CB>(&mut self, mut callback : CB) -> nb::Result<(), Error> 
        where CB: FnMut(Token) -> () {


        loop {
            let c = match self.get_char() { 
                Err(e) => {
                    return Err(e)
                },
                Ok(c) => c
            };

            let send_val = |callback: &mut CB, s: &mut String<SLEN>| {
                if !s.is_empty() {
                    callback(Token::Value(s))
                }
                s.clear();
            };

            match c {
                ' ' => {
                    send_val(&mut callback, &mut self.nextstr);
                    callback(Token::Space)
                },
                '=' => {
                    send_val(&mut callback, &mut self.nextstr);
                    callback(Token::Equals)
                },
                '\r' => {
                    send_val(&mut callback, &mut self.nextstr);
                    callback(Token::CarriageReturn)
                }
                '\n' => {
                    send_val(&mut callback, &mut self.nextstr);
                    callback(Token::NewLine)
                },
                _ => {
                    match self.nextstr.push(c) {
                        // if we aren't able to push a char onto the string
                        // it probably means it is full 
                        Err(_) => return Err(nb::Error::Other(Error::Overflow)),
                        _ => ()
                    }
                }
            };

        }
    }

    pub fn fill<E>(&mut self, ser: &mut Read<u8, Error=E>) -> nb::Result<(), E> {
        loop {
            let r = ser.read();
            match r {
                Err(nb::Error::WouldBlock) => return Ok(()),
                Err(e) => return Err(e),
                Ok(c) => self.rb.enqueue(c).unwrap()
            }
        }
    }
}