use core::ops::{BitAnd, BitXor, Neg, Shl, Shr};
use crate::int::ByteOrder;
use crate::reader::Reader;
use crate::writer::Writer;
pub trait Unsigned:
Sized
+ Copy
+ Shr<u32, Output = Self>
+ Shl<u32, Output = Self>
+ BitXor<Self, Output = Self>
+ BitAnd<Self, Output = Self>
+ PartialOrd<Self>
+ Ord
{
const ONE: Self;
const BYTES: u8;
type Signed: Signed;
fn signed(self) -> Self::Signed;
fn from_byte(byte: u8) -> Self;
fn as_byte(self) -> u8;
fn is_smaller_than(self, byte: u8) -> bool;
fn is_zero(self) -> bool;
fn checked_shr(self, value: u32) -> Option<Self>;
fn checked_shl(self, value: u32) -> Option<Self>;
fn checked_add(self, value: Self) -> Option<Self>;
}
pub trait ByteOrderIo: Unsigned {
fn write_bytes_unsigned<W, B>(self, writer: W) -> Result<(), W::Error>
where
W: Writer,
B: ByteOrder;
fn read_bytes_unsigned<'de, R, B>(reader: R) -> Result<Self, R::Error>
where
R: Reader<'de>,
B: ByteOrder;
}
pub trait Signed:
Sized
+ Copy
+ Neg<Output = Self>
+ Shr<u32, Output = Self>
+ Shl<u32, Output = Self>
+ BitXor<Self, Output = Self>
{
const BITS: u32;
type Unsigned: Unsigned;
fn unsigned(self) -> Self::Unsigned;
}
macro_rules! implement {
($signed:ty, $unsigned:ty) => {
impl Signed for $signed {
const BITS: u32 = <$signed>::BITS;
type Unsigned = $unsigned;
fn unsigned(self) -> Self::Unsigned {
self as $unsigned
}
}
impl Unsigned for $unsigned {
const ONE: Self = 1;
const BYTES: u8 = (<$unsigned>::BITS / 8) as u8;
type Signed = $signed;
#[inline]
fn signed(self) -> Self::Signed {
self as $signed
}
#[inline]
fn from_byte(byte: u8) -> Self {
byte as $unsigned
}
#[inline]
fn as_byte(self) -> u8 {
self as u8
}
#[inline]
fn is_smaller_than(self, b: u8) -> bool {
self < b as $unsigned
}
#[inline]
fn is_zero(self) -> bool {
self == 0
}
#[inline]
fn checked_shr(self, value: u32) -> Option<Self> {
self.checked_shr(value)
}
#[inline]
fn checked_shl(self, value: u32) -> Option<Self> {
self.checked_shl(value)
}
#[inline]
fn checked_add(self, value: Self) -> Option<Self> {
self.checked_add(value)
}
}
};
}
macro_rules! implement_io {
($signed:ty, $unsigned:ty, $read:ident, $write:ident) => {
implement!($signed, $unsigned);
impl ByteOrderIo for $unsigned {
#[inline]
fn write_bytes_unsigned<W, B>(self, mut writer: W) -> Result<(), W::Error>
where
W: Writer,
B: ByteOrder,
{
writer.write_array(B::$write(self))
}
#[inline]
fn read_bytes_unsigned<'de, R, B>(mut reader: R) -> Result<Self, R::Error>
where
R: Reader<'de>,
B: ByteOrder,
{
Ok(B::$read(reader.read_array()?))
}
}
};
}
implement_io!(i8, u8, read_u8, write_u8);
implement_io!(i16, u16, read_u16, write_u16);
implement_io!(i32, u32, read_u32, write_u32);
implement_io!(i64, u64, read_u64, write_u64);
implement_io!(i128, u128, read_u128, write_u128);
implement!(isize, usize);