#![allow(dead_code)]
use crate::error::{Error, Result};
use crate::io::{BinaryReader, BinaryWriter};
fn write_multibyte(writer: &mut BinaryWriter, length: u32) -> Result<()> {
if length < 0xFFFF {
writer.write_u8(0xFF)?;
writer.write_u16(length as u16)
} else {
writer.write_u8(0xFF)?;
writer.write_u8(0xFF)?;
writer.write_u8(0xFF)?;
writer.write_u32(length)
}
}
pub mod multi_packet {
use super::*;
pub fn encoded_size(length: u32) -> usize {
if length <= 0xFF {
1
} else if length < 0xFFFF {
3
} else {
7
}
}
pub fn read(reader: &mut BinaryReader) -> Result<u32> {
let b0 = reader.peek(0).ok_or(Error::BufferTooShort {
needed: 1,
available: 0,
})?;
if b0 < 0xFF {
reader.skip(1)?;
Ok(b0 as u32)
} else if reader.peek(1) == Some(0) {
reader.skip(1)?;
Ok(0xFF)
} else if reader.peek(1) == Some(0xFF) && reader.peek(2) == Some(0xFF) {
reader.skip(3)?;
Ok(reader.read_u32()?)
} else {
reader.skip(1)?;
Ok(reader.read_u16()? as u32)
}
}
pub fn write(writer: &mut BinaryWriter, length: u32) -> Result<()> {
if length <= 0xFF {
writer.write_u8(length as u8)
} else {
write_multibyte(writer, length)
}
}
}
pub mod data_bundle {
use super::*;
pub fn encoded_size(length: u32) -> usize {
if length < 0xFF {
1
} else if length < 0xFFFF {
3
} else {
7
}
}
pub fn read(reader: &mut BinaryReader) -> Result<u32> {
let b0 = reader.peek(0).ok_or(Error::BufferTooShort {
needed: 1,
available: 0,
})?;
if b0 < 0xFF {
reader.skip(1)?;
Ok(b0 as u32)
} else if reader.peek(1) == Some(0xFF) && reader.peek(2) == Some(0xFF) {
reader.skip(3)?;
Ok(reader.read_u32()?)
} else {
reader.skip(1)?;
Ok(reader.read_u16()? as u32)
}
}
pub fn write(writer: &mut BinaryWriter, length: u32) -> Result<()> {
if length < 0xFF {
writer.write_u8(length as u8)
} else {
write_multibyte(writer, length)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn multi_packet_encoded_size_boundaries() {
assert_eq!(multi_packet::encoded_size(0), 1);
assert_eq!(multi_packet::encoded_size(0xFF), 1);
assert_eq!(multi_packet::encoded_size(0x100), 3);
assert_eq!(multi_packet::encoded_size(0xFFFE), 3);
assert_eq!(multi_packet::encoded_size(0xFFFF), 7);
}
#[test]
fn data_bundle_encoded_size_boundaries() {
assert_eq!(data_bundle::encoded_size(0), 1);
assert_eq!(data_bundle::encoded_size(0xFE), 1);
assert_eq!(data_bundle::encoded_size(0xFF), 3);
assert_eq!(data_bundle::encoded_size(0xFFFE), 3);
assert_eq!(data_bundle::encoded_size(0xFFFF), 7);
}
#[test]
fn data_bundle_round_trip() {
for &len in &[
0u32,
1,
0xFE,
0xFF,
0x100,
0xFFFE,
0xFFFF,
0x1_0000,
0xFFFF_FFFF,
] {
let mut buf = [0u8; 8];
let mut w = BinaryWriter::new(&mut buf);
data_bundle::write(&mut w, len).unwrap();
let written = w.offset();
assert_eq!(written, data_bundle::encoded_size(len), "size len={len:#x}");
let mut r = BinaryReader::new(&buf);
let got = data_bundle::read(&mut r).unwrap();
assert_eq!(got, len, "len={len:#x}");
assert_eq!(r.offset(), written);
}
}
#[test]
fn multi_packet_round_trip() {
for &len in &[
0u32,
1,
0xFE,
0xFF,
0x100,
0xFFFE,
0xFFFF,
0x1_0000,
0xFFFF_FFFF,
] {
let mut buf = [0u8; 9];
let mut w = BinaryWriter::new(&mut buf);
multi_packet::write(&mut w, len).unwrap();
let written = w.offset();
assert_eq!(
written,
multi_packet::encoded_size(len),
"size len={len:#x}"
);
let mut r = BinaryReader::new(&buf);
let got = multi_packet::read(&mut r).unwrap();
assert_eq!(got, len, "len={len:#x}");
assert_eq!(r.offset(), written);
}
}
#[test]
fn multi_packet_single_byte_ff() {
let mut buf = [0u8; 4];
let mut w = BinaryWriter::new(&mut buf);
multi_packet::write(&mut w, 0xFF).unwrap();
assert_eq!(w.offset(), 1);
assert_eq!(buf[0], 0xFF);
let mut r = BinaryReader::new(&buf);
assert_eq!(multi_packet::read(&mut r).unwrap(), 0xFF);
assert_eq!(r.offset(), 1);
}
}