mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2025-04-27 23:44:55 +00:00
1859 lines
64 KiB
Rust
1859 lines
64 KiB
Rust
// Take a look at the license at the top of the repository in the LICENSE file.
|
|
|
|
macro_rules! impl_trait_op_same(
|
|
($typ:ty, $op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident) => {
|
|
impl std::ops::$op for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn $op_name(self, rhs: $typ) -> Self {
|
|
Self(self.0.$op_name(rhs.0))
|
|
}
|
|
}
|
|
|
|
impl std::ops::$op_assign for $typ {
|
|
#[inline]
|
|
fn $op_assign_name(&mut self, rhs: $typ) {
|
|
self.0.$op_assign_name(rhs.0)
|
|
}
|
|
}
|
|
};
|
|
);
|
|
|
|
macro_rules! impl_non_trait_op_same(
|
|
($typ:ty, $inner:ty) => {
|
|
impl $typ {
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub const fn checked_add(self, rhs: Self) -> Option<Self> {
|
|
match self.0.checked_add(rhs.0) {
|
|
Some(res) if res <= Self::MAX.0 => Some(Self(res)),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub const fn saturating_add(self, rhs: Self) -> Self {
|
|
let res = self.0.saturating_add(rhs.0);
|
|
if res < Self::MAX.0 {
|
|
Self(res)
|
|
} else {
|
|
Self::MAX
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
|
|
let self_u128 = self.0 as u128;
|
|
let rhs_128 = rhs.0 as u128;
|
|
let res_u128 = self_u128 + rhs_128;
|
|
if res_u128 <= Self::MAX.0 as u128 {
|
|
(Self(<$inner>::try_from(res_u128).unwrap()), false)
|
|
} else {
|
|
(Self(<$inner>::try_from((res_u128 - Self::MAX.0 as u128 - 1) as u64).unwrap()), true)
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn wrapping_add(self, rhs: Self) -> Self {
|
|
self.overflowing_add(rhs).0
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
// FIXME Can't use `map` in a `const fn` as of rustc 1.53.0-beta.2
|
|
#[allow(clippy::manual_map)]
|
|
pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
|
|
match self.0.checked_sub(rhs.0) {
|
|
Some(res) => Some(Self(res)),
|
|
None => None,
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub const fn saturating_sub(self, rhs: Self) -> Self {
|
|
Self(self.0.saturating_sub(rhs.0))
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
|
|
if self.0 >= rhs.0 {
|
|
(Self(self.0 - rhs.0), false)
|
|
} else {
|
|
(Self(Self::MAX.0 - rhs.0 + self.0 + 1), true)
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub const fn wrapping_sub(self, rhs: Self) -> Self {
|
|
self.overflowing_sub(rhs).0
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn absdiff(self, rhs: Self) -> Self {
|
|
if self > rhs {
|
|
self - rhs
|
|
} else {
|
|
rhs - self
|
|
}
|
|
}
|
|
|
|
}
|
|
};
|
|
);
|
|
|
|
macro_rules! impl_trait_op_inner_type(
|
|
($typ:ty, $inner:ty, $op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident) => {
|
|
impl std::ops::$op<$inner> for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn $op_name(self, rhs: $inner) -> Self {
|
|
Self(self.0.$op_name(rhs))
|
|
}
|
|
}
|
|
|
|
impl std::ops::$op_assign<$inner> for $typ {
|
|
#[inline]
|
|
fn $op_assign_name(&mut self, rhs: $inner) {
|
|
self.0.$op_assign_name(rhs)
|
|
}
|
|
}
|
|
};
|
|
);
|
|
|
|
macro_rules! impl_non_trait_op_inner_type(
|
|
($typ:ty, $inner:ty) => {
|
|
impl $typ {
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub const fn checked_div(self, rhs: $inner) -> Option<Self> {
|
|
match self.0.checked_div(rhs) {
|
|
Some(val) => Some(Self(val)),
|
|
None => None,
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub const fn saturating_div(self, rhs: $inner) -> Self {
|
|
Self(self.0.saturating_div(rhs))
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub const fn checked_mul(self, rhs: $inner) -> Option<Self> {
|
|
match self.0.checked_mul(rhs) {
|
|
Some(res) if res <= Self::MAX.0 => Some(Self(res)),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub const fn saturating_mul(self, rhs: $inner) -> Self {
|
|
let res = self.0.saturating_mul(rhs);
|
|
if res < Self::MAX.0 {
|
|
Self(res)
|
|
} else {
|
|
Self::MAX
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn overflowing_mul(self, rhs: $inner) -> (Self, bool) {
|
|
let self_u128 = self.0 as u128;
|
|
let rhs_128 = rhs as u128;
|
|
let res_u128 = self_u128 * rhs_128;
|
|
if res_u128 <= Self::MAX.0 as u128 {
|
|
(Self(<$inner>::try_from(res_u128).unwrap()), false)
|
|
} else {
|
|
(Self(<$inner>::try_from((res_u128 - Self::MAX.0 as u128 - 1) as u64).unwrap()), true)
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn wrapping_mul(self, rhs: $inner) -> Self {
|
|
self.overflowing_mul(rhs).0
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub const fn checked_rem(self, rhs: $inner) -> Option<Self> {
|
|
match self.0.checked_rem(rhs) {
|
|
Some(val) => Some(Self(val)),
|
|
None => None,
|
|
}
|
|
}
|
|
}
|
|
};
|
|
);
|
|
|
|
macro_rules! impl_unsigned_int_into_signed(
|
|
($typ:ty) => {
|
|
impl crate::format::SignedIntrinsic for $typ {}
|
|
|
|
impl crate::format::UnsignedIntoSigned for $typ {
|
|
type Signed = crate::Signed<$typ>;
|
|
|
|
#[inline]
|
|
fn into_positive(self) -> Self::Signed {
|
|
crate::Signed::Positive(self)
|
|
}
|
|
|
|
#[inline]
|
|
fn into_negative(self) -> Self::Signed {
|
|
crate::Signed::Negative(self)
|
|
}
|
|
}
|
|
|
|
impl crate::format::UnsignedIntoSigned for Option<$typ> {
|
|
type Signed = Option<crate::Signed<$typ>>;
|
|
|
|
#[inline]
|
|
fn into_positive(self) -> Self::Signed {
|
|
Some(self?.into_positive())
|
|
}
|
|
|
|
#[inline]
|
|
fn into_negative(self) -> Self::Signed {
|
|
Some(self?.into_negative())
|
|
}
|
|
}
|
|
|
|
impl From<$typ> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn from(v: $typ) -> crate::Signed<$typ> {
|
|
crate::Signed::Positive(v)
|
|
}
|
|
}
|
|
};
|
|
|
|
($typ:ty, $inner:ty) => {
|
|
impl_unsigned_int_into_signed!($typ);
|
|
|
|
impl crate::Signed<$typ> {
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns a `Signed` containing the inner type of `self`.
|
|
#[inline]
|
|
pub fn into_inner_signed(self) -> crate::Signed<$inner> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(new_type) => Positive(*new_type),
|
|
Negative(new_type) => Negative(*new_type),
|
|
}
|
|
}
|
|
}
|
|
};
|
|
);
|
|
|
|
macro_rules! impl_common_ops_for_newtype_uint(
|
|
($typ:ty, $inner:ty) => {
|
|
impl_common_ops_for_newtype_uint!($typ, $inner, one: 1);
|
|
};
|
|
|
|
($typ:ty, $inner:ty, one: $one:expr$(,)?) => {
|
|
impl $typ {
|
|
pub const ZERO: Self = Self(0);
|
|
pub const NONE: Option<Self> = None;
|
|
// rustdoc-stripper-ignore-next
|
|
/// The unitary value.
|
|
pub const ONE: Self = Self($one);
|
|
|
|
pub const MAX_SIGNED: crate::Signed::<$typ> = crate::Signed::Positive(Self::MAX);
|
|
pub const MIN_SIGNED: crate::Signed::<$typ> = crate::Signed::Negative(Self::MAX);
|
|
|
|
#[inline]
|
|
pub const fn is_zero(self) -> bool {
|
|
self.0 == Self::ZERO.0
|
|
}
|
|
}
|
|
|
|
impl std::ops::Deref for $typ {
|
|
type Target = $inner;
|
|
|
|
#[inline]
|
|
fn deref(&self) -> &$inner {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl AsRef<$inner> for $typ {
|
|
#[inline]
|
|
fn as_ref(&self) -> &$inner {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl From<$typ> for $inner {
|
|
fn from(v: $typ) -> $inner {
|
|
v.0
|
|
}
|
|
}
|
|
|
|
impl_trait_op_same!($typ, Add, add, AddAssign, add_assign);
|
|
impl_trait_op_same!($typ, Sub, sub, SubAssign, sub_assign);
|
|
impl std::ops::Div for $typ {
|
|
type Output = $inner;
|
|
#[inline]
|
|
fn div(self, rhs: $typ) -> $inner {
|
|
self.0.div(rhs.0)
|
|
}
|
|
}
|
|
impl std::ops::Rem for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn rem(self, rhs: Self) -> Self {
|
|
Self(self.0.rem(rhs.0))
|
|
}
|
|
}
|
|
|
|
impl_non_trait_op_same!($typ, $inner);
|
|
|
|
impl_trait_op_inner_type!($typ, $inner, Mul, mul, MulAssign, mul_assign);
|
|
impl std::ops::Mul<$typ> for $inner {
|
|
type Output = $typ;
|
|
#[inline]
|
|
fn mul(self, rhs: $typ) -> $typ {
|
|
rhs.mul(self)
|
|
}
|
|
}
|
|
|
|
impl_trait_op_inner_type!($typ, $inner, Div, div, DivAssign, div_assign);
|
|
impl_trait_op_inner_type!($typ, $inner, Rem, rem, RemAssign, rem_assign);
|
|
|
|
impl_non_trait_op_inner_type!($typ, $inner);
|
|
|
|
impl_unsigned_int_into_signed!($typ, $inner);
|
|
|
|
impl_signed_ops!($typ, $inner, <$typ>::ZERO);
|
|
|
|
impl muldiv::MulDiv<$inner> for $typ {
|
|
type Output = Self;
|
|
|
|
#[inline]
|
|
fn mul_div_floor(self, num: $inner, denom: $inner) -> Option<Self> {
|
|
self.0
|
|
.mul_div_floor(num, denom)
|
|
.map(Self)
|
|
}
|
|
|
|
#[inline]
|
|
fn mul_div_round(self, num: $inner, denom: $inner) -> Option<Self> {
|
|
self.0
|
|
.mul_div_round(num, denom)
|
|
.map(Self)
|
|
}
|
|
|
|
#[inline]
|
|
fn mul_div_ceil(self, num: $inner, denom: $inner) -> Option<Self> {
|
|
self.0
|
|
.mul_div_ceil(num, denom)
|
|
.map(Self)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionOperations for $typ {}
|
|
|
|
impl opt_ops::OptionCheckedAdd for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_add(
|
|
self,
|
|
rhs: Self,
|
|
) -> Result<Option<Self>, opt_ops::Error> {
|
|
self.checked_add(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingAdd for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_saturating_add(self, rhs: Self) -> Option<Self> {
|
|
Some(self.saturating_add(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionOverflowingAdd for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_overflowing_add(self, rhs: Self) -> Option<(Self, bool)> {
|
|
let res = self.overflowing_add(rhs);
|
|
Some((res.0, res.1))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionWrappingAdd for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_wrapping_add(self, rhs: Self) -> Option<Self> {
|
|
Some(self.wrapping_add(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedDiv<$inner> for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_div(self, rhs: $inner) -> Result<Option<Self>, opt_ops::Error> {
|
|
if rhs == 0 {
|
|
return Err(opt_ops::Error::DivisionByZero);
|
|
}
|
|
self
|
|
.checked_div(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedDiv for $typ {
|
|
type Output = $inner;
|
|
#[inline]
|
|
fn opt_checked_div(self, rhs: Self) -> Result<Option<$inner>, opt_ops::Error> {
|
|
if rhs.0 == 0 {
|
|
return Err(opt_ops::Error::DivisionByZero);
|
|
}
|
|
self.0
|
|
.checked_div(rhs.0)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedMul<$inner> for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_mul(
|
|
self,
|
|
rhs: $inner,
|
|
) -> Result<Option<Self>, opt_ops::Error> {
|
|
self.checked_mul(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedMul<$typ> for $inner {
|
|
type Output = $typ;
|
|
#[inline]
|
|
fn opt_checked_mul(
|
|
self,
|
|
rhs: $typ,
|
|
) -> Result<Option<$typ>, opt_ops::Error> {
|
|
rhs.checked_mul(self)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingMul<$inner> for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_saturating_mul(self, rhs: $inner) -> Option<Self> {
|
|
Some(self.saturating_mul(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingMul<$typ> for $inner {
|
|
type Output = $typ;
|
|
#[inline]
|
|
fn opt_saturating_mul(self, rhs: $typ) -> Option<$typ> {
|
|
Some(rhs.saturating_mul(self))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionOverflowingMul<$inner> for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_overflowing_mul(self, rhs: $inner) -> Option<(Self, bool)> {
|
|
let res = self.overflowing_mul(rhs);
|
|
Some((res.0, res.1))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionOverflowingMul<$typ> for $inner {
|
|
type Output = $typ;
|
|
#[inline]
|
|
fn opt_overflowing_mul(self, rhs: $typ) -> Option<($typ, bool)> {
|
|
let res = rhs.overflowing_mul(self);
|
|
Some((res.0, res.1))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionWrappingMul<$inner> for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_wrapping_mul(self, rhs: $inner) -> Option<Self> {
|
|
Some(self.wrapping_mul(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionWrappingMul<$typ> for $inner {
|
|
type Output = $typ;
|
|
#[inline]
|
|
fn opt_wrapping_mul(self, rhs: $typ) -> Option<$typ> {
|
|
Some(rhs.wrapping_mul(self))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedRem<$inner> for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_rem(self, rhs: $inner) -> Result<Option<Self>, opt_ops::Error> {
|
|
if rhs == 0 {
|
|
return Err(opt_ops::Error::DivisionByZero);
|
|
}
|
|
self.checked_rem(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedRem for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_rem(self, rhs: Self) -> Result<Option<Self>, opt_ops::Error> {
|
|
if rhs.0 == 0 {
|
|
return Err(opt_ops::Error::DivisionByZero);
|
|
}
|
|
self.checked_rem(rhs.0)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedSub for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_sub(
|
|
self,
|
|
rhs: Self,
|
|
) -> Result<Option<Self>, opt_ops::Error> {
|
|
self.checked_sub(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingSub for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_saturating_sub(self, rhs: Self) -> Option<Self> {
|
|
Some(self.saturating_sub(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionOverflowingSub for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_overflowing_sub(self, rhs: Self) -> Option<(Self, bool)> {
|
|
let res = self.overflowing_sub(rhs);
|
|
Some((res.0, res.1))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionWrappingSub for $typ {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_wrapping_sub(self, rhs: Self) -> Option<Self> {
|
|
Some(self.wrapping_sub(rhs))
|
|
}
|
|
}
|
|
};
|
|
);
|
|
|
|
macro_rules! impl_signed_ops(
|
|
(u64) => {
|
|
impl_signed_ops!(u64, u64, 0);
|
|
};
|
|
|
|
(u32) => {
|
|
impl_signed_ops!(u32, u32, 0);
|
|
};
|
|
|
|
(usize) => {
|
|
impl_signed_ops!(usize, usize, 0);
|
|
};
|
|
|
|
($typ:ty, $inner:ty, $zero:expr) => {
|
|
impl crate::Signed<$typ> {
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns the signum for this `Signed`.
|
|
///
|
|
/// Returns:
|
|
///
|
|
/// - `0` if the number is zero.
|
|
/// - `1` if the value must be considered as positive.
|
|
/// - `-1` if the value must be considered as negative.
|
|
#[inline]
|
|
pub fn signum(self) -> i32 {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(val) | Negative(val) if val == $zero => 0i32,
|
|
Positive(_) => 1i32,
|
|
Negative(_) => -1i32,
|
|
}
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns the checked subtraction `self - other`.
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn checked_sub(self, other: Self) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match (self, other) {
|
|
(Positive(a), Positive(b)) if a >= b => Some(Positive(a - b)),
|
|
(Positive(a), Positive(b)) => Some(Negative(b - a)),
|
|
(Negative(a), Negative(b)) if a >= b => Some(Negative(a - b)),
|
|
(Negative(a), Negative(b)) => Some(Positive(b - a)),
|
|
(Positive(a), Negative(b)) => a.checked_add(b).map(Positive),
|
|
(Negative(a), Positive(b)) => a.checked_add(b).map(Negative),
|
|
}
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns the checked subtraction `self - other`.
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn checked_sub_unsigned(self, other: $typ) -> Option<Self> {
|
|
self.checked_sub(crate::Signed::Positive(other))
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns the checked addition `self + other`.
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn checked_add(self, other: Self) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match (self, other) {
|
|
(Positive(a), Positive(b)) => a.checked_add(b).map(Positive),
|
|
(Negative(a), Negative(b)) => a.checked_add(b).map(Negative),
|
|
(Positive(_), Negative(_)) => self.checked_sub(-other),
|
|
(Negative(_), Positive(_)) => Some(-((-self).checked_sub(other)?))
|
|
}
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns the checked addition `self + other`.
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn checked_add_unsigned(self, other: $typ) -> Option<Self> {
|
|
self.checked_add(crate::Signed::Positive(other))
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns the saturating subtraction `self - other`.
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn saturating_sub(self, other: Self) -> Self {
|
|
use crate::Signed::*;
|
|
match (self, other) {
|
|
(Positive(a), Positive(b)) if a >= b => Positive(a - b),
|
|
(Positive(a), Positive(b)) => Negative(b - a),
|
|
(Negative(a), Negative(b)) if a >= b => Negative(a - b),
|
|
(Negative(a), Negative(b)) => Positive(b - a),
|
|
(Positive(a), Negative(b)) => Positive(a.saturating_add(b)),
|
|
(Negative(a), Positive(b)) => Negative(a.saturating_add(b)),
|
|
}
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns the saturating subtraction `self - other`.
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn saturating_sub_unsigned(self, other: $typ) -> Self {
|
|
self.saturating_sub(crate::Signed::Positive(other))
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns the saturating addition `self + other`.
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn saturating_add(self, other: Self) -> Self {
|
|
use crate::Signed::*;
|
|
match (self, other) {
|
|
(Positive(a), Positive(b)) => Positive(a.saturating_add(b)),
|
|
(Negative(a), Negative(b)) => Negative(a.saturating_add(b)),
|
|
(Positive(_), Negative(_)) => self.saturating_sub(-other),
|
|
(Negative(_), Positive(_)) => -((-self).saturating_sub(other)),
|
|
}
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns the saturating addition `self + other`.
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn saturating_add_unsigned(self, other: $typ) -> Self {
|
|
self.saturating_add(crate::Signed::Positive(other))
|
|
}
|
|
}
|
|
|
|
impl std::ops::Add for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn add(self, other: Self) -> Self {
|
|
self.checked_add(other).expect("Overflowing addition")
|
|
}
|
|
}
|
|
|
|
impl std::ops::AddAssign for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn add_assign(&mut self, other: Self) {
|
|
*self = self.checked_add(other).expect("Overflowing addition")
|
|
}
|
|
}
|
|
|
|
impl std::ops::Sub for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn sub(self, other: Self) -> Self {
|
|
self.checked_sub(other).expect("Overflowing subtraction")
|
|
}
|
|
}
|
|
|
|
impl std::ops::SubAssign for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn sub_assign(&mut self, other: Self) {
|
|
*self = self.checked_sub(other).expect("Overflowing subtraction")
|
|
}
|
|
}
|
|
|
|
impl std::ops::Add<$typ> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn add(self, other: $typ) -> Self {
|
|
self.checked_add(crate::Signed::Positive(other)).expect("Overflowing addition")
|
|
}
|
|
}
|
|
|
|
impl std::ops::AddAssign<$typ> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn add_assign(&mut self, other: $typ) {
|
|
*self = self.checked_add(crate::Signed::Positive(other)).expect("Overflowing addition")
|
|
}
|
|
}
|
|
|
|
impl std::ops::Sub<$typ> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
|
|
#[inline]
|
|
fn sub(self, other: $typ) -> Self {
|
|
self.checked_sub(crate::Signed::Positive(other)).expect("Overflowing subtraction")
|
|
}
|
|
}
|
|
|
|
impl std::ops::SubAssign<$typ> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn sub_assign(&mut self, other: $typ) {
|
|
*self = self.checked_sub(crate::Signed::Positive(other)).expect("Overflowing subtraction")
|
|
}
|
|
}
|
|
|
|
impl std::ops::Add<crate::Signed<$typ>> for $typ {
|
|
type Output = crate::Signed<$typ>;
|
|
#[inline]
|
|
fn add(self, other: crate::Signed<$typ>) -> crate::Signed<$typ> {
|
|
crate::Signed::Positive(self).checked_add(other).expect("Overflowing addition")
|
|
}
|
|
}
|
|
|
|
impl std::ops::Sub<crate::Signed<$typ>> for $typ {
|
|
type Output = crate::Signed<$typ>;
|
|
#[inline]
|
|
fn sub(self, other: crate::Signed<$typ>) -> crate::Signed<$typ> {
|
|
crate::Signed::Positive(self).checked_sub(other).expect("Overflowing subtraction")
|
|
}
|
|
}
|
|
|
|
impl std::cmp::PartialOrd for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
Some(self.cmp(other))
|
|
}
|
|
}
|
|
|
|
impl std::cmp::PartialEq<$typ> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn eq(&self, other: &$typ) -> bool {
|
|
self.eq(&crate::Signed::Positive(*other))
|
|
}
|
|
}
|
|
|
|
impl std::cmp::PartialEq<crate::Signed<$typ>> for $typ {
|
|
#[inline]
|
|
fn eq(&self, other: &crate::Signed<$typ>) -> bool {
|
|
crate::Signed::Positive(*self).eq(other)
|
|
}
|
|
}
|
|
|
|
impl std::cmp::PartialOrd<$typ> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &$typ) -> Option<std::cmp::Ordering> {
|
|
Some(self.cmp(&crate::Signed::Positive(*other)))
|
|
}
|
|
}
|
|
|
|
impl std::cmp::PartialOrd<crate::Signed<$typ>> for $typ {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &crate::Signed<$typ>) -> Option<std::cmp::Ordering> {
|
|
Some(crate::Signed::Positive(*self).cmp(other))
|
|
}
|
|
}
|
|
|
|
impl std::cmp::Ord for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
use crate::Signed::*;
|
|
match (self, other) {
|
|
(Positive(a), Positive(b)) => a.cmp(b),
|
|
(Negative(a), Negative(b)) => b.cmp(a),
|
|
(Positive(_), Negative(_)) => std::cmp::Ordering::Greater,
|
|
(Negative(_), Positive(_)) => std::cmp::Ordering::Less,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionOperations for crate::Signed<$typ> {}
|
|
|
|
impl opt_ops::OptionCheckedAdd for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_add(
|
|
self,
|
|
rhs: Self,
|
|
) -> Result<Option<Self>, opt_ops::Error> {
|
|
self.checked_add(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingAdd for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_saturating_add(self, rhs: Self) -> Option<Self> {
|
|
Some(self.saturating_add(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedSub for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_sub(
|
|
self,
|
|
rhs: Self,
|
|
) -> Result<Option<Self>, opt_ops::Error> {
|
|
self.checked_sub(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingSub for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_saturating_sub(self, rhs: Self) -> Option<Self> {
|
|
Some(self.saturating_sub(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedAdd<$typ> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_add(
|
|
self,
|
|
rhs: $typ,
|
|
) -> Result<Option<Self>, opt_ops::Error> {
|
|
self.opt_checked_add(crate::Signed::Positive(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingAdd<$typ> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_saturating_add(self, rhs: $typ) -> Option<Self> {
|
|
self.opt_saturating_add(crate::Signed::Positive(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedSub<$typ> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_sub(
|
|
self,
|
|
rhs: $typ,
|
|
) -> Result<Option<Self>, opt_ops::Error> {
|
|
self.opt_checked_sub(crate::Signed::Positive(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingSub<$typ> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_saturating_sub(self, rhs: $typ) -> Option<Self> {
|
|
self.opt_saturating_sub(crate::Signed::Positive(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedAdd<crate::Signed<$typ>> for $typ {
|
|
type Output = crate::Signed<$typ>;
|
|
#[inline]
|
|
fn opt_checked_add(
|
|
self,
|
|
rhs: crate::Signed<$typ>,
|
|
) -> Result<Option<Self::Output>, opt_ops::Error> {
|
|
crate::Signed::Positive(self).opt_checked_add(rhs)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingAdd<crate::Signed<$typ>> for $typ {
|
|
type Output = crate::Signed<$typ>;
|
|
#[inline]
|
|
fn opt_saturating_add(
|
|
self,
|
|
rhs: crate::Signed<$typ>
|
|
) -> Option<Self::Output> {
|
|
crate::Signed::Positive(self).opt_saturating_add(rhs)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedSub<crate::Signed<$typ>> for $typ {
|
|
type Output = crate::Signed<$typ>;
|
|
#[inline]
|
|
fn opt_checked_sub(
|
|
self,
|
|
rhs: crate::Signed<$typ>,
|
|
) -> Result<Option<Self::Output>, opt_ops::Error> {
|
|
crate::Signed::Positive(self).opt_checked_sub(rhs)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingSub<crate::Signed<$typ>> for $typ {
|
|
type Output = crate::Signed<$typ>;
|
|
#[inline]
|
|
fn opt_saturating_sub(
|
|
self,
|
|
rhs: crate::Signed<$typ>
|
|
) -> Option<Self::Output> {
|
|
crate::Signed::Positive(self).opt_saturating_sub(rhs)
|
|
}
|
|
}
|
|
};
|
|
);
|
|
|
|
macro_rules! impl_signed_div_mul(
|
|
(u64) => {
|
|
impl_signed_div_mul!(u64, u64, i64, |val: u64| val);
|
|
impl_signed_extra_div_mul!(u64, i64);
|
|
impl_signed_div_mul_trait!(u64, u64, i64, |val: u64| val);
|
|
};
|
|
|
|
(usize) => {
|
|
impl_signed_div_mul!(usize, usize, isize, |val: usize| val);
|
|
impl_signed_extra_div_mul!(usize, isize);
|
|
// `MulDiv` not available for usize
|
|
};
|
|
|
|
(u32) => {
|
|
impl_signed_div_mul!(u32, u32, i32, |val: u32| val);
|
|
impl_signed_extra_div_mul!(u32, i32);
|
|
impl_signed_div_mul_trait!(u32, u32, i32, |val: u32| val);
|
|
};
|
|
|
|
($newtyp:ty, u64) => {
|
|
impl_signed_div_mul!($newtyp, u64, i64, |val: $newtyp| *val);
|
|
impl_signed_extra_div_mul!($newtyp, u64, i64);
|
|
impl_signed_div_mul_trait!($newtyp, u64, i64, |val: $newtyp| *val);
|
|
};
|
|
|
|
($newtyp:ty, u32) => {
|
|
impl_signed_div_mul!($newtyp, u32, i32, |val: $newtyp| *val);
|
|
impl_signed_extra_div_mul!($newtyp, u32, i32);
|
|
impl_signed_div_mul_trait!($newtyp, u32, i32, |val: $newtyp| *val);
|
|
};
|
|
|
|
($typ:ty, $inner:ty, $signed_rhs:ty, $into_inner:expr) => {
|
|
impl crate::Signed<$typ> {
|
|
#[allow(dead_code)]
|
|
#[inline]
|
|
fn signed_from_inner(val: $inner, sign: $signed_rhs) -> Option<crate::Signed<$typ>> {
|
|
skip_assert_initialized!();
|
|
if sign.is_positive() {
|
|
Self::positive_from_inner(val)
|
|
} else {
|
|
Self::negative_from_inner(val)
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn positive_from_inner(val: $inner) -> Option<Self> {
|
|
skip_assert_initialized!();
|
|
<$typ>::try_from(val).ok().map(crate::Signed::Positive)
|
|
}
|
|
|
|
#[inline]
|
|
fn negative_from_inner(val: $inner) -> Option<Self> {
|
|
skip_assert_initialized!();
|
|
<$typ>::try_from(val).ok().map(crate::Signed::Negative)
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn checked_div(self, rhs:$signed_rhs) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => {
|
|
if rhs.is_positive() {
|
|
lhs.checked_div(rhs as $inner).map(Positive)
|
|
} else {
|
|
lhs.checked_div(-rhs as $inner).map(Negative)
|
|
}
|
|
}
|
|
Negative(lhs) => {
|
|
if rhs.is_positive() {
|
|
lhs.checked_div(rhs as $inner).map(Negative)
|
|
} else {
|
|
lhs.checked_div(-rhs as $inner).map(Positive)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn checked_div_unsigned(self, rhs:$inner) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => lhs.checked_div(rhs).map(Positive),
|
|
Negative(lhs) => lhs.checked_div(rhs).map(Negative),
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn checked_rem(self, rhs:$signed_rhs) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => {
|
|
if rhs.is_positive() {
|
|
lhs.checked_rem(rhs as $inner).map(Positive)
|
|
} else {
|
|
lhs.checked_rem(-rhs as $inner).map(Positive)
|
|
}
|
|
}
|
|
Negative(lhs) => {
|
|
if rhs.is_positive() {
|
|
lhs.checked_rem(rhs as $inner).map(Negative)
|
|
} else {
|
|
lhs.checked_rem(-rhs as $inner).map(Negative)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn checked_rem_unsigned(self, rhs:$inner) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => lhs.checked_rem(rhs).map(Positive),
|
|
Negative(lhs) => lhs.checked_rem(rhs).map(Negative),
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn checked_mul(self, rhs:$signed_rhs) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => {
|
|
if rhs.is_positive() {
|
|
lhs.checked_mul(rhs as $inner).map(Positive)
|
|
} else {
|
|
lhs.checked_mul(-rhs as $inner).map(Negative)
|
|
}
|
|
}
|
|
Negative(lhs) => {
|
|
if rhs.is_positive() {
|
|
lhs.checked_mul(rhs as $inner).map(Negative)
|
|
} else {
|
|
lhs.checked_mul(-rhs as $inner).map(Positive)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn checked_mul_unsigned(self, rhs:$inner) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => lhs.checked_mul(rhs).map(Positive),
|
|
Negative(lhs) => lhs.checked_mul(rhs).map(Negative),
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn saturating_mul(self, rhs:$signed_rhs) -> Self {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => {
|
|
if rhs.is_positive() {
|
|
Positive(lhs.saturating_mul(rhs as $inner))
|
|
} else {
|
|
Negative(lhs.saturating_mul(-rhs as $inner))
|
|
}
|
|
}
|
|
Negative(lhs) => {
|
|
if rhs.is_positive() {
|
|
Negative(lhs.saturating_mul(rhs as $inner))
|
|
} else {
|
|
Positive(lhs.saturating_mul(-rhs as $inner))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
|
#[inline]
|
|
pub fn saturating_mul_unsigned(self, rhs:$inner) -> Self {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => Positive(lhs.saturating_mul(rhs)),
|
|
Negative(lhs) => Negative(lhs.saturating_mul(rhs)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::ops::Div<$signed_rhs> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn div(self, rhs: $signed_rhs) -> Self {
|
|
self.checked_div(rhs).expect("division overflowed")
|
|
}
|
|
}
|
|
|
|
impl std::ops::DivAssign<$signed_rhs> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn div_assign(&mut self, rhs: $signed_rhs) {
|
|
*self = std::ops::Div::div(*self, rhs);
|
|
}
|
|
}
|
|
|
|
impl std::ops::Div<$inner> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn div(self, rhs: $inner) -> Self {
|
|
self.checked_div_unsigned(rhs).expect("division overflowed")
|
|
}
|
|
}
|
|
|
|
impl std::ops::DivAssign<$inner> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn div_assign(&mut self, rhs: $inner) {
|
|
*self = std::ops::Div::div(*self, rhs);
|
|
}
|
|
}
|
|
|
|
impl std::ops::Rem<$signed_rhs> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn rem(self, rhs: $signed_rhs) -> Self {
|
|
self.checked_rem(rhs).expect("division overflowed")
|
|
}
|
|
}
|
|
|
|
impl std::ops::RemAssign<$signed_rhs> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn rem_assign(&mut self, rhs: $signed_rhs) {
|
|
*self = std::ops::Rem::rem(*self, rhs);
|
|
}
|
|
}
|
|
|
|
impl std::ops::Rem<$inner> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn rem(self, rhs: $inner) -> Self {
|
|
self.checked_rem_unsigned(rhs).expect("division overflowed")
|
|
}
|
|
}
|
|
|
|
impl std::ops::RemAssign<$inner> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn rem_assign(&mut self, rhs: $inner) {
|
|
*self = std::ops::Rem::rem(*self, rhs);
|
|
}
|
|
}
|
|
|
|
impl std::ops::Mul<$signed_rhs> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn mul(self, rhs: $signed_rhs) -> Self {
|
|
self.checked_mul(rhs).expect("multiplication overflowed")
|
|
}
|
|
}
|
|
|
|
impl std::ops::MulAssign<$signed_rhs> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn mul_assign(&mut self, rhs: $signed_rhs) {
|
|
*self = std::ops::Mul::mul(*self, rhs);
|
|
}
|
|
}
|
|
|
|
impl std::ops::Mul<$inner> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn mul(self, rhs: $inner) -> Self {
|
|
self.checked_mul_unsigned(rhs).expect("multiplication overflowed")
|
|
}
|
|
}
|
|
|
|
impl std::ops::MulAssign<$inner> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn mul_assign(&mut self, rhs: $inner) {
|
|
*self = std::ops::Mul::mul(*self, rhs);
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedDiv<$signed_rhs> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_div(self, rhs: $signed_rhs) -> Result<Option<Self>, opt_ops::Error> {
|
|
if rhs == 0 {
|
|
return Err(opt_ops::Error::DivisionByZero);
|
|
}
|
|
self.checked_div(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedMul<$signed_rhs> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_mul(self, rhs: $signed_rhs) -> Result<Option<Self>, opt_ops::Error> {
|
|
self.checked_mul(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingMul<$signed_rhs> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_saturating_mul(self, rhs: $signed_rhs) -> Option<Self> {
|
|
Some(self.saturating_mul(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedRem<$signed_rhs> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_rem(self, rhs: $signed_rhs) -> Result<Option<Self>, opt_ops::Error> {
|
|
if rhs == 0 {
|
|
return Err(opt_ops::Error::DivisionByZero);
|
|
}
|
|
self.checked_rem(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedDiv<$inner> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_div(self, rhs: $inner) -> Result<Option<Self>, opt_ops::Error> {
|
|
if rhs == 0 {
|
|
return Err(opt_ops::Error::DivisionByZero);
|
|
}
|
|
self.checked_div_unsigned(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedMul<$inner> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_mul(self, rhs: $inner) -> Result<Option<Self>, opt_ops::Error> {
|
|
self.checked_mul_unsigned(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingMul<$inner> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_saturating_mul(self, rhs: $inner) -> Option<Self> {
|
|
Some(self.saturating_mul_unsigned(rhs))
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedRem<$inner> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_rem(self, rhs: $inner) -> Result<Option<Self>, opt_ops::Error> {
|
|
if rhs == 0 {
|
|
return Err(opt_ops::Error::DivisionByZero);
|
|
}
|
|
self.checked_rem_unsigned(rhs)
|
|
.ok_or(opt_ops::Error::Overflow)
|
|
.map(Some)
|
|
}
|
|
}
|
|
};
|
|
);
|
|
|
|
macro_rules! impl_signed_extra_div_mul(
|
|
($typ:ty, $signed:ty) => {
|
|
impl std::ops::Div for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn div(self, rhs: Self) -> Self {
|
|
match rhs {
|
|
crate::Signed::Positive(rhs) => self.div(rhs),
|
|
crate::Signed::Negative(rhs) => std::ops::Neg::neg(self.div(rhs)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::ops::Rem for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn rem(self, rhs: Self) -> Self {
|
|
self.rem(rhs.abs())
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedDiv for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_div(self, rhs: Self) -> Result<Option<Self>, opt_ops::Error> {
|
|
match rhs {
|
|
crate::Signed::Positive(rhs) => self.opt_checked_div(rhs),
|
|
crate::Signed::Negative(rhs) => {
|
|
self.opt_checked_div(rhs)
|
|
.map(|res| res.map(std::ops::Neg::neg))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedRem for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn opt_checked_rem(self, rhs: Self) -> Result<Option<Self>, opt_ops::Error> {
|
|
self.opt_checked_rem(rhs.abs())
|
|
}
|
|
}
|
|
};
|
|
($newtyp:ty, $inner:ty, $signed_inner:ty) => {
|
|
impl std::ops::Div for crate::Signed<$newtyp> {
|
|
type Output = crate::Signed<$inner>;
|
|
#[inline]
|
|
fn div(self, rhs: Self) -> Self::Output {
|
|
self.into_inner_signed().div(rhs.into_inner_signed())
|
|
}
|
|
}
|
|
|
|
impl std::ops::Rem for crate::Signed<$newtyp> {
|
|
type Output = Self;
|
|
#[inline]
|
|
fn rem(self, rhs: Self) -> Self {
|
|
self.rem(rhs.abs().0)
|
|
}
|
|
}
|
|
|
|
impl std::ops::Mul<crate::Signed<$newtyp>> for $inner {
|
|
type Output = crate::Signed<$newtyp>;
|
|
#[inline]
|
|
fn mul(self, rhs: crate::Signed<$newtyp>) -> Self::Output {
|
|
rhs.mul(self)
|
|
}
|
|
}
|
|
|
|
impl std::ops::Mul<crate::Signed<$newtyp>> for $signed_inner {
|
|
type Output = crate::Signed<$newtyp>;
|
|
#[inline]
|
|
fn mul(self, rhs: crate::Signed<$newtyp>) -> Self::Output {
|
|
rhs.mul(self)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedDiv for crate::Signed<$newtyp> {
|
|
type Output = crate::Signed<$inner>;
|
|
#[inline]
|
|
fn opt_checked_div(self, rhs: Self) -> Result<Option<Self::Output>, opt_ops::Error> {
|
|
self.into_inner_signed().opt_checked_div(rhs.into_inner_signed())
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedRem for crate::Signed<$newtyp> {
|
|
type Output = crate::Signed<$inner>;
|
|
#[inline]
|
|
fn opt_checked_rem(self, rhs: Self) -> Result<Option<Self::Output>, opt_ops::Error> {
|
|
self.into_inner_signed().opt_checked_rem(rhs.abs().0)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedMul<crate::Signed<$newtyp>> for $signed_inner {
|
|
type Output = crate::Signed<$newtyp>;
|
|
#[inline]
|
|
fn opt_checked_mul(self, rhs: crate::Signed<$newtyp>) -> Result<Option<Self::Output>, opt_ops::Error> {
|
|
rhs.opt_checked_mul(self)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingMul<crate::Signed<$newtyp>> for $signed_inner {
|
|
type Output = crate::Signed<$newtyp>;
|
|
#[inline]
|
|
fn opt_saturating_mul(self, rhs: crate::Signed<$newtyp>) -> Option<Self::Output> {
|
|
rhs.opt_saturating_mul(self)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionCheckedMul<crate::Signed<$newtyp>> for $inner {
|
|
type Output = crate::Signed<$newtyp>;
|
|
#[inline]
|
|
fn opt_checked_mul(self, rhs: crate::Signed<$newtyp>) -> Result<Option<Self::Output>, opt_ops::Error> {
|
|
rhs.opt_checked_mul(self)
|
|
}
|
|
}
|
|
|
|
impl opt_ops::OptionSaturatingMul<crate::Signed<$newtyp>> for $inner {
|
|
type Output = crate::Signed<$newtyp>;
|
|
#[inline]
|
|
fn opt_saturating_mul(self, rhs: crate::Signed<$newtyp>) -> Option<Self::Output> {
|
|
rhs.opt_saturating_mul(self)
|
|
}
|
|
}
|
|
};
|
|
);
|
|
|
|
macro_rules! impl_signed_div_mul_trait(
|
|
($typ:ty, $inner:ty, $signed_rhs:ty, $into_inner:expr) => {
|
|
#[allow(clippy::redundant_closure_call)]
|
|
impl muldiv::MulDiv<$signed_rhs> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
|
|
#[inline]
|
|
fn mul_div_floor(self, num: $signed_rhs, denom: $signed_rhs) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_floor(num.unsigned_abs(), denom.unsigned_abs())
|
|
.and_then(|val| Self::signed_from_inner(val, num.signum() * denom.signum()))
|
|
}
|
|
Negative(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_floor(num.unsigned_abs(), denom.unsigned_abs())
|
|
.and_then(|val| Self::signed_from_inner(val, -num.signum() * denom.signum()))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn mul_div_round(self, num: $signed_rhs, denom: $signed_rhs) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_round(num.unsigned_abs(), denom.unsigned_abs())
|
|
.and_then(|val| Self::signed_from_inner(val, num.signum() * denom.signum()))
|
|
}
|
|
Negative(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_round(num.unsigned_abs(), denom.unsigned_abs())
|
|
.and_then(|val| Self::signed_from_inner(val, -num.signum() * denom.signum()))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn mul_div_ceil(self, num: $signed_rhs, denom: $signed_rhs) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_ceil(num.unsigned_abs(), denom.unsigned_abs())
|
|
.and_then(|val| Self::signed_from_inner(val, num.signum() * denom.signum()))
|
|
}
|
|
Negative(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_ceil(num.unsigned_abs(), denom.unsigned_abs())
|
|
.and_then(|val| Self::signed_from_inner(val, -num.signum() * denom.signum()))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::redundant_closure_call)]
|
|
impl muldiv::MulDiv<$inner> for crate::Signed<$typ> {
|
|
type Output = Self;
|
|
|
|
#[inline]
|
|
fn mul_div_floor(self, num: $inner, denom: $inner) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_floor(num, denom)
|
|
.and_then(Self::positive_from_inner)
|
|
}
|
|
Negative(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_floor(num, denom)
|
|
.and_then(Self::negative_from_inner)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn mul_div_round(self, num: $inner, denom: $inner) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_round(num, denom)
|
|
.and_then(Self::positive_from_inner)
|
|
}
|
|
Negative(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_round(num, denom)
|
|
.and_then(Self::negative_from_inner)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn mul_div_ceil(self, num: $inner, denom: $inner) -> Option<Self> {
|
|
use crate::Signed::*;
|
|
match self {
|
|
Positive(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_ceil(num, denom)
|
|
.and_then(Self::positive_from_inner)
|
|
}
|
|
Negative(lhs) => {
|
|
$into_inner(lhs)
|
|
.mul_div_ceil(num, denom)
|
|
.and_then(Self::negative_from_inner)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
);
|
|
|
|
macro_rules! impl_format_value_traits(
|
|
($typ:ty, $format:ident, $format_value:ident, $inner:ty) => {
|
|
impl FormattedValue for Option<$typ> {
|
|
type FullRange = Self;
|
|
|
|
#[inline]
|
|
fn default_format() -> Format {
|
|
Format::$format
|
|
}
|
|
|
|
#[inline]
|
|
fn format(&self) -> Format {
|
|
Format::$format
|
|
}
|
|
|
|
#[inline]
|
|
fn is_some(&self) -> bool {
|
|
Option::is_some(self)
|
|
}
|
|
|
|
#[inline]
|
|
unsafe fn into_raw_value(self) -> i64 {
|
|
IntoGlib::into_glib(self) as i64
|
|
}
|
|
}
|
|
|
|
impl FormattedValueFullRange for Option<$typ> {
|
|
#[inline]
|
|
unsafe fn from_raw(format: Format, value: i64) -> Self {
|
|
debug_assert_eq!(format, Format::$format);
|
|
FromGlib::from_glib(value as u64)
|
|
}
|
|
}
|
|
|
|
impl FormattedValueNoneBuilder for Option<$typ> {
|
|
#[inline]
|
|
fn none() -> Option<$typ> {
|
|
None
|
|
}
|
|
}
|
|
|
|
impl From<Option<$typ>> for GenericFormattedValue {
|
|
#[inline]
|
|
fn from(v: Option<$typ>) -> Self {
|
|
skip_assert_initialized!();
|
|
Self::$format_value(v)
|
|
}
|
|
}
|
|
|
|
impl From<$typ> for GenericFormattedValue {
|
|
#[inline]
|
|
fn from(v: $typ) -> Self {
|
|
skip_assert_initialized!();
|
|
Self::$format_value(Some(v))
|
|
}
|
|
}
|
|
|
|
impl FormattedValue for $typ {
|
|
type FullRange = Option<$typ>;
|
|
|
|
#[inline]
|
|
fn default_format() -> Format {
|
|
Format::$format
|
|
}
|
|
|
|
#[inline]
|
|
fn format(&self) -> Format {
|
|
Format::$format
|
|
}
|
|
|
|
#[inline]
|
|
fn is_some(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
#[inline]
|
|
unsafe fn into_raw_value(self) -> i64 {
|
|
IntoGlib::into_glib(self) as i64
|
|
}
|
|
}
|
|
|
|
impl SpecificFormattedValue for Option<$typ> {}
|
|
impl SpecificFormattedValueFullRange for Option<$typ> {}
|
|
impl SpecificFormattedValue for $typ {}
|
|
impl FormattedValueIntrinsic for $typ {}
|
|
impl SpecificFormattedValueIntrinsic for $typ {}
|
|
|
|
impl TryFrom<GenericFormattedValue> for Option<$typ> {
|
|
type Error = FormattedValueError;
|
|
#[inline]
|
|
fn try_from(v: GenericFormattedValue) -> Result<Self, Self::Error> {
|
|
skip_assert_initialized!();
|
|
if let GenericFormattedValue::$format_value(v) = v {
|
|
Ok(v)
|
|
} else {
|
|
Err(FormattedValueError(v.format()))
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFrom<$inner> for $typ {
|
|
type Error = GlibNoneError;
|
|
#[inline]
|
|
fn try_from(v: $inner) -> Result<Self, GlibNoneError> {
|
|
skip_assert_initialized!();
|
|
unsafe { Self::try_from_glib(v as i64) }
|
|
}
|
|
}
|
|
|
|
impl TryFromGlib<i64> for $typ {
|
|
type Error = GlibNoneError;
|
|
#[inline]
|
|
unsafe fn try_from_glib(val: i64) -> Result<Self, GlibNoneError> {
|
|
skip_assert_initialized!();
|
|
<$typ as TryFromGlib<u64>>::try_from_glib(val as u64)
|
|
}
|
|
}
|
|
};
|
|
);
|
|
|
|
macro_rules! option_glib_newtype_from_to {
|
|
($typ:ident, $none_value:expr) => {
|
|
#[doc(hidden)]
|
|
impl IntoGlib for $typ {
|
|
type GlibType = u64;
|
|
#[inline]
|
|
fn into_glib(self) -> u64 {
|
|
assert_ne!(
|
|
self.0, $none_value,
|
|
concat!(
|
|
"attempt to build a `None` glib variant",
|
|
"from a non-`Option` type ",
|
|
stringify!($typ),
|
|
),
|
|
);
|
|
self.0
|
|
}
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
impl OptionIntoGlib for $typ {
|
|
const GLIB_NONE: u64 = $none_value;
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
impl TryFromGlib<u64> for $typ {
|
|
type Error = GlibNoneError;
|
|
#[inline]
|
|
unsafe fn try_from_glib(val: u64) -> Result<Self, GlibNoneError> {
|
|
skip_assert_initialized!();
|
|
if val == $none_value {
|
|
return Err(GlibNoneError);
|
|
}
|
|
|
|
Ok($typ(val))
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
// FIXME we could automatically build `$displayable_option_name`
|
|
// if `concat_idents!` was stable.
|
|
// See: https://doc.rust-lang.org/std/macro.concat_idents.html
|
|
macro_rules! glib_newtype_display {
|
|
($typ:ty) => {
|
|
impl std::fmt::Display for $typ {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
std::fmt::Display::fmt(&self.0, f)
|
|
}
|
|
}
|
|
|
|
impl crate::utils::Displayable for $typ {
|
|
type DisplayImpl = Self;
|
|
fn display(self) -> Self {
|
|
self
|
|
}
|
|
}
|
|
};
|
|
|
|
($typ:ty, Format::$format:ident) => {
|
|
impl std::fmt::Display for $typ {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
std::fmt::Display::fmt(&self.0, f)?;
|
|
std::fmt::Write::write_char(f, ' ')?;
|
|
std::fmt::Display::fmt(&Format::$format, f)
|
|
}
|
|
}
|
|
|
|
impl crate::utils::Displayable for $typ {
|
|
type DisplayImpl = Self;
|
|
fn display(self) -> Self {
|
|
self
|
|
}
|
|
}
|
|
};
|
|
|
|
($typ:ty, $displayable_option_name:ident) => {
|
|
glib_newtype_display!($typ);
|
|
|
|
pub struct $displayable_option_name(Option<$typ>);
|
|
|
|
impl std::fmt::Display for $displayable_option_name {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
if let Some(val) = self.0.as_ref() {
|
|
std::fmt::Display::fmt(val, f)
|
|
} else {
|
|
f.write_str("undef.")
|
|
}
|
|
}
|
|
}
|
|
|
|
impl crate::utils::Displayable for Option<$typ> {
|
|
type DisplayImpl = $displayable_option_name;
|
|
fn display(self) -> Self::DisplayImpl {
|
|
$displayable_option_name(self)
|
|
}
|
|
}
|
|
};
|
|
|
|
($typ:ty, $displayable_option_name:ident, Format::$format:ident) => {
|
|
glib_newtype_display!($typ, Format::$format);
|
|
|
|
pub struct $displayable_option_name(Option<$typ>);
|
|
|
|
impl std::fmt::Display for $displayable_option_name {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
if let Some(val) = self.0.as_ref() {
|
|
std::fmt::Display::fmt(val, f)
|
|
} else {
|
|
write!(f, "undef. {}", Format::$format)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl crate::utils::Displayable for Option<$typ> {
|
|
type DisplayImpl = $displayable_option_name;
|
|
fn display(self) -> Self::DisplayImpl {
|
|
$displayable_option_name(self)
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! impl_signed_int_into_signed(
|
|
(u64) => {
|
|
impl_signed_int_into_signed!(u64, u64, i64, |val: u64| val);
|
|
};
|
|
|
|
(usize) => {
|
|
impl_signed_int_into_signed!(usize, usize, isize, |val: usize| val);
|
|
};
|
|
|
|
(u32) => {
|
|
impl_signed_int_into_signed!(u32, u32, i32, |val: u32| val);
|
|
};
|
|
|
|
($newtyp:ty, u64) => {
|
|
impl_signed_int_into_signed!($newtyp, u64, i64, |val: $newtyp| *val);
|
|
};
|
|
|
|
($newtyp:ty, u32) => {
|
|
impl_signed_int_into_signed!($newtyp, u32, i32, |val: $newtyp| *val);
|
|
};
|
|
|
|
($typ:ty, $inner:ty, $signed:ty, $into_inner:expr) => {
|
|
#[allow(clippy::redundant_closure_call)]
|
|
impl TryFrom<crate::Signed<$typ>> for $signed {
|
|
type Error = std::num::TryFromIntError;
|
|
|
|
#[inline]
|
|
fn try_from(value: crate::Signed<$typ>) -> Result<$signed, Self::Error> {
|
|
assert_eq!(::std::mem::size_of::<$inner>(), ::std::mem::size_of::<$signed>());
|
|
|
|
match value {
|
|
crate::Signed::Positive(value) => <$signed>::try_from($into_inner(value)),
|
|
crate::Signed::Negative(value) => {
|
|
let inner = $into_inner(value);
|
|
// `$signed::MIN.abs()` can't be represented as an `$signed`
|
|
if inner == (<$inner>::MAX >> 1) + 1 {
|
|
Ok(<$signed>::MIN)
|
|
} else {
|
|
Ok(-<$signed>::try_from(inner)?)
|
|
}
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<$signed> for crate::Signed<$typ> {
|
|
#[inline]
|
|
fn from(value: $signed) -> crate::Signed<$typ> {
|
|
let abs = value.unsigned_abs();
|
|
if value.signum() >= 0 {
|
|
Self::positive_from_inner(abs).unwrap()
|
|
} else {
|
|
Self::negative_from_inner(abs).unwrap()
|
|
}
|
|
}
|
|
}
|
|
};
|
|
);
|