diff --git a/server/src/protocol/mod.rs b/server/src/protocol/mod.rs index ec06033f..8553a336 100644 --- a/server/src/protocol/mod.rs +++ b/server/src/protocol/mod.rs @@ -164,27 +164,27 @@ impl UnsafeSlice { } } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq)] #[repr(u8)] /// # Parser Errors /// /// Several errors can arise during parsing and this enum accounts for them pub enum ParseError { /// Didn't get the number of expected bytes - NotEnough = 0, + NotEnough = 0u8, /// The packet simply contains invalid data - BadPacket = 1, + BadPacket = 1u8, /// The query contains an unexpected byte - UnexpectedByte = 2, + UnexpectedByte = 2u8, /// A data type was given but the parser failed to serialize it into this type /// /// This can happen not just for elements but can also happen for their sizes ([`Self::parse_into_u64`]) - DatatypeParseFailure = 3, + DatatypeParseFailure = 3u8, /// A data type that the server doesn't know was passed into the query /// /// This is a frequent problem that can arise between different server editions as more data types /// can be added with changing server versions - UnknownDatatype = 4, + UnknownDatatype = 4u8, } #[derive(Debug, PartialEq)] diff --git a/server/src/protocol/v2/mod.rs b/server/src/protocol/v2/mod.rs index c79843d7..5df9d814 100644 --- a/server/src/protocol/v2/mod.rs +++ b/server/src/protocol/v2/mod.rs @@ -28,10 +28,11 @@ use crate::corestore::heap_array::HeapArray; use crate::protocol::{ParseError, ParseResult, UnsafeSlice}; -use core::marker::PhantomData; +use core::{marker::PhantomData, mem::transmute}; #[cfg(test)] mod tests; +#[derive(Debug)] pub struct Query { forward: usize, data: QueryType, @@ -43,11 +44,13 @@ impl Query { } } +#[derive(Debug)] pub enum QueryType { Simple(SimpleQuery), Pipelined(PipelinedQuery), } +#[derive(Debug)] pub struct SimpleQuery { data: HeapArray, } @@ -70,6 +73,7 @@ struct OwnedSimpleQuery { data: Vec>, } +#[derive(Debug)] pub struct PipelinedQuery { data: HeapArray>, } @@ -207,7 +211,7 @@ impl<'a> Parser<'a> { Ok(UnsafeSlice::new(start_ptr, len)) } else { // just some silly hackery - Err(*(&(1 & has_lf as u8) as *const u8 as *const ParseError)) + Err(transmute(has_lf)) } } } @@ -312,7 +316,8 @@ impl<'a> Parser<'a> { unsafe { let mut queries = HeapArray::with_capacity(query_count); for i in 0..query_count { - queries.write_to_index(i, self._next_simple_query()?); + let sq = self._next_simple_query()?; + queries.write_to_index(i, sq); } Ok(PipelinedQuery { data: queries }) } diff --git a/server/src/protocol/v2/tests.rs b/server/src/protocol/v2/tests.rs index 8ec14f98..284b2edf 100644 --- a/server/src/protocol/v2/tests.rs +++ b/server/src/protocol/v2/tests.rs @@ -563,6 +563,15 @@ fn read_usize_fail() { ); } +#[test] +fn parse_fail_because_unknown_query_scheme() { + let body = v!(b"?3\n3\nSET1\nx3\n100"); + assert_eq!( + Parser::parse(&body).unwrap_err(), + ParseError::UnexpectedByte + ) +} + #[test] fn simple_query_okay() { let body = v!(b"*3\n3\nSET1\nx3\n100"); @@ -571,6 +580,21 @@ fn simple_query_okay() { let query = simple_query(ret); assert_eq!(query.into_owned().data, v!["SET", "x", "100"]); } +#[test] +fn parse_fail_because_not_enough() { + let full_payload = b"*3\n3\nSET1\nx3\n100"; + let samples: Vec> = (0..full_payload.len() - 1) + .map(|i| full_payload.iter().take(i).cloned().collect()) + .collect(); + for body in samples { + assert_eq!( + Parser::parse(&body).unwrap_err(), + ParseError::NotEnough, + "Failed with body len: {}", + body.len() + ) + } +} #[test] fn pipelined_query_okay() { @@ -583,3 +607,15 @@ fn pipelined_query_okay() { vec![v!["SET", "x", "100"], v!["GET", "x"]] ) } + +#[test] +fn pipelined_query_fail_because_not_enough() { + let full_payload = v!(b"$2\n3\n3\nSET1\nx3\n1002\n3\nGET1\nx"); + let samples: Vec> = (0..full_payload.len() - 1) + .map(|i| full_payload.iter().cloned().take(i).collect()) + .collect(); + for body in samples { + let ret = Parser::parse(&body).unwrap_err(); + assert_eq!(ret, ParseError::NotEnough) + } +}