use core::convert::TryFrom;
pub use super::DecoderError;
use crate::{Typ, Encoder};
pub fn decode_varint(buf: &[u8], dst: &mut u64) -> Result<usize, DecoderError> {
let mut value: u64 = 0;
let mut count = 0;
loop {
let byte = match buf.get(count) {
Some(b) => *b,
None => return Err(DecoderError::InputUnderflow),
};
value |= u64::from(byte & 0x7F) << (7 * count);
count += 1;
if byte <= 0x7F {
*dst = value;
return Ok(count);
}
}
}
pub fn decode_key(
buf: &[u8],
dst: &mut (u32, Typ),
) -> Result<usize, DecoderError> {
let mut key = 0;
let size = decode_varint(buf, &mut key)?;
if key > u64::from(u32::MAX) {
return Err(DecoderError::InvalidInput);
}
let typ = Typ::try_from(key & 0x07)?;
let tag = key as u32 >> 3;
if tag < Encoder::TAG_MIN {
return Err(DecoderError::InvalidInput);
} else if typ == Typ::Unknown {
return Err(DecoderError::InvalidInput);
}
*dst = (tag, typ);
Ok(size)
}
pub fn decode_bool(buf: &[u8], dst: &mut bool) -> Result<usize, DecoderError> {
let mut val = 0;
let size = decode_varint(buf, &mut val)?;
*dst = if val == 0u64 { false } else { true };
Ok(size)
}
pub fn decode_bool_vec(
buf: &[u8],
dst: &mut Vec<bool>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = false;
size += decode_bool(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_int32(buf: &[u8], dst: &mut i32) -> Result<usize, DecoderError> {
let mut val = 0;
let size = decode_varint(buf, &mut val)?;
*dst = val as i32;
Ok(size)
}
pub fn decode_int32_vec(
buf: &[u8],
dst: &mut Vec<i32>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0;
size += decode_int32(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_int64(buf: &[u8], dst: &mut i64) -> Result<usize, DecoderError> {
let mut val = 0;
let size = decode_varint(buf, &mut val)?;
*dst = val as i64;
Ok(size)
}
pub fn decode_int64_vec(
buf: &[u8],
dst: &mut Vec<i64>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0;
size += decode_int64(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_uint32(buf: &[u8], dst: &mut u32) -> Result<usize, DecoderError> {
let mut val = 0;
let size = decode_varint(buf, &mut val)?;
*dst = val as u32;
Ok(size)
}
pub fn decode_uint32_vec(
buf: &[u8],
dst: &mut Vec<u32>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0;
size += decode_uint32(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_uint64(buf: &[u8], dst: &mut u64) -> Result<usize, DecoderError> {
decode_varint(buf, dst)
}
pub fn decode_uint64_vec(
buf: &[u8],
dst: &mut Vec<u64>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0;
size += decode_varint(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_sint32(buf: &[u8], dst: &mut i32) -> Result<usize, DecoderError> {
let mut val = 0;
let size = decode_varint(buf, &mut val)?;
*dst = ((val >> 1) as i32) ^ (-((val & 1) as i32));
Ok(size)
}
pub fn decode_sint32_vec(
buf: &[u8],
dst: &mut Vec<i32>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0;
size += decode_sint32(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_sint64(buf: &[u8], dst: &mut i64) -> Result<usize, DecoderError> {
let mut val = 0;
let size = decode_varint(buf, &mut val)?;
*dst = ((val >> 1) as i64) ^ (-((val & 1) as i64));
Ok(size)
}
pub fn decode_sint64_vec(
buf: &[u8],
dst: &mut Vec<i64>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0;
size += decode_sint64(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_fixed32(
buf: &[u8],
dst: &mut u32,
) -> Result<usize, DecoderError> {
if buf.len() < 4 {
return Err(DecoderError::InputUnderflow)
}
let mut bytes = [0u8; 4];
bytes.clone_from_slice(&buf[0..4]);
*dst = u32::from_le_bytes(bytes);
Ok(4)
}
pub fn decode_fixed32_vec(
buf: &[u8],
dst: &mut Vec<u32>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0;
size += decode_fixed32(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_fixed64(
buf: &[u8],
dst: &mut u64,
) -> Result<usize, DecoderError> {
if buf.len() < 8 {
return Err(DecoderError::InputUnderflow)
}
let mut bytes = [0u8; 8];
bytes.clone_from_slice(&buf[0..8]);
*dst = u64::from_le_bytes(bytes);
Ok(8)
}
pub fn decode_fixed64_vec(
buf: &[u8],
dst: &mut Vec<u64>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0;
size += decode_fixed64(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_sfixed32(
buf: &[u8],
dst: &mut i32,
) -> Result<usize, DecoderError> {
if buf.len() < 4 {
return Err(DecoderError::InputUnderflow)
}
let mut bytes = [0u8; 4];
bytes.clone_from_slice(&buf[0..4]);
*dst = i32::from_le_bytes(bytes);
Ok(4)
}
pub fn decode_sfixed32_vec(
buf: &[u8],
dst: &mut Vec<i32>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0;
size += decode_sfixed32(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_sfixed64(
buf: &[u8],
dst: &mut i64,
) -> Result<usize, DecoderError> {
if buf.len() < 8 {
return Err(DecoderError::InputUnderflow)
}
let mut bytes = [0u8; 8];
bytes.clone_from_slice(&buf[0..8]);
*dst = i64::from_le_bytes(bytes);
Ok(8)
}
pub fn decode_sfixed64_vec(
buf: &[u8],
dst: &mut Vec<i64>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0;
size += decode_sfixed64(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_float(buf: &[u8], dst: &mut f32) -> Result<usize, DecoderError> {
if buf.len() < 4 {
return Err(DecoderError::InputUnderflow)
}
let mut bytes = [0u8; 4];
bytes.clone_from_slice(&buf[0..4]);
*dst = f32::from_le_bytes(bytes);
Ok(4)
}
pub fn decode_float_vec(
buf: &[u8],
dst: &mut Vec<f32>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0.0;
size += decode_float(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn decode_double(buf: &[u8], dst: &mut f64) -> Result<usize, DecoderError> {
if buf.len() < 8 {
return Err(DecoderError::InputUnderflow)
}
let mut bytes = [0u8; 8];
bytes.clone_from_slice(&buf[0..8]);
*dst = f64::from_le_bytes(bytes);
Ok(8)
}
pub fn decode_double_vec(
buf: &[u8],
dst: &mut Vec<f64>,
) -> Result<usize, DecoderError> {
let total = buf.len();
let mut size = 0;
let mut items = vec![];
while total > size || total == 0 {
let mut val = 0.0;
size += decode_double(&buf[size..], &mut val)?;
items.push(val);
}
dst.append(&mut items);
Ok(size)
}
pub fn extract_varint(
buf: &[u8],
dst: &mut Vec<u8>,
) -> Result<usize, DecoderError> {
let mut bytes = vec![];
let mut count = 0;
loop {
let byte = match buf.get(count) {
Some(b) => *b,
None => return Err(DecoderError::InputUnderflow),
};
bytes.push(byte.clone());
count += 1;
if byte <= 0x7F {
dst.append(&mut bytes);
return Ok(count);
}
}
}
pub fn extract_bit32(
buf: &[u8],
dst: &mut Vec<u8>,
) -> Result<usize, DecoderError> {
if buf.len() < 4 {
return Err(DecoderError::InputUnderflow);
}
dst.append(&mut buf[0..4].to_vec());
Ok(4)
}
pub fn extract_bit64(
buf: &[u8],
dst: &mut Vec<u8>,
) -> Result<usize, DecoderError> {
if buf.len() < 8 {
return Err(DecoderError::InputUnderflow);
}
dst.append(&mut buf[0..8].to_vec());
Ok(8)
}
pub fn extract_ld(
buf: &[u8],
size: u64,
dst: &mut Vec<u8>,
) -> Result<usize, DecoderError> {
let size = size as usize;
if buf.len() < size {
return Err(DecoderError::InputUnderflow);
}
dst.append(&mut buf[0..size].to_vec());
Ok(size)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn decodes_varints() {
let mut dst = 0;
let buf = vec![0xb9];
assert!(decode_varint(&buf, &mut dst).is_err());
let buf = vec![0xb9, 0x60, 0x85];
let size = decode_varint(&buf, &mut dst).unwrap();
assert_eq!(dst, 12345);
assert_eq!(size, 2);
let buf = vec![0x85, 0x35, 0x85];
let size = decode_varint(&buf, &mut dst).unwrap();
assert_eq!(dst, 6789);
assert_eq!(size, 2);
}
#[test]
fn decodes_key() {
let mut dst = (0, Typ::Unknown);
let buf = vec![0xcd, 0x83, 0x06, 0xaa];
let size = decode_key(&buf, &mut dst).unwrap();
assert_eq!(dst.0, 12345);
assert_eq!(dst.1, Typ::Bit32);
assert_eq!(size, 3);
let buf = vec![0xaa, 0xa8, 0x03, 0x03];
let size = decode_key(&buf, &mut dst).unwrap();
assert_eq!(dst.0, 6789);
assert_eq!(dst.1, Typ::LengthDelimited);
assert_eq!(size, 3);
}
#[test]
fn decodes_bool() {
let mut dst = true;
let buf = vec![0x00];
let size = decode_bool(&buf, &mut dst).unwrap();
assert_eq!(dst, false);
assert_eq!(size, 1);
let buf = vec![0x01];
let size = decode_bool(&buf, &mut dst).unwrap();
assert_eq!(dst, true);
assert_eq!(size, 1);
}
#[test]
fn decodes_int32() {
let mut dst = 0;
let buf = vec![0x80, 0x80, 0x80, 0x80, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff];
let size = decode_int32(&buf, &mut dst).unwrap();
assert_eq!(dst, i32::MIN);
assert_eq!(size, 10);
let buf = vec![0xff, 0xff, 0xff, 0xff, 0x07];
let size = decode_int32(&buf, &mut dst).unwrap();
assert_eq!(dst, i32::MAX);
assert_eq!(size, 5);
}
#[test]
fn decodes_int64() {
let mut dst = 0;
let buf = vec![0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01];
let size = decode_int64(&buf, &mut dst).unwrap();
assert_eq!(dst, i64::MIN);
assert_eq!(size, 10);
let buf = vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f];
let size = decode_int64(&buf, &mut dst).unwrap();
assert_eq!(dst, i64::MAX);
assert_eq!(size, 9);
}
#[test]
fn decodes_uint32() {
let mut dst = 0;
let buf = vec![0x00];
let size = decode_uint32(&buf, &mut dst).unwrap();
assert_eq!(dst, u32::MIN);
assert_eq!(size, 1);
let buf = vec![0xff, 0xff, 0xff, 0xff, 0x0f];
let size = decode_uint32(&buf, &mut dst).unwrap();
assert_eq!(dst, u32::MAX);
assert_eq!(size, 5);
}
#[test]
fn decodes_uint64() {
let mut dst = 0;
let buf = vec![0x00];
let size = decode_uint64(&buf, &mut dst).unwrap();
assert_eq!(dst, u64::MIN);
assert_eq!(size, 1);
let buf = vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01];
let size = decode_uint64(&buf, &mut dst).unwrap();
assert_eq!(dst, u64::MAX);
assert_eq!(size, 10);
}
#[test]
fn decodes_sint32() {
let mut dst = 0;
let buf = vec![0xff, 0xff, 0xff, 0xff, 0x0f];
let size = decode_sint32(&buf, &mut dst).unwrap();
assert_eq!(dst, i32::MIN);
assert_eq!(size, 5);
let buf = vec![0xfe, 0xff, 0xff, 0xff, 0x0f];
let size = decode_sint32(&buf, &mut dst).unwrap();
assert_eq!(dst, i32::MAX);
assert_eq!(size, 5);
}
#[test]
fn decodes_sint64() {
let mut dst = 0;
let buf = vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01];
let size = decode_sint64(&buf, &mut dst).unwrap();
assert_eq!(dst, i64::MIN);
assert_eq!(size, 10);
let buf = vec![0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01];
let size = decode_sint64(&buf, &mut dst).unwrap();
assert_eq!(dst, i64::MAX);
assert_eq!(size, 10);
}
#[test]
fn decodes_fixed32() {
let mut dst = 0;
let buf = vec![0x00];
assert!(decode_fixed32(&buf, &mut dst).is_err());
let buf = vec![0x00, 0x00, 0x00, 0x00];
let size = decode_fixed32(&buf, &mut dst).unwrap();
assert_eq!(dst, u32::MIN);
assert_eq!(size, 4);
let buf = vec![0xff, 0xff, 0xff, 0xff];
let size = decode_fixed32(&buf, &mut dst).unwrap();
assert_eq!(dst, u32::MAX);
assert_eq!(size, 4);
}
#[test]
fn decodes_fixed64() {
let mut dst = 0;
let buf = vec![0x00];
assert!(decode_fixed64(&buf, &mut dst).is_err());
let buf = vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff];
let size = decode_fixed64(&buf, &mut dst).unwrap();
assert_eq!(dst, u64::MIN);
assert_eq!(size, 8);
let buf = vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
let size = decode_fixed64(&buf, &mut dst).unwrap();
assert_eq!(dst, u64::MAX);
assert_eq!(size, 8);
}
#[test]
fn decodes_sfixed32() {
let mut dst = 0;
let buf = vec![0x00];
assert!(decode_sfixed32(&buf, &mut dst).is_err());
let buf = vec![0x00, 0x00, 0x00, 0x80];
let size = decode_sfixed32(&buf, &mut dst).unwrap();
assert_eq!(dst, i32::MIN);
assert_eq!(size, 4);
let buf = vec![0xff, 0xff, 0xff, 0x7f];
let size = decode_sfixed32(&buf, &mut dst).unwrap();
assert_eq!(dst, i32::MAX);
assert_eq!(size, 4);
}
#[test]
fn decodes_sfixed64() {
let mut dst = 0;
let buf = vec![0x00];
assert!(decode_sfixed64(&buf, &mut dst).is_err());
let buf = vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80];
let size = decode_sfixed64(&buf, &mut dst).unwrap();
assert_eq!(dst, i64::MIN);
assert_eq!(size, 8);
let buf = vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f];
let size = decode_sfixed64(&buf, &mut dst).unwrap();
assert_eq!(dst, i64::MAX);
assert_eq!(size, 8);
}
#[test]
fn decodes_float() {
let mut dst = 0.0;
let buf = vec![0x00];
assert!(decode_float(&buf, &mut dst).is_err());
let buf = vec![0xff, 0xff, 0x7f, 0xff];
let size = decode_float(&buf, &mut dst).unwrap();
assert_eq!(dst, f32::MIN);
assert_eq!(size, 4);
let buf = vec![0xff, 0xff, 0x7f, 0x7f];
let size = decode_float(&buf, &mut dst).unwrap();
assert_eq!(dst, f32::MAX);
assert_eq!(size, 4);
}
#[test]
fn decodes_double() {
let mut dst = 0.0;
let buf = vec![0x00];
assert!(decode_double(&buf, &mut dst).is_err());
let buf = vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff];
let size = decode_double(&buf, &mut dst).unwrap();
assert_eq!(dst, f64::MIN);
assert_eq!(size, 8);
let buf = vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7f];
let size = decode_double(&buf, &mut dst).unwrap();
assert_eq!(dst, f64::MAX);
assert_eq!(size, 8);
}
}