forked from mirrors/gstreamer-rs
format: Add Signed<T>
<=> signed integer conversions
Co-authored-by: Sebastian Dröge <sebastian@centricular.com> Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1149>
This commit is contained in:
parent
88791294a5
commit
77fd187986
5 changed files with 125 additions and 60 deletions
|
@ -368,6 +368,7 @@ impl From<ClockTime> for Duration {
|
|||
|
||||
impl_common_ops_for_newtype_uint!(ClockTime, u64);
|
||||
impl_signed_div_mul!(ClockTime, u64);
|
||||
impl_signed_int_into_signed!(ClockTime, u64);
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Tell [`pad_clocktime`] what kind of time we're formatting
|
||||
|
@ -1342,4 +1343,37 @@ mod tests {
|
|||
fn attempt_to_build_from_u64max() {
|
||||
let _ = ClockTime::from_nseconds(u64::MAX);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_into_signed() {
|
||||
let time = crate::Signed::Positive(ClockTime::from_nseconds(0));
|
||||
assert_eq!(i64::try_from(time), Ok(0));
|
||||
|
||||
let time = crate::Signed::Positive(ClockTime::from_nseconds(123));
|
||||
assert_eq!(i64::try_from(time), Ok(123));
|
||||
|
||||
let time = crate::Signed::Positive(ClockTime::from_nseconds(u64::MAX - 1));
|
||||
assert!(i64::try_from(time).is_err());
|
||||
|
||||
let time = crate::Signed::Positive(ClockTime::from_nseconds(u64::MAX >> 1));
|
||||
assert_eq!(i64::MAX as i128, (u64::MAX >> 1) as i128);
|
||||
assert_eq!(i64::try_from(time), Ok(i64::MAX));
|
||||
|
||||
let time = crate::Signed::Negative(ClockTime::from_nseconds(0));
|
||||
assert_eq!(i64::try_from(time), Ok(0));
|
||||
|
||||
let time = crate::Signed::Negative(ClockTime::from_nseconds(123));
|
||||
assert_eq!(i64::try_from(time), Ok(-123));
|
||||
|
||||
let time = crate::Signed::Negative(ClockTime::from_nseconds(u64::MAX - 1));
|
||||
assert!(i64::try_from(time).is_err());
|
||||
|
||||
let time = crate::Signed::Negative(ClockTime::from_nseconds(u64::MAX >> 1));
|
||||
assert_eq!(i64::MIN as i128 + 1, -((u64::MAX >> 1) as i128));
|
||||
assert_eq!(i64::try_from(time), Ok(i64::MIN + 1));
|
||||
|
||||
let time = crate::Signed::Negative(ClockTime::from_nseconds((u64::MAX >> 1) + 1));
|
||||
assert_eq!(i64::MIN as i128, -(((u64::MAX >> 1) + 1) as i128));
|
||||
assert_eq!(i64::try_from(time), Ok(i64::MIN));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ impl Other {
|
|||
|
||||
impl_common_ops_for_newtype_uint!(Other, u64);
|
||||
impl_signed_div_mul!(Other, u64);
|
||||
impl_signed_int_into_signed!(Other, u64);
|
||||
option_glib_newtype_from_to!(Other, u64::MAX);
|
||||
glib_newtype_display!(Other, DisplayableOptionOther);
|
||||
|
||||
|
|
|
@ -517,6 +517,10 @@ macro_rules! impl_signed_ops(
|
|||
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
|
||||
|
@ -879,6 +883,26 @@ macro_rules! impl_signed_div_mul(
|
|||
|
||||
($typ:ty, $inner:ty, $signed_rhs:ty, $into_inner:expr) => {
|
||||
impl crate::Signed<$typ> {
|
||||
#[allow(dead_code)]
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
fn positive_from_inner(val: $inner) -> Option<Self> {
|
||||
skip_assert_initialized!();
|
||||
<$typ>::try_from(val).ok().map(crate::Signed::Positive)
|
||||
}
|
||||
|
||||
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"]
|
||||
pub fn checked_div(self, rhs:$signed_rhs) -> Option<Self> {
|
||||
use crate::Signed::*;
|
||||
|
@ -1274,27 +1298,6 @@ macro_rules! impl_signed_extra_div_mul(
|
|||
|
||||
macro_rules! impl_signed_div_mul_trait(
|
||||
($typ:ty, $inner:ty, $signed_rhs:ty, $into_inner:expr) => {
|
||||
impl crate::Signed<$typ> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
fn positive_from_inner(val: $inner) -> Option<Self> {
|
||||
skip_assert_initialized!();
|
||||
<$typ>::try_from(val).ok().map(crate::Signed::Positive)
|
||||
}
|
||||
|
||||
fn negative_from_inner(val: $inner) -> Option<Self> {
|
||||
skip_assert_initialized!();
|
||||
<$typ>::try_from(val).ok().map(crate::Signed::Negative)
|
||||
}
|
||||
}
|
||||
|
||||
impl muldiv::MulDiv<$signed_rhs> for crate::Signed<$typ> {
|
||||
type Output = Self;
|
||||
|
||||
|
@ -1628,3 +1631,59 @@ macro_rules! glib_newtype_display {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
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) => {
|
||||
impl TryFrom<crate::Signed<$typ>> for $signed {
|
||||
type Error = std::num::TryFromIntError;
|
||||
|
||||
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> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
|
|
@ -220,50 +220,17 @@ pub trait UnsignedIntoSigned: Copy + Sized {
|
|||
impl_unsigned_int_into_signed!(u64);
|
||||
impl_signed_ops!(u64);
|
||||
impl_signed_div_mul!(u64);
|
||||
impl_signed_int_into_signed!(u64);
|
||||
|
||||
impl_unsigned_int_into_signed!(u32);
|
||||
impl_signed_ops!(u32);
|
||||
impl_signed_div_mul!(u32);
|
||||
impl_signed_int_into_signed!(u32);
|
||||
|
||||
impl From<i64> for Signed<u64> {
|
||||
fn from(val: i64) -> Signed<u64> {
|
||||
skip_assert_initialized!();
|
||||
match val {
|
||||
positive if positive.is_positive() => Signed::Positive(positive as u64),
|
||||
i64::MIN => {
|
||||
// `i64::MIN.abs()` can't be represented as an `i64`
|
||||
Signed::Negative((-(i64::MIN as i128)) as u64)
|
||||
}
|
||||
negative => Signed::Negative((-negative) as u64),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<isize> for Signed<usize> {
|
||||
fn from(val: isize) -> Signed<usize> {
|
||||
skip_assert_initialized!();
|
||||
match val {
|
||||
positive if positive.is_positive() => Signed::Positive(positive as usize),
|
||||
isize::MIN => {
|
||||
// `isize::MIN.abs()` can't be represented as an `isize`
|
||||
Signed::Negative((-(isize::MIN as i128)) as usize)
|
||||
}
|
||||
negative => Signed::Negative((-negative) as usize),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// `i32::MIN.abs()` can't be represented as an `i32`
|
||||
impl From<i32> for Signed<u32> {
|
||||
fn from(val: i32) -> Signed<u32> {
|
||||
skip_assert_initialized!();
|
||||
if val.is_positive() {
|
||||
Signed::Positive(val as u32)
|
||||
} else {
|
||||
Signed::Negative((-(val as i64)) as u32)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl_unsigned_int_into_signed!(usize);
|
||||
impl_signed_ops!(usize);
|
||||
impl_signed_div_mul!(usize);
|
||||
impl_signed_int_into_signed!(usize);
|
||||
|
||||
pub trait NoneSignedBuilder: FormattedValueNoneBuilder {
|
||||
type Signed;
|
||||
|
|
|
@ -60,6 +60,7 @@ impl Buffers {
|
|||
|
||||
impl_common_ops_for_newtype_uint!(Buffers, u64);
|
||||
impl_signed_div_mul!(Buffers, u64);
|
||||
impl_signed_int_into_signed!(Buffers, u64);
|
||||
impl_format_value_traits!(Buffers, Buffers, Buffers, u64);
|
||||
option_glib_newtype_from_to!(Buffers, Buffers::OFFSET_NONE);
|
||||
glib_newtype_display!(Buffers, DisplayableOptionBuffers, Format::Buffers);
|
||||
|
@ -132,6 +133,7 @@ impl Bytes {
|
|||
|
||||
impl_common_ops_for_newtype_uint!(Bytes, u64);
|
||||
impl_signed_div_mul!(Bytes, u64);
|
||||
impl_signed_int_into_signed!(Bytes, u64);
|
||||
impl_format_value_traits!(Bytes, Bytes, Bytes, u64);
|
||||
option_glib_newtype_from_to!(Bytes, u64::MAX);
|
||||
glib_newtype_display!(Bytes, DisplayableOptionBytes, Format::Bytes);
|
||||
|
@ -222,6 +224,7 @@ impl Default {
|
|||
|
||||
impl_common_ops_for_newtype_uint!(Default, u64);
|
||||
impl_signed_div_mul!(Default, u64);
|
||||
impl_signed_int_into_signed!(Default, u64);
|
||||
impl_format_value_traits!(Default, Default, Default, u64);
|
||||
option_glib_newtype_from_to!(Default, u64::MAX);
|
||||
glib_newtype_display!(Default, DisplayableOptionDefault, Format::Default);
|
||||
|
@ -297,6 +300,7 @@ impl Percent {
|
|||
|
||||
impl_common_ops_for_newtype_uint!(Percent, u32, one: ffi::GST_FORMAT_PERCENT_SCALE as u32);
|
||||
impl_signed_div_mul!(Percent, u32);
|
||||
impl_signed_int_into_signed!(Percent, u32);
|
||||
|
||||
impl FormattedValue for Option<Percent> {
|
||||
type FullRange = Option<Percent>;
|
||||
|
|
Loading…
Reference in a new issue