use crate::nested_ser_output::NestedEncodeOutput;
pub fn using_encoded_number<F: FnOnce(&[u8])>(
x: u64,
size_in_bits: usize,
signed: bool,
mut compact: bool,
f: F,
) {
let mut result = [0u8; 8];
let mut result_size = 0usize;
let negative = compact && signed && x >> (size_in_bits - 1) & 1 == 1; let irrelevant_byte = if negative { 0xffu8 } else { 0x00u8 };
let mut bit_offset = size_in_bits as isize - 8;
while bit_offset >= 0 {
let byte = (x >> (bit_offset as usize) & 0xffu64) as u8;
if compact {
if byte != irrelevant_byte {
result[result_size] = byte;
result_size += 1;
compact = false;
}
} else {
result[result_size] = byte;
result_size += 1;
}
bit_offset -= 8;
}
f(&result[0..result_size])
}
pub fn top_encode_number_to_output<O: NestedEncodeOutput>(output: &mut O, x: u64, signed: bool) {
let bytes_be: [u8; 8] = x.to_be_bytes();
if x == 0 {
return;
}
if signed && x == u64::MAX {
output.push_byte(0xffu8);
return;
}
let negative = signed && bytes_be[0] > 0x7fu8; let irrelevant_byte = if negative { 0xffu8 } else { 0x00u8 };
let mut offset = 0usize;
while bytes_be[offset] == irrelevant_byte {
debug_assert!(offset < 7);
offset += 1;
}
if signed && bytes_be[offset] >> 7 != negative as u8 {
debug_assert!(offset > 0);
offset -= 1;
}
output.write(&bytes_be[offset..]);
}
#[inline(never)]
pub fn bytes_to_number(bytes: &[u8], signed: bool) -> u64 {
if bytes.is_empty() {
return 0;
}
let negative = signed && bytes[0] >> 7 == 1;
let mut result = if negative {
u64::MAX
} else {
0u64
};
for byte in bytes.iter() {
result <<= 8;
result |= *byte as u64;
}
result
}