#![no_std]
#![allow(clippy::nonminimal_bool)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::cast_sign_loss)]
#[cfg(feature = "std")]
extern crate std;
use core::mem;
use byteio::{ReadBytes, ReadBytesExt, WriteBytes, WriteBytesExt};
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct SLEB128(i64);
impl From<SLEB128> for i64 {
fn from(sleb128: SLEB128) -> Self {
sleb128.0
}
}
impl From<i64> for SLEB128 {
fn from(val: i64) -> Self {
Self(val)
}
}
impl SLEB128 {
pub fn read_from(buf: &[u8]) -> Result<(Self, usize), LEB128DecodeError> {
<Self as LEB128>::read_from(buf)
}
pub fn write_into(self, buf: &mut [u8]) -> Result<usize, LEB128EncodeError> {
<Self as LEB128>::write_into(self, buf)
}
#[cfg(feature = "std_io_ext")]
pub fn read_from_std_io<R: ::std::io::Read>(reader: R) -> ::std::io::Result<(Self, usize)> {
<Self as LEB128>::read_from_std_io(reader)
}
#[cfg(feature = "std_io_ext")]
pub fn write_into_std_io<W: ::std::io::Write>(self, writer: W) -> ::std::io::Result<usize> {
<Self as LEB128>::write_into_std_io(self, writer)
}
#[cfg(feature = "byteio_ext")]
pub fn read_from_byteio<'a, R: ReadBytes<'a>>(
reader: R,
) -> Result<(Self, usize), LEB128DecodeError> {
<Self as LEB128>::read_from_byteio(reader)
}
#[cfg(feature = "byteio_ext")]
pub fn write_into_byteio<W: WriteBytes>(self, writer: W) -> Result<usize, LEB128EncodeError> {
<Self as LEB128>::write_into_byteio(self, writer)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ULEB128(u64);
impl From<ULEB128> for u64 {
fn from(uleb128: ULEB128) -> Self {
uleb128.0
}
}
impl From<u64> for ULEB128 {
fn from(val: u64) -> Self {
Self(val)
}
}
impl ULEB128 {
pub fn read_from(buf: &[u8]) -> Result<(Self, usize), LEB128DecodeError> {
<Self as LEB128>::read_from(buf)
}
pub fn write_into(self, buf: &mut [u8]) -> Result<usize, LEB128EncodeError> {
<Self as LEB128>::write_into(self, buf)
}
#[cfg(feature = "std_io_ext")]
pub fn read_from_std_io<R: ::std::io::Read>(reader: R) -> ::std::io::Result<(Self, usize)> {
<Self as LEB128>::read_from_std_io(reader)
}
#[cfg(feature = "std_io_ext")]
pub fn write_into_std_io<W: ::std::io::Write>(self, writer: W) -> ::std::io::Result<usize> {
<Self as LEB128>::write_into_std_io(self, writer)
}
#[cfg(feature = "byteio_ext")]
pub fn read_from_byteio<'a, R: ReadBytes<'a>>(
reader: R,
) -> Result<(Self, usize), LEB128DecodeError> {
<Self as LEB128>::read_from_byteio(reader)
}
#[cfg(feature = "byteio_ext")]
pub fn write_into_byteio<W: WriteBytes>(self, writer: W) -> Result<usize, LEB128EncodeError> {
<Self as LEB128>::write_into_byteio(self, writer)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum LEB128DecodeError {
BufferOverflow,
IntegerOverflow,
}
#[cfg(feature = "std")]
impl From<LEB128DecodeError> for ::std::io::Error {
fn from(err: LEB128DecodeError) -> Self {
match err {
LEB128DecodeError::BufferOverflow => ::std::io::ErrorKind::UnexpectedEof.into(),
LEB128DecodeError::IntegerOverflow => ::std::io::ErrorKind::InvalidData.into(),
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum LEB128EncodeError {
BufferOverflow,
}
#[cfg(feature = "std")]
impl From<LEB128EncodeError> for ::std::io::Error {
fn from(err: LEB128EncodeError) -> Self {
match err {
LEB128EncodeError::BufferOverflow => ::std::io::ErrorKind::UnexpectedEof.into(),
}
}
}
const LEB128_HIGH_ORDER_BIT: u8 = 1 << 7;
const LEB128_SIGN_BIT: u8 = 1 << 6;
trait LEB128Decode: Sized {
fn leb128_decode<'a, R: ReadBytes<'a>>(reader: R) -> Result<Self, LEB128DecodeError>;
}
trait LEB128Encode {
fn leb128_encode<W: WriteBytes>(self, writer: W) -> Result<(), LEB128EncodeError>;
}
trait LEB128: LEB128Decode + LEB128Encode {
fn read_from(buf: &[u8]) -> Result<(Self, usize), LEB128DecodeError> {
let mut reader = ::byteio::Reader::new(buf);
let value = Self::leb128_decode(&mut reader)?;
Ok((value, reader.num_bytes_read()))
}
fn write_into(self, buf: &mut [u8]) -> Result<usize, LEB128EncodeError> {
let mut writer = ::byteio::Writer::new(buf);
self.leb128_encode(&mut writer)?;
Ok(writer.num_bytes_written())
}
#[cfg(feature = "std_io_ext")]
fn read_from_std_io<R: ::std::io::Read>(mut reader: R) -> ::std::io::Result<(Self, usize)> {
let mut buf = ::std::vec::Vec::with_capacity(10);
loop {
let mut byte = [0];
reader.read_exact(&mut byte)?;
buf.push(byte[0]);
match Self::leb128_decode(&*buf) {
Ok(val) => {
return Ok((val, buf.len()));
}
Err(err) if err == LEB128DecodeError::IntegerOverflow => {
return Err(err.into());
}
_ => (),
}
}
}
#[cfg(feature = "std_io_ext")]
fn write_into_std_io<W: ::std::io::Write>(self, mut writer: W) -> ::std::io::Result<usize> {
let mut buf = ::std::vec::Vec::with_capacity(10);
self.leb128_encode(&mut buf)?;
writer.write_all(&buf)?;
Ok(buf.len())
}
#[cfg(feature = "byteio_ext")]
fn read_from_byteio<'a, R: ReadBytes<'a>>(
reader: R,
) -> Result<(Self, usize), LEB128DecodeError> {
let mut reader = ::byteio::Reader::new(reader);
let value = Self::leb128_decode(&mut reader)?;
Ok((value, reader.num_bytes_read()))
}
#[cfg(feature = "byteio_ext")]
fn write_into_byteio<W: WriteBytes>(self, writer: W) -> Result<usize, LEB128EncodeError> {
let mut writer = ::byteio::Writer::new(writer);
self.leb128_encode(&mut writer)?;
Ok(writer.num_bytes_written())
}
}
impl LEB128Decode for SLEB128 {
fn leb128_decode<'a, R: ReadBytes<'a>>(mut reader: R) -> Result<Self, LEB128DecodeError> {
let mut result = 0;
let mut shift = 0;
let byte = loop {
let byte = reader
.try_read_u8()
.map_err(|_| LEB128DecodeError::BufferOverflow)?;
if shift == 63 && byte != 0x00 && byte != !LEB128_HIGH_ORDER_BIT {
return Err(LEB128DecodeError::IntegerOverflow);
}
result |= i64::from(byte & !LEB128_HIGH_ORDER_BIT) << shift;
shift += 7;
if byte & LEB128_HIGH_ORDER_BIT == 0 {
break byte;
}
};
if shift < 8 * mem::size_of::<i64>() && (byte & LEB128_SIGN_BIT) != 0 {
result |= !0 << shift;
}
Ok(Self(result))
}
}
impl LEB128Encode for SLEB128 {
fn leb128_encode<W: WriteBytes>(self, mut writer: W) -> Result<(), LEB128EncodeError> {
let Self(mut value) = self;
let mut more = true;
while more {
let mut byte = (value as u8) & !LEB128_HIGH_ORDER_BIT;
value >>= 7;
if value == 0 && (byte & LEB128_SIGN_BIT) == 0
|| value == -1 && (byte & LEB128_SIGN_BIT) != 0
{
more = false;
} else {
byte |= LEB128_HIGH_ORDER_BIT;
}
writer
.try_write_u8(byte)
.map_err(|_| LEB128EncodeError::BufferOverflow)?;
}
Ok(())
}
}
impl LEB128 for SLEB128 {}
impl LEB128Decode for ULEB128 {
fn leb128_decode<'a, R: ReadBytes<'a>>(mut reader: R) -> Result<Self, LEB128DecodeError> {
let mut result = 0;
let mut shift = 0;
loop {
let byte = reader
.try_read_u8()
.map_err(|_| LEB128DecodeError::BufferOverflow)?;
if shift == 63 && byte > 1 {
return Err(LEB128DecodeError::IntegerOverflow);
}
result |= u64::from(byte & !LEB128_HIGH_ORDER_BIT) << shift;
if byte & LEB128_HIGH_ORDER_BIT == 0 {
return Ok(Self(result));
}
shift += 7;
}
}
}
impl LEB128Encode for ULEB128 {
fn leb128_encode<W: WriteBytes>(self, mut writer: W) -> Result<(), LEB128EncodeError> {
let Self(mut value) = self;
loop {
let mut byte = (value as u8) & !LEB128_HIGH_ORDER_BIT;
value >>= 7;
if value != 0 {
byte |= LEB128_HIGH_ORDER_BIT;
}
writer
.try_write_u8(byte)
.map_err(|_| LEB128EncodeError::BufferOverflow)?;
if value == 0 {
return Ok(());
}
}
}
}
impl LEB128 for ULEB128 {}