use std::fmt::{Display, Formatter};
use std::string::FromUtf8Error;
use crate::bipack_source::BipackError::NoDataError;
pub type Result<T> = std::result::Result<T, BipackError>;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum BipackError {
NoDataError,
BadEncoding(FromUtf8Error),
BufferOverflow,
Message(String),
BadFormat(String),
Eof,
ExtraBytes,
NotSupported,
NotImplemented,
NotPossible
}
impl std::error::Error for BipackError {}
impl Display for BipackError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
pub trait BipackSource {
fn get_u8(self: &mut Self) -> Result<u8>;
fn eof(self: &Self) -> bool;
fn get_u16(self: &mut Self) -> Result<u16> {
Ok(((self.get_u8()? as u16) << 8) + (self.get_u8()? as u16))
}
fn get_u32(self: &mut Self) -> Result<u32> {
Ok(((self.get_u16()? as u32) << 16) + (self.get_u16()? as u32))
}
fn get_u64(self: &mut Self) -> Result<u64> {
Ok(((self.get_u32()? as u64) << 32) | (self.get_u32()? as u64))
}
fn get_i64(self: &mut Self) -> Result<i64> {
Ok(self.get_u64()? as i64)
}
fn get_i32(self: &mut Self) -> Result<i32> {
Ok(self.get_u32()? as i32)
}
fn get_i16(self: &mut Self) -> Result<i16> {
Ok(self.get_u16()? as i16)
}
fn get_i8(self: &mut Self) -> Result<i8> {
Ok(self.get_u8()? as i8)
}
fn get_unsigned(self: &mut Self) -> Result<u64> {
let mut get = || -> Result<u64> { Ok(self.get_u8()? as u64) };
let first = get()?;
let mut ty = first & 3;
let mut result = first >> 2;
if ty == 0 { return Ok(result); }
ty -= 1;
result = result + (get()? << 6);
if ty == 0 { return Ok(result); }
ty -= 1;
result = result + (get()? << 14);
if ty == 0 { return Ok(result); }
Ok(result | (self.get_varint_unsigned()? << 22))
}
fn get_signed(self: &mut Self) -> Result<i64> {
let value = self.get_unsigned()?;
let result = (value >> 1) as i64;
Ok(if value & 1 != 0 { -result } else { result } )
}
fn get_varint_unsigned(self: &mut Self) -> Result<u64> {
let mut result = 0u64;
let mut count = 0;
loop {
let x = self.get_u8()? as u64;
result = result | ((x & 0x7F) << count);
if (x & 0x80) == 0 { return Ok(result); }
count += 7
}
}
fn get_packed_u16(self: &mut Self) -> Result<u16> {
Ok(self.get_unsigned()? as u16)
}
fn get_packed_u32(self: &mut Self) -> Result<u32> { Ok(self.get_unsigned()? as u32) }
fn get_fixed_bytes(self: &mut Self, size: usize) -> Result<Vec<u8>> {
let mut result = Vec::with_capacity(size);
for i in 0..size { result.push(self.get_u8()?); }
Ok(result)
}
fn get_var_bytes(self: &mut Self) -> Result<Vec<u8>> {
let size = self.get_unsigned()? as usize;
self.get_fixed_bytes(size)
}
fn get_str(self: &mut Self) -> Result<String> {
String::from_utf8(
self.get_var_bytes()?
).or_else(|e| Err(BipackError::BadEncoding(e)))
}
}
pub struct SliceSource<'a> {
data: &'a [u8],
position: usize,
}
impl<'a> SliceSource<'a> {
pub fn from(src: &'a [u8]) -> SliceSource<'a> {
SliceSource { data: src, position: 0 }
}
}
impl<'x> BipackSource for SliceSource<'x> {
fn get_u8(self: &mut Self) -> Result<u8> {
if self.position >= self.data.len() {
Err(NoDataError)
} else {
let result = self.data[self.position];
self.position += 1;
Ok(result)
}
}
fn eof(self: &Self) -> bool {
self.data.len() >= self.position
}
}