use num_bigint::BigInt;
use crate::encoding::encode_u8_arr;
#[inline]
pub fn encode_u8(data: &mut Vec<u8>, value: u8) {
data.push(value);
}
#[inline]
pub fn encode_u16(data: &mut Vec<u8>, value: u16) {
data.extend_from_slice(&value.to_le_bytes());
}
#[inline]
pub fn encode_u32(data: &mut Vec<u8>, value: u32) {
data.extend_from_slice(&value.to_le_bytes());
}
#[inline]
pub fn encode_u64(data: &mut Vec<u8>, value: u64) {
data.extend_from_slice(&value.to_le_bytes());
}
#[inline]
pub fn encode_i8(data: &mut Vec<u8>, value: i8) {
data.push(value.to_le_bytes()[0]);
}
#[inline]
pub fn encode_i16(data: &mut Vec<u8>, value: i16) {
data.extend_from_slice(&value.to_le_bytes());
}
#[inline]
pub fn encode_i32(data: &mut Vec<u8>, value: i32) {
data.extend_from_slice(&value.to_le_bytes());
}
#[inline]
pub fn encode_i64(data: &mut Vec<u8>, value: i64) {
data.extend_from_slice(&value.to_le_bytes());
}
#[inline]
pub fn decode_u8(data: &[u8], ind: &mut usize) -> Option<u8> {
let value = data.get(*ind)?;
*ind += 1;
Some(*value)
}
#[inline]
pub fn decode_u16(data: &[u8], ind: &mut usize) -> Option<u16> {
let value = u16::from_le_bytes(data.get(*ind..*ind + 2)?.try_into().ok()?);
*ind += 2;
Some(value)
}
#[inline]
pub fn decode_u32(data: &[u8], ind: &mut usize) -> Option<u32> {
let value = u32::from_le_bytes(data.get(*ind..*ind + 4)?.try_into().ok()?);
*ind += 4;
Some(value)
}
#[inline]
pub fn decode_u64(data: &[u8], ind: &mut usize) -> Option<u64> {
let value = u64::from_le_bytes(data.get(*ind..*ind + 8)?.try_into().ok()?);
*ind += 8;
Some(value)
}
#[inline]
pub fn decode_i8(data: &[u8], ind: &mut usize) -> Option<i8> {
let value = i8::from_le_bytes([*data.get(*ind)?]);
*ind += 1;
Some(value)
}
#[inline]
pub fn decode_i16(data: &[u8], ind: &mut usize) -> Option<i16> {
let value = i16::from_le_bytes(data.get(*ind..*ind + 2)?.try_into().ok()?);
*ind += 2;
Some(value)
}
#[inline]
pub fn decode_i32(data: &[u8], ind: &mut usize) -> Option<i32> {
let value = i32::from_le_bytes(data.get(*ind..*ind + 4)?.try_into().ok()?);
*ind += 4;
Some(value)
}
#[inline]
pub fn decode_i64(data: &[u8], ind: &mut usize) -> Option<i64> {
let value = i64::from_le_bytes(data.get(*ind..*ind + 8)?.try_into().ok()?);
*ind += 8;
Some(value)
}
#[inline]
pub fn encode_f32(data: &mut Vec<u8>, value: f32) {
data.extend_from_slice(&value.to_le_bytes());
}
#[inline]
pub fn encode_f64(data: &mut Vec<u8>, value: f64) {
data.extend_from_slice(&value.to_le_bytes());
}
#[inline]
pub fn decode_f32(data: &[u8], ind: &mut usize) -> Option<f32> {
let value = f32::from_le_bytes(data.get(*ind..*ind + 4)?.try_into().ok()?);
*ind += 4;
Some(value)
}
#[inline]
pub fn decode_f64(data: &[u8], ind: &mut usize) -> Option<f64> {
let value = f64::from_le_bytes(data.get(*ind..*ind + 8)?.try_into().ok()?);
*ind += 8;
Some(value)
}
pub fn encode_vuint(data: &mut Vec<u8>, mut value: u64) {
let mut buf = [0u8; 10];
let mut there_input = true;
let mut ind = 0;
while there_input {
let byte = value as u8 & 0b0111_1111;
value >>= 7;
buf[ind] = if value == 0 { byte } else { byte | 0b1000_0000 };
there_input = value != 0;
ind += 1;
}
data.extend_from_slice(&buf[0..ind]);
}
pub fn encode_vuint_pre_aloc(
data: &mut Vec<u8>, mut value: u64, start_ind: usize, pre_aloc: usize,
) {
let mut buf = [0u8; 10];
let mut size = 0;
let mut there_input = true;
while there_input {
let byte = value as u8 & 0b0111_1111;
value >>= 7;
buf[size] = if value == 0 { byte } else { byte | 0b1000_0000 };
there_input = value != 0;
size += 1;
}
if size > pre_aloc {
let len = data.len();
data.resize(len + size - pre_aloc, 0);
data.copy_within(start_ind + pre_aloc..len, start_ind + size);
}
if size < pre_aloc {
for i in size - 1..pre_aloc - 1 {
buf[i] |= 0b1000_0000
}
size = pre_aloc;
}
data[start_ind..start_ind + size].copy_from_slice(&buf[..size]);
}
pub fn encode_vint(data: &mut Vec<u8>, mut value: i64) {
let mut buf = [0u8; 10];
let mut ind = 0;
let mut there_input = true;
while there_input {
let mut byte = (value & 0b0111_1111) as u8;
value >>= 7;
let sign_bit = byte & 0b0100_0000;
if (value == 0 && sign_bit == 0) || (value == -1 && sign_bit != 0) {
there_input = false;
} else {
byte |= 0b1000_0000;
}
buf[ind] = byte;
ind += 1;
}
data.extend_from_slice(&buf[0..ind]);
}
pub fn decode_vuint(data: &[u8], ind: &mut usize) -> Option<u64> {
let mut there_input = true;
let mut res = 0u64;
let mut shift = 0;
while there_input {
let byte = *data.get(*ind)? as u64;
res |= (byte & 0b0111_1111) << shift;
shift += 7;
*ind += 1;
there_input = byte & 0b1000_0000 != 0;
}
Some(res)
}
pub fn decode_vint(data: &[u8], ind: &mut usize) -> Option<i64> {
let mut there_input = true;
let mut res = 0i64;
let mut shift = 0u64;
let mut byte = 0i64;
while there_input {
byte = *data.get(*ind)? as i64;
res |= (byte & 0b0111_1111) << shift;
shift += 7;
*ind += 1;
there_input = byte & 0b1000_0000 != 0;
}
if (shift < 64) && (byte & 0b0100_0000 != 0) {
res |= !0 << shift;
}
Some(res)
}
#[inline]
pub fn encode_bint(data: &mut Vec<u8>, value: &BigInt) {
encode_u8_arr(data, &value.to_signed_bytes_le());
}
#[inline]
pub fn decode_bint(data: &[u8], ind: &mut usize) -> Option<BigInt> {
let len = decode_vuint(data, ind)? as usize;
let value = BigInt::from_signed_bytes_le(data.get(*ind..*ind + len)?);
*ind += len;
Some(value)
}