Add support for parsing arrays and nested arrays

next
Sayan Nandan 3 years ago
parent 53cad270fc
commit 14bfe1fcd1

@ -62,6 +62,7 @@ pub enum Query {
PipelinedQuery(Vec<ActionGroup>),
}
#[derive(Debug, PartialEq)]
#[non_exhaustive]
pub enum DataType {
/// Arrays can be nested! Their `<tsymbol>` is `&`
@ -259,7 +260,7 @@ impl<'a> Parser<'a> {
/// Get the next element **without** the tsymbol
///
/// This function **does not forward the newline**
fn __parse_next_element(&mut self) -> ParseResult<&[u8]> {
fn __get_next_element(&mut self) -> ParseResult<&[u8]> {
let string_sizeline = self.read_line();
let string_size =
Self::parse_into_usize(&self.buffer[string_sizeline.0..string_sizeline.1])?;
@ -268,7 +269,7 @@ impl<'a> Parser<'a> {
}
/// The cursor should have passed the `+` tsymbol
fn parse_next_string(&mut self) -> ParseResult<String> {
let our_string_chunk = self.__parse_next_element()?;
let our_string_chunk = self.__get_next_element()?;
let our_string = String::from_utf8_lossy(&our_string_chunk).to_string();
if self.will_cursor_give_linefeed()? {
// there is a lf after the end of the string; great!
@ -282,16 +283,45 @@ impl<'a> Parser<'a> {
}
/// The cursor should have passed the `:` tsymbol
fn parse_next_u64(&mut self) -> ParseResult<u64> {
let our_u64_chunk = self.__parse_next_element()?;
let our_u64_chunk = self.__get_next_element()?;
let our_u64 = Self::parse_into_u64(our_u64_chunk)?;
if self.will_cursor_give_linefeed()? {
// line feed after u64; heck yeah!
self.incr_cursor();
// return it
Ok(our_u64)
} else {
Err(ParseError::UnexpectedByte)
}
}
/// The cursor should be **at the tsymbol**
fn parse_next_element(&mut self) -> ParseResult<DataType> {
if let Some(tsymbol) = self.buffer.get(self.cursor) {
// so we have a tsymbol; nice, let's match it
// but advance the cursor before doing that
self.incr_cursor();
let ret = match *tsymbol {
b'+' => DataType::String(self.parse_next_string()?),
b':' => DataType::UnsignedInt(self.parse_next_u64()?),
b'&' => DataType::Array(self.parse_next_array()?),
_ => return Err(ParseError::UnknownDatatype),
};
Ok(ret)
} else {
// Not enough bytes to read an element
Err(ParseError::NotEnough)
}
}
/// The tsymbol `&` should have been passed!
fn parse_next_array(&mut self) -> ParseResult<Vec<DataType>> {
let (start, stop) = self.read_line();
let array_size = Self::parse_into_usize(&self.buffer[start..stop])?;
let mut array = Vec::with_capacity(array_size);
for _ in 0..array_size {
array.push(self.parse_next_element()?);
}
Ok(array)
}
/// This will read a datagroup element and return an **owned vector** containing the bytes
/// for the next datagroup element
fn parse_next_datagroup_element(&mut self) -> ParseResult<Vec<u8>> {
@ -577,3 +607,86 @@ fn test_parse_next_u64() {
let our_u64 = Parser::new(&bytes).parse_next_u64().unwrap_err();
assert_eq!(our_u64, ParseError::DataTypeParseError);
}
#[test]
fn test_parse_next_element_string() {
let bytes = "+5\nsayan\n".as_bytes();
let next_element = Parser::new(&bytes).parse_next_element().unwrap();
assert_eq!(next_element, DataType::String("sayan".to_owned()));
}
#[test]
fn test_parse_next_element_u64() {
let bytes = ":20\n18446744073709551615\n".as_bytes();
let our_u64 = Parser::new(&bytes).parse_next_element().unwrap();
assert_eq!(our_u64, DataType::UnsignedInt(u64::MAX));
}
#[test]
fn test_parse_next_element_array() {
let bytes = "&3\n+4\nMGET\n+3\nfoo\n+3\nbar\n".as_bytes();
let mut parser = Parser::new(&bytes);
let array = parser.parse_next_element().unwrap();
assert_eq!(
array,
DataType::Array(vec![
DataType::String("MGET".to_owned()),
DataType::String("foo".to_owned()),
DataType::String("bar".to_owned())
])
);
assert_eq!(parser.cursor, bytes.len());
}
#[test]
fn test_parse_nested_array() {
// let's test a nested array
let bytes =
"&3\n+3\nACT\n+3\nfoo\n&4\n+5\nsayan\n+2\nis\n+7\nworking\n&2\n+6\nreally\n+4\nhard\n"
.as_bytes();
let mut parser = Parser::new(&bytes);
let array = parser.parse_next_element().unwrap();
assert_eq!(
array,
DataType::Array(vec![
DataType::String("ACT".to_owned()),
DataType::String("foo".to_owned()),
DataType::Array(vec![
DataType::String("sayan".to_owned()),
DataType::String("is".to_owned()),
DataType::String("working".to_owned()),
DataType::Array(vec![
DataType::String("really".to_owned()),
DataType::String("hard".to_owned())
])
])
])
);
assert_eq!(parser.cursor, bytes.len());
}
#[test]
fn test_parse_multitype_array() {
// let's test a nested array
let bytes = "&3\n+3\nACT\n+3\nfoo\n&4\n+5\nsayan\n+2\nis\n+7\nworking\n&2\n:2\n23\n+5\napril\n"
.as_bytes();
let mut parser = Parser::new(&bytes);
let array = parser.parse_next_element().unwrap();
assert_eq!(
array,
DataType::Array(vec![
DataType::String("ACT".to_owned()),
DataType::String("foo".to_owned()),
DataType::Array(vec![
DataType::String("sayan".to_owned()),
DataType::String("is".to_owned()),
DataType::String("working".to_owned()),
DataType::Array(vec![
DataType::UnsignedInt(23),
DataType::String("april".to_owned())
])
])
])
);
assert_eq!(parser.cursor, bytes.len());
}

Loading…
Cancel
Save