use std::hash::Hash;
use derive_more::{Binary, Display, Neg, Not};
use std::ops::{BitAnd, BitOr, BitXor, Neg, Rem, Shl, Shr};
use std::str::FromStr;
pub mod float;
pub mod ops;
use crate::var_num::ParseError;
pub use float::VarFloat;
#[derive(Copy, Binary, Clone, Debug, PartialEq, Display, Not, Neg, Hash, Eq, PartialOrd)]
pub enum VarInt {
I8(i8),
I16(i16),
I32(i32),
I64(i64),
I128(i128),
}
impl FromStr for VarInt {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let f: i128 = match s.parse() {
Ok(f) => f,
Err(e) => return Err(ParseError::InvalidNumber(format!("Invalid Int: {}", e))),
};
Ok(f.into())
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for VarInt {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
VarInt::I8(v) => serializer.serialize_i8(*v),
VarInt::I16(v) => serializer.serialize_i16(*v),
VarInt::I32(v) => serializer.serialize_i32(*v),
VarInt::I64(v) => serializer.serialize_i64(*v),
VarInt::I128(v) => serializer.serialize_i128(*v),
}
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for VarInt {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let i = i128::deserialize(deserializer)?;
Ok(i.into())
}
}
impl VarInt {
#[inline]
pub fn reverse(&self) -> Self {
match self {
VarInt::I8(i) => VarInt::I8(i.reverse_bits()),
VarInt::I16(i) => VarInt::I16(i.reverse_bits()),
VarInt::I32(i) => VarInt::I32(i.reverse_bits()),
VarInt::I64(i) => VarInt::I64(i.reverse_bits()),
VarInt::I128(i) => VarInt::I128(i.reverse_bits()),
}
}
#[inline]
pub fn zero() -> Self {
VarInt::I8(0)
}
#[inline]
pub fn one() -> Self {
VarInt::I8(1)
}
#[inline]
pub fn is_one(&self) -> bool {
match self {
VarInt::I8(i) => *i == 1,
VarInt::I16(i) => *i == 1,
VarInt::I32(i) => *i == 1,
VarInt::I64(i) => *i == 1,
VarInt::I128(i) => *i == 1,
}
}
#[inline]
pub fn is_non_zero(&self) -> bool {
match self {
VarInt::I8(i) => *i != 0,
VarInt::I16(i) => *i != 0,
VarInt::I32(i) => *i != 0,
VarInt::I64(i) => *i != 0,
VarInt::I128(i) => *i != 0,
}
}
#[inline]
pub fn is_zero(&self) -> bool {
match self {
VarInt::I8(i) => *i == 0,
VarInt::I16(i) => *i == 0,
VarInt::I32(i) => *i == 0,
VarInt::I64(i) => *i == 0,
VarInt::I128(i) => *i == 0,
}
}
#[inline]
pub fn to_float(&self) -> VarFloat {
match self {
VarInt::I8(v) => VarFloat::F32(*v as f32),
VarInt::I16(v) => VarFloat::F32(*v as f32),
VarInt::I32(v) => VarFloat::F32(*v as f32),
VarInt::I64(v) => VarFloat::F64(*v as f64),
VarInt::I128(v) => VarFloat::F64(*v as f64),
}
}
#[inline]
pub fn to_uint(&self) -> VarUInt {
match self {
VarInt::I8(v) => VarUInt::U8(*v as u8),
VarInt::I16(v) => VarUInt::U16(*v as u16),
VarInt::I32(v) => VarUInt::U32(*v as u32),
VarInt::I64(v) => VarUInt::U64(*v as u64),
VarInt::I128(v) => VarUInt::U128(*v as u128),
}
}
}
#[derive(Copy, Binary, Clone, Debug, PartialEq, Display, Not, Hash, Eq, PartialOrd)]
pub enum VarUInt {
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
}
impl FromStr for VarUInt {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let f: u128 = match s.parse() {
Ok(f) => f,
Err(e) => return Err(ParseError::InvalidNumber(format!("Invalid UInt: {}", e))),
};
Ok(f.into())
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for VarUInt {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
VarUInt::U8(v) => serializer.serialize_u8(*v),
VarUInt::U16(v) => serializer.serialize_u16(*v),
VarUInt::U32(v) => serializer.serialize_u32(*v),
VarUInt::U64(v) => serializer.serialize_u64(*v),
VarUInt::U128(v) => serializer.serialize_u128(*v),
}
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for VarUInt {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let i = u128::deserialize(deserializer)?;
Ok(i.into())
}
}
impl VarUInt {
#[inline]
pub fn reverse(&self) -> Self {
match self {
VarUInt::U8(i) => VarUInt::U8(i.reverse_bits()),
VarUInt::U16(i) => VarUInt::U16(i.reverse_bits()),
VarUInt::U32(i) => VarUInt::U32(i.reverse_bits()),
VarUInt::U64(i) => VarUInt::U64(i.reverse_bits()),
VarUInt::U128(i) => VarUInt::U128(i.reverse_bits()),
}
}
#[inline]
pub fn zero() -> Self {
VarUInt::U8(0)
}
#[inline]
pub fn one() -> Self {
VarUInt::U8(1)
}
#[inline]
pub fn is_non_zero(&self) -> bool {
match self {
VarUInt::U8(i) => *i != 0,
VarUInt::U16(i) => *i != 0,
VarUInt::U32(i) => *i != 0,
VarUInt::U64(i) => *i != 0,
VarUInt::U128(i) => *i != 0,
}
}
#[inline]
pub fn is_one(&self) -> bool {
match self {
VarUInt::U8(i) => *i == 1,
VarUInt::U16(i) => *i == 1,
VarUInt::U32(i) => *i == 1,
VarUInt::U64(i) => *i == 1,
VarUInt::U128(i) => *i == 1,
}
}
#[inline]
pub fn is_zero(&self) -> bool {
match self {
VarUInt::U8(i) => *i == 0,
VarUInt::U16(i) => *i == 0,
VarUInt::U32(i) => *i == 0,
VarUInt::U64(i) => *i == 0,
VarUInt::U128(i) => *i == 0,
}
}
#[inline]
pub fn to_int(&self) -> VarInt {
match self {
VarUInt::U8(v) => VarInt::I8(*v as i8),
VarUInt::U16(v) => VarInt::I16(*v as i16),
VarUInt::U32(v) => VarInt::I32(*v as i32),
VarUInt::U64(v) => VarInt::I64(*v as i64),
VarUInt::U128(v) => VarInt::I128(*v as i128),
}
}
#[inline]
pub fn to_float(&self) -> VarFloat {
match self {
VarUInt::U8(v) => VarFloat::F32(*v as f32),
VarUInt::U16(v) => VarFloat::F32(*v as f32),
VarUInt::U32(v) => VarFloat::F32(*v as f32),
VarUInt::U64(v) => VarFloat::F64(*v as f64),
VarUInt::U128(v) => VarFloat::F64(*v as f64),
}
}
}
macro_rules! impl_op {
($trait:ident: $method:tt($op:tt) -> $enm:ty, $byl:ident, $by:ty, $wrl:ident, $wrd:ty, $dll:ident, $dbl:ty, $qdl:ident, $qad:ty, $ocl:ident, $oct:ty) => {
impl $trait for $enm {
type Output = $enm;
#[inline]
#[deny(arithmetic_overflow)]
fn $method(self, rhs: Self) -> Self::Output {
match Self::normalize(self, rhs) {
(Self::$byl(lhs), Self::$byl(rhs)) => (lhs $op rhs).into(),
(Self::$wrl(lhs), Self::$wrl(rhs)) => (lhs $op rhs).into(),
(Self::$dll(lhs), Self::$dll(rhs)) => (lhs $op rhs).into(),
(Self::$qdl(lhs), Self::$qdl(rhs)) => (lhs $op rhs).into(),
(Self::$ocl(lhs), Self::$ocl(rhs)) => (lhs $op rhs).into(),
(lhs, rhs) => panic!("normalization failed: {} {} {}", lhs, stringify!($op), rhs),
}
}
}
};
}
impl Neg for VarUInt {
type Output = VarUInt;
fn neg(self) -> Self::Output {
match self {
VarUInt::U8(v) => VarUInt::U8(!v + 1),
VarUInt::U16(v) => VarUInt::U16(!v + 1),
VarUInt::U32(v) => VarUInt::U32(!v + 1),
VarUInt::U64(v) => VarUInt::U64(!v + 1),
VarUInt::U128(v) => VarUInt::U128(!v + 1),
}
}
}
macro_rules! from_inner {
($enm:ty = $byl:ident:$by:ty, $wrl:ident:$wrd:ty, $dll:ident:$dbl:ty, $qdl:ident:$qad:ty, $ocl:ident:$oct:ty) => {
impl From<$by> for $enm {
fn from(v: $by) -> Self {
Self::$byl(v)
}
}
impl From<$wrd> for $enm {
fn from(v: $wrd) -> Self {
if v <= <$by>::MAX as $wrd {
Self::$byl(v as $by)
} else {
Self::$wrl(v)
}
}
}
impl From<$dbl> for $enm {
fn from(v: $dbl) -> Self {
if v <= <$wrd>::MAX as $dbl {
if v <= <$by>::MAX as $dbl {
Self::$byl(v as $by)
} else {
Self::$wrl(v as $wrd)
}
} else {
Self::$dll(v)
}
}
}
impl From<$qad> for $enm {
fn from(v: $qad) -> Self {
if v <= <$dbl>::MAX as $qad {
if v <= <$wrd>::MAX as $qad {
if v <= <$by>::MAX as $qad {
Self::$byl(v as $by)
} else {
Self::$wrl(v as $wrd)
}
} else {
Self::$dll(v as $dbl)
}
} else {
Self::$qdl(v)
}
}
}
impl From<$oct> for $enm {
fn from(v: $oct) -> Self {
if v <= <$qad>::MAX as $oct {
if v <= <$qad>::MAX as $oct {
if v <= <$wrd>::MAX as $oct {
if v <= <$by>::MAX as $oct {
Self::$byl(v as $by)
} else {
Self::$wrl(v as $wrd)
}
} else {
Self::$dll(v as $dbl)
}
} else {
Self::$qdl(v as $qad)
}
} else {
Self::$ocl(v)
}
}
}
impl_op!(Rem: rem(%) -> $enm, $byl, $by, $wrl, $wrd, $dll, $dbl, $qdl, $qad, $ocl, $oct);
impl_op!(BitAnd: bitand(&) -> $enm, $byl, $by, $wrl, $wrd, $dll, $dbl, $qdl, $qad, $ocl, $oct);
impl_op!(BitOr: bitor(|) -> $enm, $byl, $by, $wrl, $wrd, $dll, $dbl, $qdl, $qad, $ocl, $oct);
impl_op!(BitXor: bitxor(^) -> $enm, $byl, $by, $wrl, $wrd, $dll, $dbl, $qdl, $qad, $ocl, $oct);
impl_op!(Shl: shl(<<) -> $enm, $byl, $by, $wrl, $wrd, $dll, $dbl, $qdl, $qad, $ocl, $oct);
impl_op!(Shr: shr(>>) -> $enm, $byl, $by, $wrl, $wrd, $dll, $dbl, $qdl, $qad, $ocl, $oct);
impl $enm {
#[inline]
pub fn upgrade(&self) -> Self {
match self {
Self::$byl(v) => Self::$wrl(*v as $wrd),
Self::$wrl(v) => Self::$dll(*v as $dbl),
Self::$dll(v) => Self::$qdl(*v as $qad),
Self::$qdl(v) => Self::$ocl(*v as $oct),
Self::$ocl(o) => {
panic!("cannot upgrade octal value: {}", o)
},
}
}
#[inline]
pub fn downgrade(&self) -> Self {
match self {
Self::$byl(v) => panic!("cannot downgrade byte value: {}", v),
Self::$wrl(v) => Self::$byl(*v as $by),
Self::$dll(v) => Self::$wrl(*v as $wrd),
Self::$qdl(v) => Self::$dll(*v as $dbl),
Self::$ocl(v) => Self::$qdl(*v as $qad),
}
}
#[inline]
pub fn to_bytes(&self) -> Vec<u8> {
match self {
Self::$byl(v) => vec![*v as u8],
Self::$wrl(v) => v.to_be_bytes().to_vec(),
Self::$dll(v) => v.to_be_bytes().to_vec(),
Self::$qdl(v) => v.to_be_bytes().to_vec(),
Self::$ocl(v) => v.to_be_bytes().to_vec(),
}
}
#[inline]
pub fn from_bytes(raw: Vec<u8>) -> Self {
match raw.len() {
1 => Self::$byl(raw[0] as $by),
2 => {
let mut bytes = [0; 2];
bytes.copy_from_slice(&raw);
Self::$wrl(<$wrd>::from_be_bytes(bytes))
},
4 => {
let mut bytes = [0; 4];
bytes.copy_from_slice(&raw);
Self::$dll(<$dbl>::from_be_bytes(bytes))
},
8 => {
let mut bytes = [0; 8];
bytes.copy_from_slice(&raw);
Self::$qdl(<$qad>::from_be_bytes(bytes))
},
16 => {
let mut bytes = [0; 16];
bytes.copy_from_slice(&raw);
Self::$ocl(<$oct>::from_be_bytes(bytes))
},
_ => panic!("invalid byte length: {}", raw.len()),
}
}
pub fn normalize(lhs: Self, rhs: Self) -> (Self, Self) {
match (lhs, rhs) {
(Self::$ocl(lhs), Self::$ocl(rhs)) => (Self::$ocl(lhs), Self::$ocl(rhs)),
(Self::$ocl(lhs), rhs) => Self::normalize(Self::$ocl(lhs), rhs.upgrade()),
(lhs, Self::$ocl(rhs)) => Self::normalize(lhs.upgrade(), Self::$ocl(rhs)),
(Self::$qdl(lhs), Self::$qdl(rhs)) => (Self::$qdl(lhs), Self::$qdl(rhs)),
(Self::$qdl(lhs), rhs) => Self::normalize(Self::$qdl(lhs), rhs.upgrade()),
(lhs, Self::$qdl(rhs)) => Self::normalize(lhs.upgrade(), Self::$qdl(rhs)),
(Self::$dll(lhs), Self::$dll(rhs)) => (Self::$dll(lhs), Self::$dll(rhs)),
(Self::$dll(lhs), rhs) => Self::normalize(Self::$dll(lhs), rhs.upgrade()),
(lhs, Self::$dll(rhs)) => Self::normalize(lhs.upgrade(), Self::$dll(rhs)),
(Self::$wrl(lhs), Self::$wrl(rhs)) => (Self::$wrl(lhs), Self::$wrl(rhs)),
(Self::$wrl(lhs), rhs) => Self::normalize(Self::$wrl(lhs), rhs.upgrade()),
(lhs, Self::$wrl(rhs)) => Self::normalize(lhs.upgrade(), Self::$wrl(rhs)),
(Self::$byl(lhs), Self::$byl(rhs)) => (Self::$byl(lhs), Self::$byl(rhs)),
}
}
}
};
}
from_inner!(VarInt = I8: i8, I16: i16, I32: i32, I64: i64, I128: i128);
from_inner!(VarUInt = U8: u8, U16: u16, U32: u32, U64: u64, U128: u128);
macro_rules! from_cast {
($($enm:ident: $($t:ty as $to:ty)*),*) => {
$(
$(
impl From<$t> for $enm {
#[inline]
fn from(value: $t) -> Self {
(value as $to).into()
}
}
)*
)*
}
}
from_cast! {
VarUInt: usize as u64,
VarInt: isize as i64
}
from_cast! {
VarUInt: bool as u8,
VarInt: bool as i8
}