es51986/
parser.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{Output, OUTPUT_LENGTH};
4
5/// Parse errors
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
7pub enum ParseError {
8    /// Length error. ES51986's data is 9 byte long followed by CRLF characters.
9    /// If the length is wrong, this error will be returned.
10    LengthError {
11        /// The length detected. If the data was '1234567890\r\n' then this 'len' will become 10.
12        len: usize
13    },
14    /// The first byte of the data is range. If the range byte is invalid, this error will be returned.
15    /// The u8 data is actual data byte.
16    InvalidRange(u8),
17    /// The 5th byte of the data is function. If the function is invalid, this error will be returned.
18    /// The u8 data is actual data byte.
19    InvalidFunction(u8),
20    /// The 1-4 byte of the data is digits. If the digits is invalid, this error will be returned.
21    /// The u8 data is actual data byte.
22    InvalidDigit(u8),
23}
24
25const CR: u8 = 0x0d;
26const LF: u8 = 0x0a;
27
28enum ParserState {
29    Idle,
30    FoundCr,
31}
32
33pub struct Parser {
34    state: ParserState,
35    buf: Vec<u8>,
36}
37
38impl Parser {
39    pub fn new() -> Self {
40        Self {
41            state: ParserState::Idle,
42            buf: vec![]
43        }
44    }
45    
46    fn parse_ch(&mut self, ch: u8) -> Result<Option<Output>, ParseError> {
47        match self.state {
48            ParserState::Idle => {
49                if ch == CR {
50                    self.state = ParserState::FoundCr;
51                    let result = Output::parse(&self.buf);
52                    self.buf.clear();
53                    result.map(|o| Some(o))
54                } else if ch == LF {
55                    self.state = ParserState::Idle;
56                    let result = Output::parse(&self.buf);
57                    self.buf.clear();
58                    result.map(|o| Some(o))
59                } else {
60                    self.buf.push(ch);
61                    let len = self.buf.len();
62                    if OUTPUT_LENGTH < len {
63                        let drain_amount = len - OUTPUT_LENGTH;
64                        self.buf.drain(..drain_amount);
65                        Err(ParseError::LengthError { len })
66                    } else {
67                        Ok(None)
68                    }
69                }
70            }
71            ParserState::FoundCr => {
72                if ch == LF {
73                    self.buf.clear();
74                    Ok(None)
75                } else {
76                    self.buf.push(ch);
77                    self.state = ParserState::Idle;
78                    Ok(None)
79                }
80            }
81        }
82    }
83    
84    /// Supply the data to the parser.
85    ///
86    /// The data to the parser is 11 bytes long that ends with CR (0x0d), LF (0x0a). 11 bytes may be given as a whole but you can supply smaller pieces (less than 11 bytes), or data exceeding 11 bytes may be given.
87    ///
88    /// # Argument
89    /// 
90    /// * 'input' - Data to parse.
91    /// 
92    ///
93    /// # Return value
94    /// 
95    /// Vector of parsed result.
96    /// 
97    /// # Examples
98    ///
99    /// Simple case.
100    /// ```
101    /// use es51986::{PrefixUnit, ValueUnit, BaseUnit};
102    /// 
103    /// let mut parser = es51986::parser::Parser::new();
104    /// let input: Vec<u8> = "00000;<0:\r\n".chars().map(|c| c as u8).collect();
105    /// let results = parser.parse(&input);
106    /// assert_eq!(results.len(), 1);
107    /// let output = results[0].as_ref().unwrap();
108    /// let value = output.get_value().unwrap();
109    /// assert_eq!(&value.digits, "0.000");
110    /// assert_eq!(value.value_unit, ValueUnit { prefix_unit: PrefixUnit::None, base_unit: BaseUnit::Volt});
111    /// ```
112    ///
113    /// You can supply smaller chunks of data.
114    /// ```
115    /// use es51986::{PrefixUnit, ValueUnit, BaseUnit};
116    /// 
117    /// let mut parser = es51986::parser::Parser::new();
118    /// let input: Vec<u8> = "01".chars().map(|c| c as u8).collect();
119    /// let results = parser.parse(&input);
120    ///  assert_eq!(results.len(), 0); // Data is not completed yet.
121    /// let input: Vec<u8> = "234;<0:\r\n".chars().map(|c| c as u8).collect();
122    /// let results = parser.parse(&input);
123    /// assert_eq!(results.len(), 1);
124    /// let output = results[0].as_ref().unwrap();
125    /// let value = output.get_value().unwrap();
126    /// assert_eq!(&value.digits, "1.234");
127    /// assert_eq!(value.value_unit, ValueUnit { prefix_unit: PrefixUnit::None, base_unit: BaseUnit::Volt});
128    /// ```
129    /// You can supply larger data that contains multiple data.
130    /// ```
131    /// use es51986::{PrefixUnit, ValueUnit, BaseUnit};
132    /// 
133    /// let mut parser = es51986::parser::Parser::new();
134    /// let input: Vec<u8> = "00000;<0:\r\n00000;<0:\r\n".chars().map(|c| c as u8).collect();
135    /// let results = parser.parse(&input);
136    /// assert_eq!(results.len(), 2);
137    /// let output = results[0].as_ref().unwrap();
138    /// let value = output.get_value().unwrap();
139    /// assert_eq!(&value.digits, "0.000");
140    /// assert_eq!(value.value_unit, ValueUnit { prefix_unit: PrefixUnit::None, base_unit: BaseUnit::Volt});
141    /// assert_eq!(results[0].as_ref().unwrap(), results[1].as_ref().unwrap());
142    /// ```
143    pub fn parse(&mut self, input: &[u8]) -> Vec<Result<Output, ParseError>> {
144        let mut results: Vec<Result<Output, ParseError>> = vec![];
145        for ch in input.iter() {
146            match self.parse_ch(*ch) {
147                Ok(Some(out)) => results.push(Ok(out)),
148                Ok(None) => {},
149                Err(err) => results.push(Err(err)),
150            }
151        }
152
153        results
154    }
155}