use crate::serde::error::DataError;
use anyhow::{bail, ensure, Result};
use serde::Deserialize;
use std::convert::TryInto;
use std::mem::size_of;
use std::ops::Deref;
pub trait ReadNumberFixed {
fn read(dr: &mut DataReader) -> Result<Self>
where
Self: Sized;
}
pub trait ReadNumberVar {
fn read(dr: &mut DataReader) -> Result<Self>
where
Self: Sized;
}
macro_rules! impl_read_number_fixed {
($type:tt) => {
impl ReadNumberFixed for $type {
#[cfg(not(feature = "big_endian"))]
#[inline]
fn read(dr: &mut DataReader) -> Result<Self>
where
Self: Sized,
{
let size = size_of::<$type>();
ensure!(
size <= dr.len(),
"read fixed error len too min:dr:{} < {}",
dr.len(),
size
);
let v = $type::from_le_bytes(dr[..size].try_into()?);
dr.advance(size)?;
Ok(v)
}
#[cfg(feature = "big_endian")]
#[inline]
fn read(dr: &mut DataReader) -> Result<Self>
where
Self: Sized,
{
let size = size_of::<$type>();
ensure!(
size <= dr.len(),
"read fixed error len too min:dr:{} < {}",
dr.len(),
size
);
let v = $type::from_be_bytes(dr[..size].try_into()?);
dr.advance(size)?;
Ok(v)
}
}
};
}
impl ReadNumberFixed for bool {
#[inline]
fn read(dr: &mut DataReader) -> Result<Self>
where
Self: Sized,
{
let v = dr.read_fixed::<u8>()?;
if v == 0 {
Ok(false)
} else {
Ok(true)
}
}
}
impl_read_number_fixed!(u8);
impl_read_number_fixed!(i8);
impl_read_number_fixed!(u16);
impl_read_number_fixed!(i16);
impl_read_number_fixed!(u32);
impl_read_number_fixed!(i32);
impl_read_number_fixed!(u64);
impl_read_number_fixed!(i64);
impl_read_number_fixed!(i128);
impl_read_number_fixed!(u128);
impl_read_number_fixed!(f32);
impl_read_number_fixed!(f64);
impl ReadNumberVar for u16 {
#[inline]
fn read(dr: &mut DataReader) -> Result<Self>
where
Self: Sized,
{
let mut v = 0u16;
let mut offset = 0;
let mut shift = 0u8;
let mut b;
while shift < 16 {
ensure!(
offset != dr.len(),
"read var number,offset:{} > bytes length:{}",
offset,
dr.len()
);
b = dr[offset];
offset += 1;
v |= ((b & 0x7F) as u16) << shift;
if b & 0x80 == 0 {
dr.buff = &dr.buff[offset..];
return Ok(v);
}
shift += 7;
}
bail!("not read var number too end")
}
}
impl ReadNumberVar for i16 {
#[inline]
fn read(dr: &mut DataReader) -> Result<Self>
where
Self: Sized,
{
Ok(zig_zag_decode_i16(ReadNumberVar::read(dr)?))
}
}
impl ReadNumberVar for u32 {
#[inline]
fn read(dr: &mut DataReader) -> Result<Self>
where
Self: Sized,
{
let mut v = 0u32;
let mut offset = 0;
let mut shift = 0u8;
let mut b;
while shift < 32 {
ensure!(
offset != dr.len(),
"read var number,offset:{} > bytes length:{}",
offset,
dr.len()
);
b = dr[offset];
offset += 1;
v |= ((b & 0x7F) as u32) << shift;
if b & 0x80 == 0 {
dr.buff = &dr.buff[offset..];
return Ok(v);
}
shift += 7;
}
bail!("not read var number too end")
}
}
impl ReadNumberVar for i32 {
#[inline]
fn read(dr: &mut DataReader) -> Result<Self>
where
Self: Sized,
{
Ok(zig_zag_decode_i32(ReadNumberVar::read(dr)?))
}
}
impl ReadNumberVar for u64 {
#[inline]
fn read(dr: &mut DataReader) -> Result<Self>
where
Self: Sized,
{
let mut v = 0u64;
let mut offset = 0;
let mut shift = 0u8;
let mut b;
while shift < 64 {
ensure!(
offset != dr.len(),
"read var number,offset:{} > bytes length:{}",
offset,
dr.len()
);
b = dr[offset];
offset += 1;
v |= ((b & 0x7F) as u64) << shift;
if b & 0x80 == 0 {
dr.buff = &dr.buff[offset..];
return Ok(v);
}
shift += 7;
}
bail!("not read var number too end")
}
}
impl ReadNumberVar for i64 {
#[inline]
fn read(dr: &mut DataReader) -> Result<Self>
where
Self: Sized,
{
Ok(zig_zag_decode_i64(ReadNumberVar::read(dr)?))
}
}
#[inline(always)]
fn zig_zag_decode_i16(v: u16) -> i16 {
((v >> 1) as i16) ^ (-((v & 1) as i16))
}
#[inline(always)]
fn zig_zag_decode_i32(v: u32) -> i32 {
((v >> 1) as i32) ^ (-((v & 1) as i32))
}
#[inline(always)]
fn zig_zag_decode_i64(v: u64) -> i64 {
((v >> 1) as i64) ^ (-((v & 1) as i64))
}
#[derive(Debug)]
pub struct DataReader<'a> {
pub(crate) buff: &'a [u8],
pub(crate) original_len: usize,
pub(crate) mode: u8,
}
impl<'a> From<&'a [u8]> for DataReader<'a> {
#[inline]
fn from(buff: &'a [u8]) -> Self {
DataReader {
buff,
original_len: buff.len(),
mode: 0,
}
}
}
impl<'a> Deref for DataReader<'a> {
type Target = &'a [u8];
#[inline]
fn deref(&self) -> &Self::Target {
&self.buff
}
}
impl<'a> AsRef<[u8]> for DataReader<'a> {
#[inline]
fn as_ref(&self) -> &[u8] {
self.buff
}
}
impl<'a> DataReader<'a> {
#[inline]
pub fn from<T: AsRef<[u8]> + ?Sized>(v: &'a T) -> Self {
let buff = v.as_ref();
DataReader {
original_len: buff.len(),
buff,
mode: 0,
}
}
#[inline]
pub fn deserialize<'de, D: Deserialize<'de>, T: AsRef<[u8]>>(
v: &'de T,
) -> Result<D, DataError> {
let buff = v.as_ref();
D::deserialize(&mut DataReader {
original_len: buff.len(),
buff,
mode: 0,
})
}
#[inline]
pub fn advance(&mut self, cnt: usize) -> Result<()> {
ensure!(
self.len() >= cnt,
"advance error,cnt:{} > len:{}",
cnt,
self.len()
);
self.buff = &self.buff[cnt..];
Ok(())
}
#[inline]
pub fn offset(&self) -> usize {
self.original_len.wrapping_sub(self.buff.len())
}
#[inline]
pub fn reload(&mut self, buff: &'a [u8], original_len: usize) {
self.buff = buff;
self.original_len = original_len;
}
#[inline]
pub fn read_buff(&mut self, buff: &mut [u8]) -> Result<()> {
let size = buff.len();
ensure!(
self.len() >= size,
"read buff,buff too max,current:{} input:{}",
self.len(),
size
);
let (copy, current) = self.buff.split_at(size);
buff.copy_from_slice(copy);
self.buff = current;
Ok(())
}
#[inline]
pub fn read_var_str(&mut self) -> Result<&'a str> {
let len = self.read_var_integer::<u64>()? as usize;
ensure!(
len <= self.len(),
"read string size too big,{}>{}",
len,
self.len()
);
let (res, have) = self.buff.split_at(len);
self.buff = have;
cfg_if::cfg_if! {
if #[cfg(feature ="check_utf8")]{
Ok(std::str::from_utf8(res)?)
}else{
unsafe {
Ok(std::str::from_utf8_unchecked(res))
}
}
}
}
#[inline]
pub fn read_fixed_str(&mut self) -> Result<&'a str> {
let len = self.read_fixed::<u32>()? as usize;
ensure!(
len <= self.len(),
"read string size too big,{}>{}",
len,
self.len()
);
let (res, have) = self.buff.split_at(len);
self.buff = have;
cfg_if::cfg_if! {
if #[cfg(feature ="check_utf8")]{
Ok(std::str::from_utf8(res)?)
}else{
unsafe {
Ok(std::str::from_utf8_unchecked(res))
}
}
}
}
#[inline]
pub fn read_var_buf(&mut self) -> Result<&'a [u8]> {
let len = self.read_var_integer::<u64>()? as usize;
ensure!(
len <= self.len(),
"read string size too big,{}>{}",
len,
self.len()
);
let (res, have) = self.buff.split_at(len);
self.buff = have;
Ok(res)
}
#[inline]
pub fn read_fixed_buf(&mut self) -> Result<&'a [u8]> {
let len = self.read_fixed::<u32>()? as usize;
ensure!(
len <= self.len(),
"read string size too big,{}>{}",
len,
self.len()
);
let (res, have) = self.buff.split_at(len);
self.buff = have;
Ok(res)
}
#[inline]
pub fn read_fixed<T: ReadNumberFixed>(&mut self) -> Result<T> {
T::read(self)
}
#[inline]
pub fn read_var_integer<T: ReadNumberVar>(&mut self) -> Result<T> {
T::read(self)
}
}