diff --git a/src/lib.rs b/src/lib.rs index ed1d883..a0d5416 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ //! //! let b: i32 = -111; //! let encoded_byte_vec = b.encode_var_vec(); -//! assert_eq!((b, 2), i32::decode_var(&encoded_byte_vec)); +//! assert_eq!(Some((b, 2)), i32::decode_var(&encoded_byte_vec)); //! } //! ``` @@ -29,14 +29,14 @@ pub use varint::VarInt; #[cfg(any(feature = "tokio_async", feature = "futures_async"))] pub use reader::FixedIntAsyncReader; +pub use reader::FixedIntReader; #[cfg(any(feature = "tokio_async", feature = "futures_async"))] pub use reader::VarIntAsyncReader; -pub use reader::FixedIntReader; pub use reader::VarIntReader; #[cfg(any(feature = "tokio_async", feature = "futures_async"))] pub use writer::FixedIntAsyncWriter; +pub use writer::FixedIntWriter; #[cfg(any(feature = "tokio_async", feature = "futures_async"))] pub use writer::VarIntAsyncWriter; -pub use writer::FixedIntWriter; pub use writer::VarIntWriter; diff --git a/src/reader.rs b/src/reader.rs index 80b79ed..0fa90e9 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -50,10 +50,10 @@ impl VarIntProcessor { Ok(()) } fn finished(&self) -> bool { - (self.i > 0 && (self.buf[self.i - 1] & MSB == 0)) + self.i > 0 && (self.buf[self.i - 1] & MSB == 0) } - fn decode(&self) -> VI { - VI::decode_var(&self.buf[0..self.i]).0 + fn decode(&self) -> Option { + Some(VI::decode_var(&self.buf[0..self.i])?.0) } } @@ -101,7 +101,7 @@ impl VarIntReader for R { p.push(buf[0])?; } - Ok(p.decode()) + p.decode().ok_or_else(|| io::Error::new(io::ErrorKind::UnexpectedEof, "Reached EOF")) } } diff --git a/src/varint.rs b/src/varint.rs index 6622f3b..c51668a 100644 --- a/src/varint.rs +++ b/src/varint.rs @@ -1,4 +1,3 @@ - /// Most-significant byte, == 0x80 pub const MSB: u8 = 0b1000_0000; const DROP_MSB: u8 = 0b0111_1111; @@ -31,7 +30,8 @@ pub trait VarInt: Sized + Copy { fn required_space(self) -> usize; /// Decode a value from the slice. Returns the value and the number of bytes read from the /// slice (can be used to read several consecutive values from a big slice) - fn decode_var(src: &[u8]) -> (Self, usize); + /// return None if all bytes has MSB set. + fn decode_var(src: &[u8]) -> Option<(Self, usize)>; /// Encode a value into the slice. The slice must be at least `required_space()` bytes long. /// The number of bytes taken by the encoded integer is returned. fn encode_var(self, src: &mut [u8]) -> usize; @@ -66,9 +66,9 @@ macro_rules! impl_varint { required_encoded_space_unsigned(self as u64) } - fn decode_var(src: &[u8]) -> (Self, usize) { - let (n, s) = u64::decode_var(src); - (n as Self, s) + fn decode_var(src: &[u8]) -> Option<(Self, usize)> { + let (n, s) = u64::decode_var(src)?; + Some((n as Self, s)) } fn encode_var(self, dst: &mut [u8]) -> usize { @@ -82,9 +82,9 @@ macro_rules! impl_varint { required_encoded_space_signed(self as i64) } - fn decode_var(src: &[u8]) -> (Self, usize) { - let (n, s) = i64::decode_var(src); - (n as Self, s) + fn decode_var(src: &[u8]) -> Option<(Self, usize)> { + let (n, s) = i64::decode_var(src)?; + Some((n as Self, s)) } fn encode_var(self, dst: &mut [u8]) -> usize { @@ -112,10 +112,16 @@ impl VarInt for u64 { required_encoded_space_unsigned(self) } - fn decode_var(src: &[u8]) -> (Self, usize) { + fn decode_var(src: &[u8]) -> Option<(Self, usize)> { let mut result: u64 = 0; let mut shift = 0; + if let Some(b) = src.last() { + if b & MSB != 0 { + return None; + } + } + for b in src.iter() { let msb_dropped = b & DROP_MSB; result |= (msb_dropped as u64) << shift; @@ -126,7 +132,7 @@ impl VarInt for u64 { } } - (result, shift / 7 as usize) + Some((result, shift / 7 as usize)) } #[inline] @@ -142,7 +148,7 @@ impl VarInt for u64 { } dst[i] = n as u8; - i+1 + i + 1 } } @@ -151,10 +157,16 @@ impl VarInt for i64 { required_encoded_space_signed(self) } - fn decode_var(src: &[u8]) -> (Self, usize) { + fn decode_var(src: &[u8]) -> Option<(Self, usize)> { let mut result: u64 = 0; let mut shift = 0; + if let Some(b) = src.last() { + if b & MSB != 0 { + return None; + } + } + for b in src.iter() { let msb_dropped = b & DROP_MSB; result |= (msb_dropped as u64) << shift; @@ -165,7 +177,7 @@ impl VarInt for i64 { } } - (zigzag_decode(result) as Self, shift / 7 as usize) + Some((zigzag_decode(result) as Self, shift / 7 as usize)) } #[inline] @@ -181,6 +193,6 @@ impl VarInt for i64 { } dst[i] = n as u8; - i+1 + i + 1 } } diff --git a/src/varint_tests.rs b/src/varint_tests.rs index b1306aa..8f0c73c 100644 --- a/src/varint_tests.rs +++ b/src/varint_tests.rs @@ -28,10 +28,10 @@ mod tests { #[test] fn test_identity_u64() { for i in 1 as u64..100 { - assert_eq!(u64::decode_var(i.encode_var_vec().as_slice()), (i, 1)); + assert_eq!(u64::decode_var(i.encode_var_vec().as_slice()).unwrap(), (i, 1)); } for i in 16400 as u64..16500 { - assert_eq!(u64::decode_var(&i.encode_var_vec().as_slice()), (i, 3)); + assert_eq!(u64::decode_var(&i.encode_var_vec().as_slice()).unwrap(), (i, 3)); } } @@ -39,7 +39,7 @@ mod tests { fn test_decode_max_u64() { let max_vec_encoded = vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01]; assert_eq!( - u64::decode_var(max_vec_encoded.as_slice()).0, + u64::decode_var(max_vec_encoded.as_slice()).unwrap().0, u64::max_value() ); } @@ -70,7 +70,7 @@ mod tests { fn test_decode_min_i64() { let min_vec_encoded = vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01]; assert_eq!( - i64::decode_var(min_vec_encoded.as_slice()).0, + i64::decode_var(min_vec_encoded.as_slice()).unwrap().0, i64::min_value() ); } @@ -79,7 +79,7 @@ mod tests { fn test_decode_max_i64() { let max_vec_encoded = vec![0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01]; assert_eq!( - i64::decode_var(max_vec_encoded.as_slice()).0, + i64::decode_var(max_vec_encoded.as_slice()).unwrap().0, i64::max_value() ); } @@ -158,6 +158,6 @@ mod tests { fn test_unterminated_varint_2() { let buf = [0xff, 0xff]; let mut read = &buf[..]; - assert_eq!(16383, read.read_varint::().unwrap()); + assert!(read.read_varint::().is_err()); } }