#[inline(always)]
pub const fn oppv_len_u64(val: u64) -> usize {
if val < 0x80 {
1
} else if val < 0x4000 {
2
} else if val < 0x20_0000 {
3
} else if val < 0x1000_0000 {
4
} else {
9
}
}
#[inline(always)]
pub fn encode_oppv_u64_slice(val: u64, buf: &mut [u8]) -> usize {
debug_assert!(
buf.len() >= oppv_len_u64(val),
"buffer too small for oppv encoding"
);
if val < 0x80 {
buf[0] = val as u8;
1
} else if val < 0x4000 {
buf[0] = 0x80 | ((val >> 8) as u8);
buf[1] = (val & 0xFF) as u8;
2
} else if val < 0x20_0000 {
buf[0] = 0xC0 | ((val >> 16) as u8);
buf[1] = ((val >> 8) & 0xFF) as u8;
buf[2] = (val & 0xFF) as u8;
3
} else if val < 0x1000_0000 {
buf[0] = 0xE0 | ((val >> 24) as u8);
buf[1] = ((val >> 16) & 0xFF) as u8;
buf[2] = ((val >> 8) & 0xFF) as u8;
buf[3] = (val & 0xFF) as u8;
4
} else {
buf[0] = 0xF8;
buf[1..9].copy_from_slice(&val.to_be_bytes());
9
}
}
#[inline(always)]
pub fn encode_oppv_u64_fixed(val: u64, buf: &mut [u8; 9]) -> usize {
encode_oppv_u64_slice(val, buf)
}
#[inline]
pub fn encode_oppv_u64(val: u64, buf: &mut Vec<u8>) {
let mut fixed = [0u8; 9];
let n = encode_oppv_u64_fixed(val, &mut fixed);
buf.extend_from_slice(&fixed[..n]);
}
#[inline]
pub fn decode_oppv_u64(slice: &[u8]) -> Option<(u64, usize)> {
let first = *slice.first()?;
if first < 0x80 {
Some((first as u64, 1))
} else if first < 0xC0 {
if slice.len() < 2 {
return None;
}
let val = (((first & 0x3F) as u64) << 8) | (slice[1] as u64);
Some((val, 2))
} else if first < 0xE0 {
if slice.len() < 3 {
return None;
}
let val = (((first & 0x1F) as u64) << 16) | ((slice[1] as u64) << 8) | (slice[2] as u64);
Some((val, 3))
} else if first < 0xF0 {
if slice.len() < 4 {
return None;
}
let val = (((first & 0x0F) as u64) << 24)
| ((slice[1] as u64) << 16)
| ((slice[2] as u64) << 8)
| (slice[3] as u64);
Some((val, 4))
} else if first == 0xF8 {
if slice.len() < 9 {
return None;
}
let bytes = slice[1..9].try_into().ok()?;
Some((u64::from_be_bytes(bytes), 9))
} else {
None
}
}