use bytes::Buf;
use crate::coding::{Decode, DecodeError};
use super::Version;
const MAX_PROPERTIES: u64 = 64;
const MAX_KVP_VALUE_LEN: usize = (1 << 16) - 1;
pub fn skip_properties<R: Buf>(r: &mut R, version: Version) -> Result<(), DecodeError> {
if version != Version::Draft17 {
return Ok(());
}
let mut prev_type: u64 = 0;
let mut i: u64 = 0;
while r.has_remaining() {
if i >= MAX_PROPERTIES {
return Err(DecodeError::TooMany);
}
let delta = u64::decode(r, version)?;
let abs = if i == 0 {
delta
} else {
prev_type.checked_add(delta).ok_or(DecodeError::BoundsExceeded)?
};
prev_type = abs;
i += 1;
if abs % 2 == 0 {
let _ = u64::decode(r, version)?;
} else {
let len = u64::decode(r, version)? as usize;
if len > MAX_KVP_VALUE_LEN {
return Err(DecodeError::BoundsExceeded);
}
if r.remaining() < len {
return Err(DecodeError::Short);
}
r.advance(len);
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::coding::Encode;
use bytes::BytesMut;
#[test]
fn test_skip_empty_properties() {
let mut buf = bytes::Bytes::new();
skip_properties(&mut buf, Version::Draft17).unwrap();
}
#[test]
fn test_skip_varint_property() {
let mut buf = BytesMut::new();
0x02u64.encode(&mut buf, Version::Draft17).unwrap(); 5000u64.encode(&mut buf, Version::Draft17).unwrap(); let mut bytes = buf.freeze();
skip_properties(&mut bytes, Version::Draft17).unwrap();
assert!(!bytes.has_remaining());
}
#[test]
fn test_skip_bytes_property() {
let mut buf = BytesMut::new();
0x0Bu64.encode(&mut buf, Version::Draft17).unwrap(); 3u64.encode(&mut buf, Version::Draft17).unwrap(); buf.extend_from_slice(&[0x01, 0x02, 0x03]); let mut bytes = buf.freeze();
skip_properties(&mut bytes, Version::Draft17).unwrap();
assert!(!bytes.has_remaining());
}
#[test]
fn test_skip_multiple_properties() {
let mut buf = BytesMut::new();
0x02u64.encode(&mut buf, Version::Draft17).unwrap();
1000u64.encode(&mut buf, Version::Draft17).unwrap();
0x02u64.encode(&mut buf, Version::Draft17).unwrap();
2000u64.encode(&mut buf, Version::Draft17).unwrap();
0x07u64.encode(&mut buf, Version::Draft17).unwrap();
2u64.encode(&mut buf, Version::Draft17).unwrap();
buf.extend_from_slice(&[0xAA, 0xBB]);
let mut bytes = buf.freeze();
skip_properties(&mut bytes, Version::Draft17).unwrap();
assert!(!bytes.has_remaining());
}
}