forked from mirrors/gstreamer-rs
format, clock_time: gather macros together
The modules format and clock_time share common macros which are scattered between each modules. This cross reference makes it difficult to maintain the macros. This commit also make it possible to use macro impl_common_ops_for_newtype_uint for Percent.
This commit is contained in:
parent
986a136492
commit
deb22b264e
4 changed files with 437 additions and 425 deletions
|
@ -2,10 +2,13 @@
|
|||
|
||||
use glib::translate::*;
|
||||
use glib::StaticType;
|
||||
use muldiv::MulDiv;
|
||||
use num_integer::div_rem;
|
||||
use opt_ops::prelude::*;
|
||||
use std::borrow::Borrow;
|
||||
use std::convert::{From, TryFrom};
|
||||
use std::io::{self, prelude::*};
|
||||
use std::ops;
|
||||
use std::time::Duration;
|
||||
use std::{cmp, fmt, str};
|
||||
|
||||
|
@ -64,38 +67,6 @@ impl ClockTime {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! option_glib_newtype_from_to {
|
||||
($type_:ident, $none_value:expr) => {
|
||||
#[doc(hidden)]
|
||||
impl IntoGlib for $type_ {
|
||||
type GlibType = u64;
|
||||
|
||||
fn into_glib(self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl OptionIntoGlib for $type_ {
|
||||
const GLIB_NONE: u64 = $none_value;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl TryFromGlib<u64> for $type_ {
|
||||
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($type_(val))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
option_glib_newtype_from_to!(ClockTime, ffi::GST_CLOCK_TIME_NONE);
|
||||
|
||||
impl glib::value::ValueType for ClockTime {
|
||||
|
@ -204,176 +175,22 @@ impl From<ClockTime> for Duration {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_common_ops_for_newtype_u64(
|
||||
($name:ident) => {
|
||||
impl $name {
|
||||
pub const ZERO: Self = Self(0);
|
||||
pub const NONE: Option<Self> = None;
|
||||
|
||||
pub const fn is_zero(self) -> bool {
|
||||
self.0 == Self::ZERO.0
|
||||
}
|
||||
|
||||
#[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 {
|
||||
(TryFrom::try_from(res_u128 as u64).unwrap(), false)
|
||||
} else {
|
||||
(TryFrom::try_from((res_u128 - Self::MAX.0 as u128 - 1) as u64).unwrap(), true)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME add overflowing_add
|
||||
|
||||
#[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
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionOperations for $name {}
|
||||
|
||||
impl OptionCheckedAdd for $name {
|
||||
type Output = Self;
|
||||
|
||||
fn opt_checked_add(
|
||||
self,
|
||||
rhs: Self,
|
||||
) -> Result<Option<Self::Output>, opt_ops::CheckedError> {
|
||||
self.checked_add(rhs)
|
||||
.ok_or(opt_ops::CheckedError::Overflow)
|
||||
.map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionSaturatingAdd for $name {
|
||||
type Output = Self;
|
||||
fn opt_saturating_add(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.saturating_add(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionOverflowingAdd for $name {
|
||||
type Output = Self;
|
||||
fn opt_overflowing_add(self, rhs: Self) -> Option<(Self::Output, bool)> {
|
||||
let res = self.overflowing_add(rhs);
|
||||
Some((res.0, res.1))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionWrappingAdd for $name {
|
||||
type Output = Self;
|
||||
fn opt_wrapping_add(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.wrapping_add(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedSub for $name {
|
||||
type Output = Self;
|
||||
fn opt_checked_sub(
|
||||
self,
|
||||
rhs: Self,
|
||||
) -> Result<Option<Self::Output>, opt_ops::CheckedError> {
|
||||
self.checked_sub(rhs)
|
||||
.ok_or(opt_ops::CheckedError::Overflow)
|
||||
.map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionSaturatingSub for $name {
|
||||
type Output = Self;
|
||||
fn opt_saturating_sub(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.saturating_sub(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionOverflowingSub for $name {
|
||||
type Output = Self;
|
||||
fn opt_overflowing_sub(self, rhs: Self) -> Option<(Self::Output, bool)> {
|
||||
let res = self.overflowing_sub(rhs);
|
||||
Some((res.0, res.1))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionWrappingSub for $name {
|
||||
type Output = Self;
|
||||
fn opt_wrapping_sub(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.wrapping_sub(rhs))
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
impl_common_ops_for_newtype_u64!(ClockTime);
|
||||
impl_common_ops_for_newtype_uint!(ClockTime, u64);
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Tell [`pad_clocktime`] what kind of time we're formatting
|
||||
enum Sign {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// An undefined time (`None`)
|
||||
Undefined,
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// A non-negative time (zero or greater)
|
||||
NonNegative,
|
||||
|
||||
// For a future ClockTimeDiff formatting
|
||||
#[allow(dead_code)]
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// A negative time (below zero)
|
||||
Negative,
|
||||
}
|
||||
|
@ -383,6 +200,7 @@ enum Sign {
|
|||
// TODO: Would be useful for formatting ClockTimeDiff
|
||||
// if it was a new type instead of an alias for i64
|
||||
//
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Performs the correct padding for a clock time which has already been
|
||||
/// emitted into a str, as by [`write_clocktime`]. The str should *not*
|
||||
/// contain the sign; that will be added by this method.
|
||||
|
@ -449,6 +267,7 @@ fn pad_clocktime(f: &mut fmt::Formatter<'_>, sign: Sign, buf: &str) -> fmt::Resu
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Writes an unpadded, signless clocktime string with the given precision
|
||||
fn write_clocktime<W: io::Write>(
|
||||
mut writer: W,
|
||||
|
|
|
@ -172,245 +172,20 @@ impl FormattedValueIntrinsic for GenericFormattedValue {
|
|||
type FormattedValueType = GenericFormattedValue;
|
||||
}
|
||||
|
||||
macro_rules! impl_op_same(
|
||||
($name:ident, $op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident) => {
|
||||
impl<RHS: Borrow<$name>> ops::$op<RHS> for $name {
|
||||
type Output = Self;
|
||||
|
||||
fn $op_name(self, rhs: RHS) -> Self::Output {
|
||||
Self(self.0.$op_name(rhs.borrow().0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<RHS: Borrow<$name>> ops::$op<RHS> for &$name {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: RHS) -> Self::Output {
|
||||
(*self).$op_name(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<RHS: Borrow<$name>> ops::$op_assign<RHS> for $name {
|
||||
fn $op_assign_name(&mut self, rhs: RHS) {
|
||||
self.0.$op_assign_name(rhs.borrow().0)
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! impl_op_u64(
|
||||
($name:ident, $op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident) => {
|
||||
impl ops::$op<u64> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: u64) -> Self::Output {
|
||||
$name(self.0.$op_name(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::$op<u64> for &$name {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: u64) -> Self::Output {
|
||||
(*self).$op_name(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::$op<$name> for u64 {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: $name) -> $name {
|
||||
$name(self.$op_name(rhs.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::$op<&$name> for u64 {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: &$name) -> $name {
|
||||
self.$op_name(*rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::$op_assign<u64> for $name {
|
||||
fn $op_assign_name(&mut self, rhs: u64) {
|
||||
self.0.$op_assign_name(rhs)
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! impl_format_value_traits(
|
||||
($name:ident, $format:ident, $format_value:ident) => {
|
||||
impl FormattedValue for Option<$name> {
|
||||
fn default_format() -> Format {
|
||||
Format::$format
|
||||
}
|
||||
|
||||
fn format(&self) -> Format {
|
||||
Format::$format
|
||||
}
|
||||
|
||||
unsafe fn from_raw(format: Format, value: i64) -> Option<$name> {
|
||||
debug_assert_eq!(format, Format::$format);
|
||||
FromGlib::from_glib(value as u64)
|
||||
}
|
||||
|
||||
unsafe fn into_raw_value(self) -> i64 {
|
||||
IntoGlib::into_glib(self) as i64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Option<$name>> for GenericFormattedValue {
|
||||
fn from(v: Option<$name>) -> Self {
|
||||
skip_assert_initialized!();
|
||||
Self::$format_value(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$name> for GenericFormattedValue {
|
||||
fn from(v: $name) -> Self {
|
||||
skip_assert_initialized!();
|
||||
Self::$format_value(Some(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedValueIntrinsic for $name {
|
||||
type FormattedValueType = Option<$name>;
|
||||
}
|
||||
|
||||
impl TryFrom<GenericFormattedValue> for Option<$name> {
|
||||
type Error = TryFromGenericFormattedValueError;
|
||||
|
||||
fn try_from(v: GenericFormattedValue) -> Result<Option<$name>, Self::Error> {
|
||||
skip_assert_initialized!();
|
||||
if let GenericFormattedValue::$format_value(v) = v {
|
||||
Ok(v)
|
||||
} else {
|
||||
Err(TryFromGenericFormattedValueError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u64> for $name {
|
||||
type Error = GlibNoneError;
|
||||
|
||||
fn try_from(v: u64) -> Result<$name, GlibNoneError> {
|
||||
skip_assert_initialized!();
|
||||
unsafe { Self::try_from_glib(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromGlib<i64> for $name {
|
||||
type Error = GlibNoneError;
|
||||
#[inline]
|
||||
unsafe fn try_from_glib(val: i64) -> Result<Self, GlibNoneError> {
|
||||
skip_assert_initialized!();
|
||||
<$name as TryFromGlib<u64>>::try_from_glib(val as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecificFormattedValue for Option<$name> {}
|
||||
impl SpecificFormattedValueIntrinsic for $name {}
|
||||
|
||||
impl ops::Deref for $name {
|
||||
type Target = u64;
|
||||
|
||||
fn deref(&self) -> &u64 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::DerefMut for $name {
|
||||
fn deref_mut(&mut self) -> &mut u64 {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<u64> for $name {
|
||||
fn as_ref(&self) -> &u64 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<u64> for $name {
|
||||
fn as_mut(&mut self) -> &mut u64 {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl_op_same!($name, Add, add, AddAssign, add_assign);
|
||||
impl_op_same!($name, Sub, sub, SubAssign, sub_assign);
|
||||
impl_op_same!($name, Mul, mul, MulAssign, mul_assign);
|
||||
impl_op_same!($name, Div, div, DivAssign, div_assign);
|
||||
impl_op_same!($name, Rem, rem, RemAssign, rem_assign);
|
||||
|
||||
impl_op_u64!($name, Mul, mul, MulAssign, mul_assign);
|
||||
impl_op_u64!($name, Div, div, DivAssign, div_assign);
|
||||
impl_op_u64!($name, Rem, rem, RemAssign, rem_assign);
|
||||
|
||||
impl<ND: Borrow<u64>> MulDiv<ND> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn mul_div_floor(self, num: ND, denom: ND) -> Option<Self::Output> {
|
||||
self.0
|
||||
.mul_div_floor(*num.borrow(), *denom.borrow())
|
||||
.map($name)
|
||||
}
|
||||
|
||||
fn mul_div_round(self, num: ND, denom: ND) -> Option<Self::Output> {
|
||||
self.0
|
||||
.mul_div_round(*num.borrow(), *denom.borrow())
|
||||
.map($name)
|
||||
}
|
||||
|
||||
fn mul_div_ceil(self, num: ND, denom: ND) -> Option<Self::Output> {
|
||||
self.0
|
||||
.mul_div_ceil(*num.borrow(), *denom.borrow())
|
||||
.map($name)
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! option_glib_newtype_display {
|
||||
($name:ident, $unit:expr) => {
|
||||
impl crate::utils::Displayable for Option<$name> {
|
||||
type DisplayImpl = String;
|
||||
|
||||
fn display(self) -> String {
|
||||
if let Some(val) = self {
|
||||
val.display()
|
||||
} else {
|
||||
format!("undef. {}", $unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::utils::Displayable for $name {
|
||||
type DisplayImpl = String;
|
||||
|
||||
fn display(self) -> String {
|
||||
format!("{} {}", self.0, $unit)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_common_ops_for_newtype_u64!(Default);
|
||||
impl_format_value_traits!(Default, Default, Default);
|
||||
impl_common_ops_for_newtype_uint!(Default, u64);
|
||||
impl_format_value_traits!(Default, Default, Default, u64);
|
||||
option_glib_newtype_from_to!(Default, u64::MAX);
|
||||
option_glib_newtype_display!(Default, "(Default)");
|
||||
|
||||
impl_common_ops_for_newtype_u64!(Bytes);
|
||||
impl_format_value_traits!(Bytes, Bytes, Bytes);
|
||||
impl_common_ops_for_newtype_uint!(Bytes, u64);
|
||||
impl_format_value_traits!(Bytes, Bytes, Bytes, u64);
|
||||
option_glib_newtype_from_to!(Bytes, u64::MAX);
|
||||
option_glib_newtype_display!(Bytes, "bytes");
|
||||
|
||||
impl_format_value_traits!(ClockTime, Time, Time);
|
||||
impl_format_value_traits!(ClockTime, Time, Time, u64);
|
||||
|
||||
impl_common_ops_for_newtype_u64!(Buffers);
|
||||
impl_format_value_traits!(Buffers, Buffers, Buffers);
|
||||
impl_common_ops_for_newtype_uint!(Buffers, u64);
|
||||
impl_format_value_traits!(Buffers, Buffers, Buffers, u64);
|
||||
option_glib_newtype_from_to!(Buffers, Buffers::OFFSET_NONE);
|
||||
option_glib_newtype_display!(Buffers, "buffers");
|
||||
|
||||
|
@ -517,7 +292,7 @@ impl crate::utils::Displayable for Undefined {
|
|||
}
|
||||
}
|
||||
|
||||
impl_common_ops_for_newtype_u64!(Percent);
|
||||
impl_common_ops_for_newtype_uint!(Percent, u32);
|
||||
option_glib_newtype_display!(Percent, "%");
|
||||
|
||||
impl FormattedValue for Option<Percent> {
|
||||
|
|
|
@ -35,6 +35,9 @@ mod auto;
|
|||
pub use crate::auto::functions::*;
|
||||
pub use crate::auto::*;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
#[macro_use]
|
||||
mod log;
|
||||
pub use crate::log::*;
|
||||
|
@ -152,7 +155,6 @@ mod bus_unix;
|
|||
mod bus_windows;
|
||||
|
||||
mod child_proxy;
|
||||
#[macro_use]
|
||||
mod clock_time;
|
||||
#[cfg(feature = "ser_de")]
|
||||
mod clock_time_serde;
|
||||
|
|
416
gstreamer/src/macros.rs
Normal file
416
gstreamer/src/macros.rs
Normal file
|
@ -0,0 +1,416 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
macro_rules! impl_op_same(
|
||||
($name:ident, $op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident) => {
|
||||
impl<RHS: Borrow<$name>> ops::$op<RHS> for $name {
|
||||
type Output = Self;
|
||||
|
||||
fn $op_name(self, rhs: RHS) -> Self::Output {
|
||||
Self(self.0.$op_name(rhs.borrow().0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<RHS: Borrow<$name>> ops::$op<RHS> for &$name {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: RHS) -> Self::Output {
|
||||
(*self).$op_name(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<RHS: Borrow<$name>> ops::$op_assign<RHS> for $name {
|
||||
fn $op_assign_name(&mut self, rhs: RHS) {
|
||||
self.0.$op_assign_name(rhs.borrow().0)
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! impl_op_inner_type(
|
||||
($name:ident, $inner_type:ty, $op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident) => {
|
||||
impl ops::$op<$inner_type> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: $inner_type) -> Self::Output {
|
||||
$name(self.0.$op_name(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::$op<$inner_type> for &$name {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: $inner_type) -> Self::Output {
|
||||
(*self).$op_name(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::$op<$name> for $inner_type {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: $name) -> $name {
|
||||
$name(self.$op_name(rhs.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::$op<&$name> for $inner_type {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: &$name) -> $name {
|
||||
self.$op_name(*rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::$op_assign<$inner_type> for $name {
|
||||
fn $op_assign_name(&mut self, rhs: $inner_type) {
|
||||
self.0.$op_assign_name(rhs)
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! impl_common_ops_for_newtype_uint(
|
||||
($name:ident, $inner_type:ty) => {
|
||||
impl $name {
|
||||
pub const ZERO: Self = Self(0);
|
||||
pub const NONE: Option<Self> = None;
|
||||
|
||||
pub const fn is_zero(self) -> bool {
|
||||
self.0 == Self::ZERO.0
|
||||
}
|
||||
|
||||
#[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_type>::try_from(res_u128).unwrap()), false)
|
||||
} else {
|
||||
(Self(<$inner_type>::try_from((res_u128 - Self::MAX.0 as u128 - 1) as u64).unwrap()), true)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME add overflowing_add
|
||||
|
||||
#[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
|
||||
}
|
||||
}
|
||||
|
||||
impl_op_same!($name, Add, add, AddAssign, add_assign);
|
||||
impl_op_same!($name, Sub, sub, SubAssign, sub_assign);
|
||||
impl_op_same!($name, Mul, mul, MulAssign, mul_assign);
|
||||
impl_op_same!($name, Div, div, DivAssign, div_assign);
|
||||
impl_op_same!($name, Rem, rem, RemAssign, rem_assign);
|
||||
|
||||
impl_op_inner_type!($name, $inner_type, Mul, mul, MulAssign, mul_assign);
|
||||
impl_op_inner_type!($name, $inner_type, Div, div, DivAssign, div_assign);
|
||||
impl_op_inner_type!($name, $inner_type, Rem, rem, RemAssign, rem_assign);
|
||||
|
||||
impl<ND: Borrow<$inner_type>> MulDiv<ND> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn mul_div_floor(self, num: ND, denom: ND) -> Option<Self::Output> {
|
||||
self.0
|
||||
.mul_div_floor(*num.borrow(), *denom.borrow())
|
||||
.map($name)
|
||||
}
|
||||
|
||||
fn mul_div_round(self, num: ND, denom: ND) -> Option<Self::Output> {
|
||||
self.0
|
||||
.mul_div_round(*num.borrow(), *denom.borrow())
|
||||
.map($name)
|
||||
}
|
||||
|
||||
fn mul_div_ceil(self, num: ND, denom: ND) -> Option<Self::Output> {
|
||||
self.0
|
||||
.mul_div_ceil(*num.borrow(), *denom.borrow())
|
||||
.map($name)
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionOperations for $name {}
|
||||
|
||||
impl OptionCheckedAdd for $name {
|
||||
type Output = Self;
|
||||
|
||||
fn opt_checked_add(
|
||||
self,
|
||||
rhs: Self,
|
||||
) -> Result<Option<Self::Output>, opt_ops::CheckedError> {
|
||||
self.checked_add(rhs)
|
||||
.ok_or(opt_ops::CheckedError::Overflow)
|
||||
.map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionSaturatingAdd for $name {
|
||||
type Output = Self;
|
||||
fn opt_saturating_add(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.saturating_add(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionOverflowingAdd for $name {
|
||||
type Output = Self;
|
||||
fn opt_overflowing_add(self, rhs: Self) -> Option<(Self::Output, bool)> {
|
||||
let res = self.overflowing_add(rhs);
|
||||
Some((res.0, res.1))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionWrappingAdd for $name {
|
||||
type Output = Self;
|
||||
fn opt_wrapping_add(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.wrapping_add(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedSub for $name {
|
||||
type Output = Self;
|
||||
fn opt_checked_sub(
|
||||
self,
|
||||
rhs: Self,
|
||||
) -> Result<Option<Self::Output>, opt_ops::CheckedError> {
|
||||
self.checked_sub(rhs)
|
||||
.ok_or(opt_ops::CheckedError::Overflow)
|
||||
.map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionSaturatingSub for $name {
|
||||
type Output = Self;
|
||||
fn opt_saturating_sub(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.saturating_sub(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionOverflowingSub for $name {
|
||||
type Output = Self;
|
||||
fn opt_overflowing_sub(self, rhs: Self) -> Option<(Self::Output, bool)> {
|
||||
let res = self.overflowing_sub(rhs);
|
||||
Some((res.0, res.1))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionWrappingSub for $name {
|
||||
type Output = Self;
|
||||
fn opt_wrapping_sub(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.wrapping_sub(rhs))
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! impl_format_value_traits(
|
||||
($name:ident, $format:ident, $format_value:ident, $inner_type:ty) => {
|
||||
impl FormattedValue for Option<$name> {
|
||||
fn default_format() -> Format {
|
||||
Format::$format
|
||||
}
|
||||
|
||||
fn format(&self) -> Format {
|
||||
Format::$format
|
||||
}
|
||||
|
||||
unsafe fn from_raw(format: Format, value: i64) -> Option<$name> {
|
||||
debug_assert_eq!(format, Format::$format);
|
||||
FromGlib::from_glib(value as u64)
|
||||
}
|
||||
|
||||
unsafe fn into_raw_value(self) -> i64 {
|
||||
IntoGlib::into_glib(self) as i64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Option<$name>> for GenericFormattedValue {
|
||||
fn from(v: Option<$name>) -> Self {
|
||||
skip_assert_initialized!();
|
||||
Self::$format_value(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$name> for GenericFormattedValue {
|
||||
fn from(v: $name) -> Self {
|
||||
skip_assert_initialized!();
|
||||
Self::$format_value(Some(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedValueIntrinsic for $name {
|
||||
type FormattedValueType = Option<$name>;
|
||||
}
|
||||
|
||||
impl TryFrom<GenericFormattedValue> for Option<$name> {
|
||||
type Error = TryFromGenericFormattedValueError;
|
||||
|
||||
fn try_from(v: GenericFormattedValue) -> Result<Option<$name>, Self::Error> {
|
||||
skip_assert_initialized!();
|
||||
if let GenericFormattedValue::$format_value(v) = v {
|
||||
Ok(v)
|
||||
} else {
|
||||
Err(TryFromGenericFormattedValueError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<$inner_type> for $name {
|
||||
type Error = GlibNoneError;
|
||||
|
||||
fn try_from(v: $inner_type) -> Result<$name, GlibNoneError> {
|
||||
skip_assert_initialized!();
|
||||
unsafe { Self::try_from_glib(v as i64) }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromGlib<i64> for $name {
|
||||
type Error = GlibNoneError;
|
||||
#[inline]
|
||||
unsafe fn try_from_glib(val: i64) -> Result<Self, GlibNoneError> {
|
||||
skip_assert_initialized!();
|
||||
<$name as TryFromGlib<u64>>::try_from_glib(val as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecificFormattedValue for Option<$name> {}
|
||||
impl SpecificFormattedValueIntrinsic for $name {}
|
||||
|
||||
impl ops::Deref for $name {
|
||||
type Target = $inner_type;
|
||||
|
||||
fn deref(&self) -> &$inner_type {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::DerefMut for $name {
|
||||
fn deref_mut(&mut self) -> &mut $inner_type {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<$inner_type> for $name {
|
||||
fn as_ref(&self) -> &$inner_type {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<$inner_type> for $name {
|
||||
fn as_mut(&mut self) -> &mut $inner_type {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! option_glib_newtype_from_to {
|
||||
($type_:ident, $none_value:expr) => {
|
||||
#[doc(hidden)]
|
||||
impl IntoGlib for $type_ {
|
||||
type GlibType = u64;
|
||||
|
||||
fn into_glib(self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl OptionIntoGlib for $type_ {
|
||||
const GLIB_NONE: u64 = $none_value;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl TryFromGlib<u64> for $type_ {
|
||||
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($type_(val))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! option_glib_newtype_display {
|
||||
($name:ident, $unit:expr) => {
|
||||
impl crate::utils::Displayable for Option<$name> {
|
||||
type DisplayImpl = String;
|
||||
|
||||
fn display(self) -> String {
|
||||
if let Some(val) = self {
|
||||
val.display()
|
||||
} else {
|
||||
format!("undef. {}", $unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::utils::Displayable for $name {
|
||||
type DisplayImpl = String;
|
||||
|
||||
fn display(self) -> String {
|
||||
format!("{} {}", self.0, $unit)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue