#![deny(missing_debug_implementations, missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
use core::{
convert::{From, TryFrom},
fmt::{self, Debug, Display, Formatter},
iter,
num::{ParseIntError as StdParseIntError, TryFromIntError as StdTryFromIntError},
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
str::FromStr,
};
#[cfg(feature = "serde")]
use serde::{
de::{Error as _, Unexpected},
Deserialize, Deserializer, Serialize,
};
pub const MAX_SAFE_INT: i64 = 0x001F_FFFF_FFFF_FFFF;
pub const MIN_SAFE_INT: i64 = -MAX_SAFE_INT;
pub const MAX_SAFE_UINT: u64 = 0x001F_FFFF_FFFF_FFFF;
#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct Int(i64);
impl Int {
pub const MIN: Self = Self(MIN_SAFE_INT);
pub const MAX: Self = Self(MAX_SAFE_INT);
#[must_use]
pub fn new(val: i64) -> Option<Self> {
if val >= MIN_SAFE_INT && val <= MAX_SAFE_INT {
Some(Self(val))
} else {
None
}
}
#[must_use]
fn new_saturating(val: i64) -> Self {
if val < MIN_SAFE_INT {
Self::MIN
} else if val > MAX_SAFE_INT {
Self::MAX
} else {
Self(val)
}
}
#[must_use]
fn new_(val: i64) -> Self {
assert!(val >= MIN_SAFE_INT);
assert!(val <= MAX_SAFE_INT);
Self(val)
}
fn assign_(&mut self, val: i64) {
assert!(val >= MIN_SAFE_INT);
assert!(val <= MAX_SAFE_INT);
*self = Self(val);
}
pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
let val = i64::from_str_radix(src, radix)?;
if val < MIN_SAFE_INT {
Err(ParseIntError {
kind: ParseIntErrorKind::Underflow,
})
} else if val > MAX_SAFE_INT {
Err(ParseIntError {
kind: ParseIntErrorKind::Overflow,
})
} else {
Ok(Self(val))
}
}
#[must_use]
#[deprecated = "Use `UInt::MIN` instead."]
pub const fn min_value() -> Self {
Self(MIN_SAFE_INT)
}
#[must_use]
#[deprecated = "Use `Int::MAX` instead."]
pub const fn max_value() -> Self {
Self(MAX_SAFE_INT)
}
#[must_use]
pub fn abs(self) -> Self {
Self(self.0.abs())
}
#[must_use]
pub const fn is_positive(self) -> bool {
self.0.is_positive()
}
#[must_use]
pub const fn is_negative(self) -> bool {
self.0.is_negative()
}
#[must_use]
pub fn checked_add(self, rhs: Self) -> Option<Self> {
self.0.checked_add(rhs.0).and_then(Self::new)
}
#[must_use]
pub fn checked_sub(self, rhs: Self) -> Option<Self> {
self.0.checked_sub(rhs.0).and_then(Self::new)
}
#[must_use]
pub fn checked_mul(self, rhs: Self) -> Option<Self> {
self.0.checked_mul(rhs.0).and_then(Self::new)
}
#[must_use]
pub fn checked_div(self, rhs: Self) -> Option<Self> {
self.0.checked_div(rhs.0).map(Self)
}
#[must_use]
pub fn checked_rem(self, rhs: Self) -> Option<Self> {
self.0.checked_rem(rhs.0).map(Self)
}
#[must_use]
pub fn checked_pow(self, exp: u32) -> Option<Self> {
self.0.checked_pow(exp).and_then(Self::new)
}
#[must_use]
pub fn saturating_add(self, rhs: Self) -> Self {
self.checked_add(rhs).unwrap_or(Self::MAX)
}
#[must_use]
pub fn saturating_sub(self, rhs: Self) -> Self {
self.checked_sub(rhs).unwrap_or(Self::MIN)
}
#[must_use]
pub fn saturating_mul(self, rhs: Self) -> Self {
Self::new_saturating(self.0.saturating_mul(rhs.0))
}
#[must_use]
pub fn saturating_pow(self, exp: u32) -> Self {
Self::new_saturating(self.0.saturating_pow(exp))
}
}
macro_rules! int_op_impl {
($trait:ident, $method:ident, $assign_trait:ident, $assign_method:ident) => {
impl $trait for Int {
type Output = Self;
fn $method(self, rhs: Self) -> Self {
Self::new_(<i64 as $trait>::$method(self.0, rhs.0))
}
}
impl $assign_trait for Int {
fn $assign_method(&mut self, other: Self) {
self.assign_(<i64 as $trait>::$method(self.0, other.0));
}
}
};
}
int_op_impl!(Add, add, AddAssign, add_assign);
int_op_impl!(Sub, sub, SubAssign, sub_assign);
int_op_impl!(Mul, mul, MulAssign, mul_assign);
int_op_impl!(Div, div, DivAssign, div_assign);
int_op_impl!(Rem, rem, RemAssign, rem_assign);
impl Neg for Int {
type Output = Self;
fn neg(self) -> Self {
Self(-self.0)
}
}
impl iter::Sum for Int {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Int>,
{
Self::new_(iter.map(|x| x.0).sum())
}
}
impl<'a> iter::Sum<&'a Int> for Int {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Int>,
{
Self::new_(iter.map(|x| x.0).sum())
}
}
impl iter::Product for Int {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Int>,
{
Self::new_(iter.map(|x| x.0).product())
}
}
impl<'a> iter::Product<&'a Int> for Int {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Int>,
{
Self::new_(iter.map(|x| x.0).product())
}
}
impl FromStr for Int {
type Err = ParseIntError;
fn from_str(src: &str) -> Result<Self, Self::Err> {
let val = i64::from_str(src)?;
if val < MIN_SAFE_INT {
Err(ParseIntError {
kind: ParseIntErrorKind::Underflow,
})
} else if val > MAX_SAFE_INT {
Err(ParseIntError {
kind: ParseIntErrorKind::Overflow,
})
} else {
Ok(Self(val))
}
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Int {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let val = i64::deserialize(deserializer)?;
Self::new(val).ok_or_else(|| {
D::Error::invalid_value(
Unexpected::Signed(val),
&"an integer between -2^53 + 1 and 2^53 - 1",
)
})
}
}
#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct UInt(u64);
impl UInt {
pub const MIN: Self = Self(0);
pub const MAX: Self = Self(MAX_SAFE_UINT);
#[must_use]
pub fn new(val: u64) -> Option<Self> {
if val <= MAX_SAFE_UINT {
Some(Self(val))
} else {
None
}
}
#[must_use]
pub fn new_wrapping(val: u64) -> Self {
Self(val & MAX_SAFE_UINT)
}
#[must_use]
fn new_saturating(val: u64) -> Self {
if val <= MAX_SAFE_UINT {
Self(val)
} else {
Self::MAX
}
}
#[must_use]
fn new_(val: u64) -> Self {
if cfg!(debug_assertions) {
assert!(val <= MAX_SAFE_UINT);
Self(val)
} else {
Self::new_wrapping(val)
}
}
fn assign_(&mut self, val: u64) {
if cfg!(debug_assertions) {
assert!(val <= MAX_SAFE_UINT);
*self = Self(val);
} else {
*self = Self::new_wrapping(val);
}
}
#[must_use]
#[deprecated = "Use `UInt::MIN` instead."]
pub const fn min_value() -> Self {
Self(0)
}
#[must_use]
#[deprecated = "Use `UInt::MAX` instead."]
pub const fn max_value() -> Self {
Self(MAX_SAFE_UINT)
}
#[must_use]
pub fn is_power_of_two(self) -> bool {
self.0.is_power_of_two()
}
#[must_use]
pub fn checked_next_power_of_two(self) -> Option<Self> {
self.0.checked_next_power_of_two().and_then(Self::new)
}
pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
let val = u64::from_str_radix(src, radix)?;
if val > MAX_SAFE_UINT {
Err(ParseIntError {
kind: ParseIntErrorKind::Overflow,
})
} else {
Ok(Self(val))
}
}
#[must_use]
pub fn checked_add(self, rhs: Self) -> Option<Self> {
self.0.checked_add(rhs.0).and_then(Self::new)
}
#[must_use]
pub fn checked_sub(self, rhs: Self) -> Option<Self> {
self.0.checked_sub(rhs.0).and_then(Self::new)
}
#[must_use]
pub fn checked_mul(self, rhs: Self) -> Option<Self> {
self.0.checked_mul(rhs.0).and_then(Self::new)
}
#[must_use]
pub fn checked_div(self, rhs: Self) -> Option<Self> {
self.0.checked_div(rhs.0).map(Self)
}
#[must_use]
pub fn checked_rem(self, rhs: Self) -> Option<Self> {
self.0.checked_rem(rhs.0).map(Self)
}
#[must_use]
pub fn checked_neg(self) -> Option<Self> {
self.0.checked_neg().map(Self)
}
#[must_use]
pub fn checked_pow(self, exp: u32) -> Option<Self> {
self.0.checked_pow(exp).and_then(Self::new)
}
#[must_use]
pub fn saturating_add(self, rhs: Self) -> Self {
self.checked_add(rhs).unwrap_or(Self::MAX)
}
#[must_use]
pub fn saturating_sub(self, rhs: Self) -> Self {
self.checked_sub(rhs).unwrap_or(Self::MIN)
}
#[must_use]
pub fn saturating_mul(self, rhs: Self) -> Self {
self.checked_mul(rhs).unwrap_or(Self::MAX)
}
#[must_use]
pub fn saturating_pow(self, exp: u32) -> Self {
Self::new_saturating(self.0.saturating_pow(exp))
}
}
macro_rules! uint_op_impl {
($trait:ident, $method:ident, $assign_trait:ident, $assign_method:ident) => {
impl $trait for UInt {
type Output = Self;
fn $method(self, rhs: Self) -> Self {
Self::new_(<u64 as $trait>::$method(self.0, rhs.0))
}
}
impl $assign_trait for UInt {
fn $assign_method(&mut self, other: Self) {
self.assign_(<u64 as $trait>::$method(self.0, other.0));
}
}
};
}
uint_op_impl!(Add, add, AddAssign, add_assign);
uint_op_impl!(Sub, sub, SubAssign, sub_assign);
uint_op_impl!(Mul, mul, MulAssign, mul_assign);
uint_op_impl!(Div, div, DivAssign, div_assign);
uint_op_impl!(Rem, rem, RemAssign, rem_assign);
impl iter::Sum for UInt {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = UInt>,
{
Self::new_(iter.map(|x| x.0).sum())
}
}
impl<'a> iter::Sum<&'a UInt> for UInt {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a UInt>,
{
Self::new_(iter.map(|x| x.0).sum())
}
}
impl iter::Product for UInt {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = UInt>,
{
Self::new_(iter.map(|x| x.0).product())
}
}
impl<'a> iter::Product<&'a UInt> for UInt {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a UInt>,
{
Self::new_(iter.map(|x| x.0).product())
}
}
impl FromStr for UInt {
type Err = ParseIntError;
fn from_str(src: &str) -> Result<Self, Self::Err> {
let val = u64::from_str(src)?;
if val > MAX_SAFE_UINT {
Err(ParseIntError {
kind: ParseIntErrorKind::Overflow,
})
} else {
Ok(Self(val))
}
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for UInt {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let val = u64::deserialize(deserializer)?;
Self::new(val).ok_or_else(|| {
D::Error::invalid_value(
Unexpected::Unsigned(val),
&"an integer between 0 and 2^53 - 1",
)
})
}
}
macro_rules! fmt_impls {
($type:ident) => {
impl Display for $type {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl Debug for $type {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}
};
}
fmt_impls!(Int);
fmt_impls!(UInt);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseIntError {
kind: ParseIntErrorKind,
}
#[derive(Debug, Clone, PartialEq, Eq)]
enum ParseIntErrorKind {
Overflow,
Underflow,
Unknown(StdParseIntError),
}
impl From<StdParseIntError> for ParseIntError {
fn from(e: StdParseIntError) -> Self {
ParseIntError {
kind: ParseIntErrorKind::Unknown(e),
}
}
}
impl Display for ParseIntError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match &self.kind {
ParseIntErrorKind::Overflow => f.write_str("number too large to fit in target type"),
ParseIntErrorKind::Underflow => f.write_str("number too small to fit in target type"),
ParseIntErrorKind::Unknown(e) => write!(f, "{}", e),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for ParseIntError {}
#[derive(Clone)]
pub struct TryFromIntError {
_private: (),
}
impl TryFromIntError {
fn new() -> Self {
Self { _private: () }
}
}
impl Display for TryFromIntError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str("out of range integral type conversion attempted")
}
}
impl Debug for TryFromIntError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str("TryFromIntError")
}
}
#[cfg(feature = "std")]
impl std::error::Error for TryFromIntError {}
macro_rules! convert_impls {
($type:ident, $t8:ident, $t16:ident, $t32:ident, $t64:ident, $t128:ident) => {
impl From<$t8> for $type {
fn from(val: $t8) -> Self {
Self($t64::from(val))
}
}
impl From<$t16> for $type {
fn from(val: $t16) -> Self {
Self($t64::from(val))
}
}
impl From<$t32> for $type {
fn from(val: $t32) -> Self {
Self($t64::from(val))
}
}
impl TryFrom<$t64> for $type {
type Error = TryFromIntError;
fn try_from(val: $t64) -> Result<Self, TryFromIntError> {
Self::new(val).ok_or_else(TryFromIntError::new)
}
}
impl TryFrom<$t128> for $type {
type Error = TryFromIntError;
fn try_from(val: $t128) -> Result<Self, TryFromIntError> {
$t64::try_from(val)
.map_err(|_| TryFromIntError::new())
.and_then($type::try_from)
}
}
impl TryFrom<$type> for $t8 {
type Error = StdTryFromIntError;
fn try_from(val: $type) -> Result<Self, StdTryFromIntError> {
Self::try_from(val.0)
}
}
impl TryFrom<$type> for $t16 {
type Error = StdTryFromIntError;
fn try_from(val: $type) -> Result<Self, StdTryFromIntError> {
Self::try_from(val.0)
}
}
impl TryFrom<$type> for $t32 {
type Error = StdTryFromIntError;
fn try_from(val: $type) -> Result<Self, StdTryFromIntError> {
Self::try_from(val.0)
}
}
impl From<$type> for $t64 {
fn from(val: $type) -> Self {
val.0
}
}
impl From<$type> for $t128 {
fn from(val: $type) -> Self {
$t128::from(val.0)
}
}
impl From<$type> for f64 {
fn from(val: $type) -> Self {
val.0 as f64
}
}
};
}
convert_impls!(Int, i8, i16, i32, i64, i128);
convert_impls!(UInt, u8, u16, u32, u64, u128);
impl From<u8> for Int {
fn from(val: u8) -> Self {
Self(i64::from(val))
}
}
impl From<u16> for Int {
fn from(val: u16) -> Self {
Self(i64::from(val))
}
}
impl From<u32> for Int {
fn from(val: u32) -> Self {
Self(i64::from(val))
}
}
impl TryFrom<u64> for Int {
type Error = TryFromIntError;
fn try_from(val: u64) -> Result<Self, TryFromIntError> {
if val <= MAX_SAFE_UINT {
Ok(Self(val as i64))
} else {
Err(TryFromIntError::new())
}
}
}
impl TryFrom<u128> for Int {
type Error = TryFromIntError;
fn try_from(val: u128) -> Result<Self, TryFromIntError> {
if val <= u128::from(MAX_SAFE_UINT) {
Ok(Self(val as i64))
} else {
Err(TryFromIntError::new())
}
}
}
impl TryFrom<i8> for UInt {
type Error = TryFromIntError;
fn try_from(val: i8) -> Result<Self, TryFromIntError> {
if val >= 0 {
Ok(Self(val as u64))
} else {
Err(TryFromIntError::new())
}
}
}
impl TryFrom<i16> for UInt {
type Error = TryFromIntError;
fn try_from(val: i16) -> Result<Self, TryFromIntError> {
if val >= 0 {
Ok(Self(val as u64))
} else {
Err(TryFromIntError::new())
}
}
}
impl TryFrom<i32> for UInt {
type Error = TryFromIntError;
fn try_from(val: i32) -> Result<Self, TryFromIntError> {
if val >= 0 {
Ok(Self(val as u64))
} else {
Err(TryFromIntError::new())
}
}
}
impl TryFrom<i64> for UInt {
type Error = TryFromIntError;
fn try_from(val: i64) -> Result<Self, TryFromIntError> {
if val >= 0 && val <= MAX_SAFE_INT {
Ok(Self(val as u64))
} else {
Err(TryFromIntError::new())
}
}
}
impl TryFrom<i128> for UInt {
type Error = TryFromIntError;
fn try_from(val: i128) -> Result<Self, TryFromIntError> {
if val >= 0 && val <= i128::from(MAX_SAFE_INT) {
Ok(Self(val as u64))
} else {
Err(TryFromIntError::new())
}
}
}
#[cfg(feature = "rocket_04")]
macro_rules! rocket_04_impls {
($type:ident) => {
impl<'v> rocket_04::request::FromFormValue<'v> for $type {
type Error = &'v rocket_04::http::RawStr;
fn from_form_value(
form_value: &'v rocket_04::http::RawStr,
) -> Result<Self, Self::Error> {
form_value.parse::<$type>().map_err(|_| form_value)
}
}
impl<'r> rocket_04::request::FromParam<'r> for $type {
type Error = &'r rocket_04::http::RawStr;
fn from_param(param: &'r rocket_04::http::RawStr) -> Result<Self, Self::Error> {
param.parse::<$type>().map_err(|_| param)
}
}
};
}
#[cfg(feature = "rocket_04")]
rocket_04_impls!(Int);
#[cfg(feature = "rocket_04")]
rocket_04_impls!(UInt);
#[cfg(test)]
mod tests {
use super::{Int, UInt, MAX_SAFE_UINT};
#[test]
fn int_ops() {
assert_eq!(Int::from(5) + Int::from(3), Int::from(8));
assert_eq!(Int::from(1) - Int::from(2), Int::from(-1));
assert_eq!(Int::from(4) * Int::from(-7), Int::from(-28));
assert_eq!(Int::from(5) / Int::from(2), Int::from(2));
assert_eq!(Int::from(9) % Int::from(3), Int::from(0));
}
#[test]
fn int_assign_ops() {
let mut int = Int::from(1);
int += Int::from(1);
assert_eq!(int, Int::from(2));
int -= Int::from(-1);
assert_eq!(int, Int::from(3));
int *= Int::from(3);
assert_eq!(int, Int::from(9));
int /= Int::from(3);
assert_eq!(int, Int::from(3));
int %= Int::from(2);
assert_eq!(int, Int::from(1));
}
#[test]
#[should_panic]
fn int_underflow_panic() {
let _ = Int::MIN - Int::from(1);
}
#[test]
#[should_panic]
fn int_overflow_panic() {
let _ = Int::MAX + Int::from(1);
}
#[test]
fn uint_ops() {
assert_eq!(UInt::from(5u32) + UInt::from(3u32), UInt::from(8u32));
assert_eq!(UInt::from(2u32) - UInt::from(1u32), UInt::from(1u32));
assert_eq!(UInt::from(4u32) * UInt::from(2u32), UInt::from(8u32));
assert_eq!(UInt::from(5u32) / UInt::from(2u32), UInt::from(2u32));
assert_eq!(UInt::from(11u32) % UInt::from(4u32), UInt::from(3u32));
}
#[test]
fn uint_assign_ops() {
let mut uint = UInt::from(1u32);
uint += UInt::from(3u32);
assert_eq!(uint, UInt::from(4u32));
uint -= UInt::from(1u32);
assert_eq!(uint, UInt::from(3u32));
uint *= UInt::from(3u32);
assert_eq!(uint, UInt::from(9u32));
uint /= UInt::from(3u32);
assert_eq!(uint, UInt::from(3u32));
uint %= UInt::from(2u32);
assert_eq!(uint, UInt::from(1u32));
}
#[test]
fn uint_wrapping_new() {
assert_eq!(UInt::new_wrapping(MAX_SAFE_UINT + 1), UInt::from(0u32));
}
#[test]
#[cfg_attr(debug_assertions, ignore)]
fn uint_underflow_wrap() {
assert_eq!(UInt::from(0u32) - UInt::from(1u32), UInt::MAX);
}
#[test]
#[cfg_attr(debug_assertions, ignore)]
fn uint_overflow_wrap() {
assert_eq!(UInt::MAX + UInt::from(1u32), UInt::from(0u32));
assert_eq!(UInt::MAX + UInt::from(5u32), UInt::from(4u32));
}
#[test]
#[should_panic]
#[cfg_attr(not(debug_assertions), ignore)]
fn uint_underflow_panic() {
let _ = UInt::from(0u32) - UInt::from(1u32);
}
#[test]
#[should_panic]
#[cfg_attr(not(debug_assertions), ignore)]
fn uint_overflow_panic() {
let _ = UInt::MAX + UInt::from(1u32);
}
}