use crate::error::{Error, Result};
#[inline]
pub fn write_size(mut n: u64, out: &mut Vec<u8>) {
if n < (1 << 6) {
let b = (n as u8) << 2;
out.push(b);
return;
}
if n < (1 << 14) {
let mut b0 = ((n & 0x3f) as u8) << 2;
b0 |= 0b01;
out.push(b0);
n >>= 6;
out.push(n as u8);
return;
}
if n < (1 << 30) {
let mut b0 = ((n & 0x3f) as u8) << 2;
b0 |= 0b10;
out.push(b0);
n >>= 6;
out.push(n as u8);
out.push((n >> 8) as u8);
out.push((n >> 16) as u8);
return;
}
let mut b0 = ((n & 0x3f) as u8) << 2;
b0 |= 0b11;
out.push(b0);
n >>= 6;
for i in 0..7 {
out.push((n >> (i * 8)) as u8);
}
}
#[inline]
pub fn size_encoded_len(n: u64) -> usize {
if n < (1 << 6) {
1
} else if n < (1 << 14) {
2
} else if n < (1 << 30) {
4
} else {
8
}
}
#[inline]
pub(crate) fn write_size_to_writer<W: std::io::Write>(w: &mut W, n: u64) -> std::io::Result<()> {
let mut buf = [0u8; 8];
let used = encode_size_to_array(n, &mut buf);
w.write_all(&buf[..used])
}
#[inline]
pub fn encode_size_to_array(mut n: u64, out: &mut [u8; 8]) -> usize {
if n < (1 << 6) {
out[0] = (n as u8) << 2;
1
} else if n < (1 << 14) {
out[0] = (((n & 0x3f) as u8) << 2) | 0b01;
n >>= 6;
out[1] = n as u8;
2
} else if n < (1 << 30) {
out[0] = (((n & 0x3f) as u8) << 2) | 0b10;
n >>= 6;
out[1] = n as u8;
out[2] = (n >> 8) as u8;
out[3] = (n >> 16) as u8;
4
} else {
out[0] = (((n & 0x3f) as u8) << 2) | 0b11;
n >>= 6;
for i in 0..7 {
out[i + 1] = (n >> (i * 8)) as u8;
}
8
}
}
#[inline]
pub fn read_size(input: &[u8], pos: &mut usize) -> Result<u64> {
if *pos >= input.len() {
return Err(Error::Eof);
}
let b0 = input[*pos];
*pos += 1;
let code = b0 & 0b11;
let mut value: u64 = (b0 >> 2) as u64; match code {
0 => Ok(value), 1 => {
if *pos >= input.len() {
return Err(Error::Eof);
}
value |= (input[*pos] as u64) << 6;
*pos += 1;
Ok(value)
}
2 => {
if input.len() < *pos + 3 {
return Err(Error::Eof);
}
value |= (input[*pos] as u64) << 6;
value |= (input[*pos + 1] as u64) << 14;
value |= (input[*pos + 2] as u64) << 22;
*pos += 3;
Ok(value)
}
_ => {
if input.len() < *pos + 7 {
return Err(Error::Eof);
}
for i in 0..7 {
value |= (input[*pos + i] as u64) << (6 + 8 * i as u64);
}
*pos += 7;
Ok(value)
}
}
}
#[inline]
pub(crate) fn read_size_from_reader<R: std::io::Read>(reader: &mut R) -> Result<u64> {
let mut b0_buf = [0u8; 1];
reader.read_exact(&mut b0_buf).map_err(|_| Error::Eof)?;
read_size_from_reader_with_first_byte(reader, b0_buf[0])
}
#[inline]
pub(crate) fn read_size_from_reader_with_first_byte<R: std::io::Read>(
reader: &mut R,
b0: u8,
) -> Result<u64> {
let code = b0 & 0b11;
let mut value: u64 = (b0 >> 2) as u64;
match code {
0 => Ok(value),
1 => {
let mut buf = [0u8; 1];
reader.read_exact(&mut buf).map_err(|_| Error::Eof)?;
value |= (buf[0] as u64) << 6;
Ok(value)
}
2 => {
let mut buf = [0u8; 3];
reader.read_exact(&mut buf).map_err(|_| Error::Eof)?;
value |= (buf[0] as u64) << 6;
value |= (buf[1] as u64) << 14;
value |= (buf[2] as u64) << 22;
Ok(value)
}
_ => {
let mut buf = [0u8; 7];
reader.read_exact(&mut buf).map_err(|_| Error::Eof)?;
for (i, &b) in buf.iter().enumerate() {
value |= (b as u64) << (6 + 8 * i as u64);
}
Ok(value)
}
}
}