use crate::common::sized_buffer::Error as SizedBufferError; use crate::common::sized_buffer::SizedBuffer; use std::fmt; #[derive(Debug)] pub enum Error { ExpectedArray(char), ExpectedString(char), InvalidLength, Buffer(SizedBufferError), } #[derive(Debug)] pub enum State { Wait, Done(Vec>), } pub struct Parser { pub argv: Vec>, argc_rem: u64, arg_len: i64, } impl Parser { pub fn new() -> Self { Self { argv: Vec::new(), argc_rem: 0, arg_len: -1, } } pub fn parse( &mut self, buffer: &mut SizedBuffer<[u8; N]>, ) -> Result { if self.argc_rem == 0 { assert_eq!(self.arg_len, -1); /* argc_rem wasn't initialized yet. The current buffer was never read, we need to * figure out the number of args. */ if buffer.peek() != b'*' { return Err(Error::ExpectedArray(buffer.peek() as char)); } let arr_lf_offset = match buffer.find_offset(b'\n') { Some(offset) => offset, /* Couldn't find \n, wait for more data */ None => return Ok(State::Wait), }; self.argc_rem = read_data_len(buffer, arr_lf_offset)? as u64; buffer.skip_byte(b'\n').map_err(Error::Buffer)?; } /* We already started reading a command. We can process the arguments. */ while self.argc_rem > 0 { /* arg_len wasn't initialized yet. We need to find the size of the string argument. */ if self.arg_len == -1 { if buffer.peek() != b'$' { return Err(Error::ExpectedString(buffer.peek() as char)); } let str_lf_offset = match buffer.find_offset(b'\n') { Some(offset) => offset, /* Couldn't find \n, wait for more data */ None => return Ok(State::Wait), }; self.arg_len = read_data_len(buffer, str_lf_offset)? as i64; buffer.skip_byte(b'\n').map_err(Error::Buffer)?; } else { match buffer.read_count(self.arg_len as usize) { /* Not enough data, wait for more */ Err(_) => return Ok(State::Wait), /* Push the new string onto the args list */ Ok(arg) => self.argv.push(arg.to_vec()), } buffer.skip_byte(b'\n').map_err(Error::Buffer)?; self.argc_rem -= 1; self.arg_len = -1; } } let argv = self.argv.clone(); self.argv.clear(); Ok(State::Done(argv)) } } fn read_data_len( buffer: &mut SizedBuffer<[u8; N]>, n: usize, ) -> Result { /* Read from 1 to skip the data tag */ let mut len: usize = 0; for (i, x) in buffer.read_count_unchecked(n)[1..].iter().rev().enumerate() { if *x < 48 || *x > 57 { return Err(Error::InvalidLength); } len += (x - 48) as usize * 10usize.pow(i as u32); } Ok(len) } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let res = match self { Error::ExpectedArray(got) => format!("Expected array, got {:?}.", *got as char), Error::ExpectedString(got) => format!("Expected string, got {:?}.", *got as char), Error::InvalidLength => "Invalid header size.".to_string(), Error::Buffer(err) => format!("Error read or writing to/from the buffer: {err:?}"), }; write!(f, "{}", res) } }