forked from mirrors/gstreamer-rs
gst/format: shuffle types and traits
This commit is contained in:
parent
79377337a4
commit
eb4d997f0a
8 changed files with 1229 additions and 1176 deletions
|
@ -2,13 +2,16 @@
|
|||
|
||||
use glib::translate::*;
|
||||
use glib::StaticType;
|
||||
use muldiv::MulDiv;
|
||||
use num_integer::div_rem;
|
||||
use opt_ops::prelude::*;
|
||||
|
||||
use std::fmt;
|
||||
use std::io::{self, prelude::*};
|
||||
use std::ops;
|
||||
use std::time::Duration;
|
||||
use std::{cmp, fmt, str};
|
||||
|
||||
use super::{Format, FormattedValueError, GenericFormattedValue, Signed};
|
||||
use super::{
|
||||
FormattedValue, FormattedValueFullRange, FormattedValueIntrinsic, FormattedValueNoneBuilder,
|
||||
SpecificFormattedValue, SpecificFormattedValueFullRange, SpecificFormattedValueIntrinsic,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
|
||||
pub struct ClockTime(pub(crate) u64);
|
||||
|
@ -115,6 +118,85 @@ impl ClockTime {
|
|||
}
|
||||
}
|
||||
|
||||
impl Signed<ClockTime> {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns the `self` in nanoseconds.
|
||||
pub fn nseconds(self) -> Signed<u64> {
|
||||
match self {
|
||||
Signed::Positive(val) => Signed::Positive(val.nseconds()),
|
||||
Signed::Negative(val) => Signed::Negative(val.nseconds()),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Creates new value from nanoseconds.
|
||||
pub fn from_nseconds(val: Signed<u64>) -> Self {
|
||||
skip_assert_initialized!();
|
||||
match val {
|
||||
Signed::Positive(val) => Signed::Positive(ClockTime::from_nseconds(val)),
|
||||
Signed::Negative(val) => Signed::Negative(ClockTime::from_nseconds(val)),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns the `self` in microseconds.
|
||||
pub fn useconds(self) -> Signed<u64> {
|
||||
match self {
|
||||
Signed::Positive(val) => Signed::Positive(val.useconds()),
|
||||
Signed::Negative(val) => Signed::Negative(val.useconds()),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Creates new value from microseconds.
|
||||
pub fn from_useconds(val: Signed<u64>) -> Self {
|
||||
skip_assert_initialized!();
|
||||
match val {
|
||||
Signed::Positive(val) => Signed::Positive(ClockTime::from_useconds(val)),
|
||||
Signed::Negative(val) => Signed::Negative(ClockTime::from_useconds(val)),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns the `self` in milliseconds.
|
||||
pub fn mseconds(self) -> Signed<u64> {
|
||||
match self {
|
||||
Signed::Positive(val) => Signed::Positive(val.mseconds()),
|
||||
Signed::Negative(val) => Signed::Negative(val.mseconds()),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Creates new value from milliseconds.
|
||||
pub fn from_mseconds(val: Signed<u64>) -> Self {
|
||||
skip_assert_initialized!();
|
||||
match val {
|
||||
Signed::Positive(val) => Signed::Positive(ClockTime::from_mseconds(val)),
|
||||
Signed::Negative(val) => Signed::Negative(ClockTime::from_mseconds(val)),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns the `self` in seconds.
|
||||
pub fn seconds(self) -> Signed<u64> {
|
||||
match self {
|
||||
Signed::Positive(val) => Signed::Positive(val.seconds()),
|
||||
Signed::Negative(val) => Signed::Negative(val.seconds()),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Creates new value from seconds.
|
||||
pub fn from_seconds(val: Signed<u64>) -> Self {
|
||||
skip_assert_initialized!();
|
||||
match val {
|
||||
Signed::Positive(val) => Signed::Positive(ClockTime::from_seconds(val)),
|
||||
Signed::Negative(val) => Signed::Negative(ClockTime::from_seconds(val)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_format_value_traits!(ClockTime, Time, Time, u64);
|
||||
option_glib_newtype_from_to!(ClockTime, ffi::GST_CLOCK_TIME_NONE);
|
||||
|
||||
impl glib::value::ValueType for ClockTime {
|
||||
|
@ -324,13 +406,13 @@ fn write_clocktime<W: io::Write>(
|
|||
precision: usize,
|
||||
) -> io::Result<()> {
|
||||
skip_assert_initialized!();
|
||||
let precision = cmp::min(9, precision);
|
||||
let precision = std::cmp::min(9, precision);
|
||||
|
||||
if let Some(ns) = clocktime.map(ClockTime::nseconds) {
|
||||
// Split the time into parts
|
||||
let (s, ns) = div_rem(ns, 1_000_000_000);
|
||||
let (m, s) = div_rem(s, 60);
|
||||
let (h, m) = div_rem(m, 60);
|
||||
let (s, ns) = num_integer::div_rem(ns, 1_000_000_000);
|
||||
let (m, s) = num_integer::div_rem(s, 60);
|
||||
let (h, m) = num_integer::div_rem(m, 60);
|
||||
|
||||
// Write HH:MM:SS
|
||||
write!(writer, "{}:{:02}:{:02}", h, m, s)?;
|
||||
|
@ -340,7 +422,7 @@ fn write_clocktime<W: io::Write>(
|
|||
// The value is zero-padded so always 9 digits long
|
||||
let mut buf = [0u8; 9];
|
||||
write!(&mut buf[..], "{:09}", ns).unwrap();
|
||||
let buf_str = str::from_utf8(&buf[..]).unwrap();
|
||||
let buf_str = std::str::from_utf8(&buf[..]).unwrap();
|
||||
|
||||
// Write decimal point and a prefix of the nanoseconds for more precision
|
||||
write!(writer, ".{:.p$}", buf_str, p = precision)?;
|
||||
|
@ -372,7 +454,7 @@ fn fmt_opt_clock_time(ct: Option<ClockTime>, f: &mut fmt::Formatter) -> fmt::Res
|
|||
let mut cursor = io::Cursor::new(&mut buf[..]);
|
||||
write_clocktime(&mut cursor, ct, precision).unwrap();
|
||||
let pos = cursor.position() as usize;
|
||||
let buf_str = str::from_utf8(&buf[..pos]).unwrap();
|
||||
let buf_str = std::str::from_utf8(&buf[..pos]).unwrap();
|
||||
|
||||
let sign = if ct.is_some() {
|
||||
Sign::NonNegative
|
||||
|
@ -436,6 +518,7 @@ impl std::iter::Sum for ClockTime {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use crate::{Signed, UnsignedIntoSigned};
|
||||
use opt_ops::prelude::*;
|
||||
|
||||
const CT_1: ClockTime = ClockTime::from_nseconds(1);
|
||||
const CT_2: ClockTime = ClockTime::from_nseconds(2);
|
||||
|
@ -729,6 +812,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn mul_div_ops() {
|
||||
use muldiv::MulDiv;
|
||||
|
||||
assert_eq!(CT_1.mul_div_floor(7, 3), Some(CT_2));
|
||||
|
||||
assert_eq!(P_CT_1.mul_div_floor(7u64, 3), Some(P_CT_2));
|
||||
|
|
175
gstreamer/src/format/compatible.rs
Normal file
175
gstreamer/src/format/compatible.rs
Normal file
|
@ -0,0 +1,175 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use super::{Format, FormattedValueError, GenericFormattedValue};
|
||||
use super::{FormattedValue, SpecificFormattedValue};
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// A trait implemented on types which can hold [`FormattedValue`]s compatible with parameter `F`.
|
||||
///
|
||||
/// This trait is auto-implemented based on [`FormattedValue`]s additional traits
|
||||
/// such as [`SpecificFormattedValue`].
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// Consider the following function:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use gstreamer::{ClockTime, CompatibleFormattedValue, FormattedValue, GenericFormattedValue};
|
||||
/// fn with_compatible_formats<V: FormattedValue>(
|
||||
/// arg1: V,
|
||||
/// arg2: impl CompatibleFormattedValue<V>,
|
||||
/// ) {
|
||||
/// // This is required to access arg2 as a FormattedValue:
|
||||
/// let _arg2 = arg2.try_into_checked(arg1).unwrap();
|
||||
/// }
|
||||
///
|
||||
/// // This is Ok because arg1 is a ClockTime and arg2 is
|
||||
/// // an Option<ClockTime> which are compatible format-wise.
|
||||
/// with_compatible_formats(ClockTime::ZERO, ClockTime::NONE);
|
||||
///
|
||||
/// // This is Ok because arg1 is a ClockTime and arg2 is
|
||||
/// // a GenericFormattedValue which are compatible format-wise.
|
||||
/// with_compatible_formats(
|
||||
/// ClockTime::ZERO,
|
||||
/// GenericFormattedValue::Time(None),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// Users are able to call the function with arguments:
|
||||
///
|
||||
/// 1. of the same type (e.g. `ClockTime`),
|
||||
/// 2. of different types, but able to hold a value of the same [`Format`]
|
||||
/// (e.g. `ClockTime` and `Option<ClockTime>`).
|
||||
/// 3. One of a Formatted Value (specific or generic), the other being
|
||||
/// a `GenericFormattedValue`.
|
||||
///
|
||||
/// Format compatibility for cases 1 and 2 is enforced by
|
||||
/// the type system, while case 3 will be checked at runtime time.
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// # use gstreamer::{ClockTime, CompatibleFormattedValue, FormattedValue, format::Bytes};
|
||||
/// # fn with_compatible_formats<V: FormattedValue>(
|
||||
/// # arg1: V,
|
||||
/// # arg2: impl CompatibleFormattedValue<V>,
|
||||
/// # ) {}
|
||||
/// // This doesn't compile because the arguments are not compatible:
|
||||
/// let _ = with_compatible_formats(ClockTime::ZERO, Bytes(Some(42)));
|
||||
/// ```
|
||||
///
|
||||
/// Note: users will not be able use `arg2` directly unless format
|
||||
/// check succeeds:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// # use gstreamer::{CompatibleFormattedValue, FormattedValue};
|
||||
/// fn with_compatible_formats<V: FormattedValue>(
|
||||
/// arg1: V,
|
||||
/// arg2: impl CompatibleFormattedValue<V>,
|
||||
/// ) {
|
||||
/// // This doesn't compile because arg2 hasn't been checked:
|
||||
/// let _format = arg2.format();
|
||||
/// }
|
||||
/// ```
|
||||
pub trait CompatibleFormattedValue<V: FormattedValue> {
|
||||
type Original: FormattedValue;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns `Ok(self)` with its type restored if it is compatible with the format of `other`.
|
||||
///
|
||||
/// When used with compatible [`SpecificFormattedValue`]s, checks
|
||||
/// are enforced by the type system, no runtime checks are performed.
|
||||
///
|
||||
/// When used with [`FormattedValue`] / [`GenericFormattedValue`] and
|
||||
/// vice versa, a runtime format check is performed. If the check fails,
|
||||
/// `Err(FormattedValueError)` is returned.
|
||||
fn try_into_checked(self, other: V) -> Result<Self::Original, FormattedValueError>;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns `Ok(self)` with its type restored if it is compatible with the format of `V`.
|
||||
///
|
||||
/// When possible, prefer using [`Self::try_into_checked`] which
|
||||
/// reduces the risk of missuse.
|
||||
///
|
||||
/// When used with compatible [`SpecificFormattedValue`]s, checks
|
||||
/// are enforced by the type system, no runtime checks are performed.
|
||||
///
|
||||
/// When used with [`SpecificFormattedValue`] as a parameter and
|
||||
/// a [`GenericFormattedValue`] as `Self`, a runtime check is perfomed
|
||||
/// against the default format of the parameter. If the check fails,
|
||||
/// `Err(FormattedValueError)` is returned.
|
||||
///
|
||||
/// When used with [`GenericFormattedValue`] as a parameter and
|
||||
/// a [`SpecificFormattedValue`] as `Self`, the `format` argument
|
||||
/// used. If the check fails, `Err(FormattedValueError)` is returned.
|
||||
fn try_into_checked_explicit(
|
||||
self,
|
||||
format: Format,
|
||||
) -> Result<Self::Original, FormattedValueError>;
|
||||
}
|
||||
|
||||
impl<T, V> CompatibleFormattedValue<V> for T
|
||||
where
|
||||
V: SpecificFormattedValue,
|
||||
T: SpecificFormattedValue<FullRange = V::FullRange>,
|
||||
{
|
||||
type Original = Self;
|
||||
fn try_into_checked(self, _other: V) -> Result<Self, FormattedValueError> {
|
||||
skip_assert_initialized!();
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn try_into_checked_explicit(
|
||||
self,
|
||||
_format: Format,
|
||||
) -> Result<Self::Original, FormattedValueError> {
|
||||
skip_assert_initialized!();
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SpecificFormattedValue> CompatibleFormattedValue<GenericFormattedValue> for T {
|
||||
type Original = Self;
|
||||
fn try_into_checked(self, other: GenericFormattedValue) -> Result<Self, FormattedValueError> {
|
||||
skip_assert_initialized!();
|
||||
if self.format() == other.format() {
|
||||
Ok(self)
|
||||
} else {
|
||||
Err(FormattedValueError(self.format()))
|
||||
}
|
||||
}
|
||||
|
||||
fn try_into_checked_explicit(
|
||||
self,
|
||||
format: Format,
|
||||
) -> Result<Self::Original, FormattedValueError> {
|
||||
skip_assert_initialized!();
|
||||
if self.format() == format {
|
||||
Ok(self)
|
||||
} else {
|
||||
Err(FormattedValueError(self.format()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: SpecificFormattedValue> CompatibleFormattedValue<V> for GenericFormattedValue {
|
||||
type Original = Self;
|
||||
fn try_into_checked(self, _other: V) -> Result<Self, FormattedValueError> {
|
||||
skip_assert_initialized!();
|
||||
if self.format() == V::default_format() {
|
||||
Ok(self)
|
||||
} else {
|
||||
Err(FormattedValueError(self.format()))
|
||||
}
|
||||
}
|
||||
|
||||
fn try_into_checked_explicit(
|
||||
self,
|
||||
_format: Format,
|
||||
) -> Result<Self::Original, FormattedValueError> {
|
||||
skip_assert_initialized!();
|
||||
if self.format() == V::default_format() {
|
||||
Ok(self)
|
||||
} else {
|
||||
Err(FormattedValueError(self.format()))
|
||||
}
|
||||
}
|
||||
}
|
202
gstreamer/src/format/generic.rs
Normal file
202
gstreamer/src/format/generic.rs
Normal file
|
@ -0,0 +1,202 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::FromGlib;
|
||||
use std::fmt;
|
||||
|
||||
use crate::utils::Displayable;
|
||||
|
||||
use super::{
|
||||
Buffers, Bytes, ClockTime, Default, Format, FormattedValueError, Percent, Signed, Undefined,
|
||||
};
|
||||
use super::{
|
||||
CompatibleFormattedValue, FormattedValue, FormattedValueFullRange, FormattedValueIntrinsic,
|
||||
FormattedValueNoneBuilder, UnsignedIntoSigned,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum GenericFormattedValue {
|
||||
Undefined(Undefined),
|
||||
Default(Option<Default>),
|
||||
Bytes(Option<Bytes>),
|
||||
Time(Option<ClockTime>),
|
||||
Buffers(Option<Buffers>),
|
||||
Percent(Option<Percent>),
|
||||
Other(Format, i64),
|
||||
}
|
||||
|
||||
impl fmt::Display for GenericFormattedValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::Undefined(val) => val.fmt(f),
|
||||
Self::Default(val) => val.display().fmt(f),
|
||||
Self::Bytes(val) => val.display().fmt(f),
|
||||
Self::Time(val) => val.display().fmt(f),
|
||||
Self::Buffers(val) => val.display().fmt(f),
|
||||
Self::Percent(val) => val.display().fmt(f),
|
||||
Self::Other(format, val) => write!(f, "{} ({:?})", val, format),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericFormattedValue {
|
||||
pub fn new(format: Format, value: i64) -> Self {
|
||||
skip_assert_initialized!();
|
||||
match format {
|
||||
Format::Undefined => Self::Undefined(Undefined(value)),
|
||||
Format::Default => Self::Default(unsafe { FromGlib::from_glib(value as u64) }),
|
||||
Format::Bytes => Self::Bytes(unsafe { FromGlib::from_glib(value as u64) }),
|
||||
Format::Time => Self::Time(unsafe { FromGlib::from_glib(value as u64) }),
|
||||
Format::Buffers => Self::Buffers(unsafe { FromGlib::from_glib(value as u64) }),
|
||||
Format::Percent => {
|
||||
Self::Percent(unsafe { FormattedValueFullRange::from_raw(format, value) })
|
||||
}
|
||||
Format::__Unknown(_) => Self::Other(format, value),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(alias = "get_format")]
|
||||
pub fn format(&self) -> Format {
|
||||
match *self {
|
||||
Self::Undefined(_) => Format::Undefined,
|
||||
Self::Default(_) => Format::Default,
|
||||
Self::Bytes(_) => Format::Bytes,
|
||||
Self::Time(_) => Format::Time,
|
||||
Self::Buffers(_) => Format::Buffers,
|
||||
Self::Percent(_) => Format::Percent,
|
||||
Self::Other(f, _) => f,
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(alias = "get_value")]
|
||||
pub fn value(&self) -> i64 {
|
||||
unsafe {
|
||||
match *self {
|
||||
Self::Undefined(v) => v.0,
|
||||
Self::Default(v) => v.into_raw_value(),
|
||||
Self::Bytes(v) => v.into_raw_value(),
|
||||
Self::Time(v) => v.into_raw_value(),
|
||||
Self::Buffers(v) => v.into_raw_value(),
|
||||
Self::Percent(v) => v.into_raw_value(),
|
||||
Self::Other(_, v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedValue for GenericFormattedValue {
|
||||
// The intrinsic value for `GenericFormattedValue` is also
|
||||
// `GenericFormattedValue`. We can't dissociate the `Option`
|
||||
// from the variants' inner type since they are not all `Option`s.
|
||||
type FullRange = GenericFormattedValue;
|
||||
|
||||
fn default_format() -> Format {
|
||||
Format::Undefined
|
||||
}
|
||||
|
||||
fn format(&self) -> Format {
|
||||
self.format()
|
||||
}
|
||||
|
||||
fn is_some(&self) -> bool {
|
||||
match self {
|
||||
Self::Undefined(_) => true,
|
||||
Self::Default(v) => v.is_some(),
|
||||
Self::Bytes(v) => v.is_some(),
|
||||
Self::Time(v) => v.is_some(),
|
||||
Self::Buffers(v) => v.is_some(),
|
||||
Self::Percent(v) => v.is_some(),
|
||||
Self::Other(..) => true,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn into_raw_value(self) -> i64 {
|
||||
self.value()
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedValueFullRange for GenericFormattedValue {
|
||||
unsafe fn from_raw(format: Format, value: i64) -> Self {
|
||||
GenericFormattedValue::new(format, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedValueIntrinsic for GenericFormattedValue {}
|
||||
|
||||
impl FormattedValueNoneBuilder for GenericFormattedValue {
|
||||
#[track_caller]
|
||||
fn none() -> Self {
|
||||
panic!(concat!(
|
||||
"`GenericFormattedValue` can't build `None` without knowing",
|
||||
"the target format. Use `GenericFormattedValue::none_for_format`",
|
||||
));
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn none_for_format(format: Format) -> Self {
|
||||
skip_assert_initialized!();
|
||||
match format {
|
||||
Format::Undefined => panic!("`None` can't be represented by `Undefined`"),
|
||||
Format::Default => Self::Default(None),
|
||||
Format::Bytes => Self::Bytes(None),
|
||||
Format::Time => Self::Time(None),
|
||||
Format::Buffers => Self::Buffers(None),
|
||||
Format::Percent => Self::Percent(None),
|
||||
Format::__Unknown(_) => panic!("`None` can't be represented by `__Unknown`"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UnsignedIntoSigned for GenericFormattedValue {
|
||||
type Signed = Signed<GenericFormattedValue>;
|
||||
|
||||
#[track_caller]
|
||||
fn into_positive(self) -> Signed<GenericFormattedValue> {
|
||||
match self {
|
||||
GenericFormattedValue::Undefined(_) => {
|
||||
unimplemented!("`GenericFormattedValue::Undefined` is already signed")
|
||||
}
|
||||
GenericFormattedValue::Other(..) => {
|
||||
unimplemented!("`GenericFormattedValue::Other` is already signed")
|
||||
}
|
||||
unsigned_inner => Signed::Positive(unsigned_inner),
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn into_negative(self) -> Signed<GenericFormattedValue> {
|
||||
match self {
|
||||
GenericFormattedValue::Undefined(_) => {
|
||||
unimplemented!("`GenericFormattedValue::Undefined` is already signed")
|
||||
}
|
||||
GenericFormattedValue::Other(..) => {
|
||||
unimplemented!("`GenericFormattedValue::Other` is already signed")
|
||||
}
|
||||
unsigned_inner => Signed::Negative(unsigned_inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CompatibleFormattedValue<GenericFormattedValue> for GenericFormattedValue {
|
||||
type Original = Self;
|
||||
fn try_into_checked(self, other: GenericFormattedValue) -> Result<Self, FormattedValueError> {
|
||||
skip_assert_initialized!();
|
||||
if self.format() == other.format() {
|
||||
Ok(self)
|
||||
} else {
|
||||
Err(FormattedValueError(self.format()))
|
||||
}
|
||||
}
|
||||
|
||||
fn try_into_checked_explicit(
|
||||
self,
|
||||
format: Format,
|
||||
) -> Result<Self::Original, FormattedValueError> {
|
||||
skip_assert_initialized!();
|
||||
if self.format() == format {
|
||||
Ok(self)
|
||||
} else {
|
||||
Err(FormattedValueError(self.format()))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
macro_rules! impl_trait_op_same(
|
||||
($name:ident, $op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident) => {
|
||||
impl ops::$op<$name> for $name {
|
||||
impl std::ops::$op<$name> for $name {
|
||||
type Output = Self;
|
||||
|
||||
fn $op_name(self, rhs: $name) -> Self::Output {
|
||||
|
@ -10,7 +10,7 @@ macro_rules! impl_trait_op_same(
|
|||
}
|
||||
}
|
||||
|
||||
impl ops::$op_assign<$name> for $name {
|
||||
impl std::ops::$op_assign<$name> for $name {
|
||||
fn $op_assign_name(&mut self, rhs: $name) {
|
||||
self.0.$op_assign_name(rhs.0)
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ macro_rules! impl_non_trait_op_same(
|
|||
|
||||
macro_rules! impl_trait_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 {
|
||||
impl std::ops::$op<$inner_type> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: $inner_type) -> Self::Output {
|
||||
|
@ -106,7 +106,7 @@ macro_rules! impl_trait_op_inner_type(
|
|||
}
|
||||
}
|
||||
|
||||
impl ops::$op<$name> for $inner_type {
|
||||
impl std::ops::$op<$name> for $inner_type {
|
||||
type Output = $name;
|
||||
|
||||
fn $op_name(self, rhs: $name) -> $name {
|
||||
|
@ -114,7 +114,7 @@ macro_rules! impl_trait_op_inner_type(
|
|||
}
|
||||
}
|
||||
|
||||
impl ops::$op_assign<$inner_type> for $name {
|
||||
impl std::ops::$op_assign<$inner_type> for $name {
|
||||
fn $op_assign_name(&mut self, rhs: $inner_type) {
|
||||
self.0.$op_assign_name(rhs)
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
impl_unsigned_int_into_signed!($name);
|
||||
impl_signed_ops!($name, $inner_type, $name::ZERO);
|
||||
|
||||
impl MulDiv<$inner_type> for $name {
|
||||
impl muldiv::MulDiv<$inner_type> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn mul_div_floor(self, num: $inner_type, denom: $inner_type) -> Option<Self::Output> {
|
||||
|
@ -272,9 +272,9 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionOperations for $name {}
|
||||
impl opt_ops::OptionOperations for $name {}
|
||||
|
||||
impl OptionCheckedAdd for $name {
|
||||
impl opt_ops::OptionCheckedAdd for $name {
|
||||
type Output = Self;
|
||||
fn opt_checked_add(
|
||||
self,
|
||||
|
@ -286,14 +286,14 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionSaturatingAdd for $name {
|
||||
impl opt_ops::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 {
|
||||
impl opt_ops::OptionOverflowingAdd for $name {
|
||||
type Output = Self;
|
||||
fn opt_overflowing_add(self, rhs: Self) -> Option<(Self::Output, bool)> {
|
||||
let res = self.overflowing_add(rhs);
|
||||
|
@ -301,14 +301,14 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionWrappingAdd for $name {
|
||||
impl opt_ops::OptionWrappingAdd for $name {
|
||||
type Output = Self;
|
||||
fn opt_wrapping_add(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.wrapping_add(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedDiv<$inner_type> for $name {
|
||||
impl opt_ops::OptionCheckedDiv<$inner_type> for $name {
|
||||
type Output = Self;
|
||||
fn opt_checked_div(self, rhs: $inner_type) -> Result<Option<Self::Output>, opt_ops::Error> {
|
||||
if rhs == 0 {
|
||||
|
@ -321,7 +321,7 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedMul<$inner_type> for $name {
|
||||
impl opt_ops::OptionCheckedMul<$inner_type> for $name {
|
||||
type Output = Self;
|
||||
fn opt_checked_mul(
|
||||
self,
|
||||
|
@ -333,14 +333,14 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionSaturatingMul<$inner_type> for $name {
|
||||
impl opt_ops::OptionSaturatingMul<$inner_type> for $name {
|
||||
type Output = Self;
|
||||
fn opt_saturating_mul(self, rhs: $inner_type) -> Option<Self::Output> {
|
||||
Some(self.saturating_mul(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionOverflowingMul<$inner_type> for $name {
|
||||
impl opt_ops::OptionOverflowingMul<$inner_type> for $name {
|
||||
type Output = Self;
|
||||
fn opt_overflowing_mul(self, rhs: $inner_type) -> Option<(Self::Output, bool)> {
|
||||
let res = self.overflowing_mul(rhs);
|
||||
|
@ -348,14 +348,14 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionWrappingMul<$inner_type> for $name {
|
||||
impl opt_ops::OptionWrappingMul<$inner_type> for $name {
|
||||
type Output = Self;
|
||||
fn opt_wrapping_mul(self, rhs: $inner_type) -> Option<Self::Output> {
|
||||
Some(self.wrapping_mul(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedRem<$inner_type> for $name {
|
||||
impl opt_ops::OptionCheckedRem<$inner_type> for $name {
|
||||
type Output = Self;
|
||||
fn opt_checked_rem(self, rhs: $inner_type) -> Result<Option<Self::Output>, opt_ops::Error> {
|
||||
if rhs == 0 {
|
||||
|
@ -368,7 +368,7 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedSub for $name {
|
||||
impl opt_ops::OptionCheckedSub for $name {
|
||||
type Output = Self;
|
||||
fn opt_checked_sub(
|
||||
self,
|
||||
|
@ -380,14 +380,14 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionSaturatingSub for $name {
|
||||
impl opt_ops::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 {
|
||||
impl opt_ops::OptionOverflowingSub for $name {
|
||||
type Output = Self;
|
||||
fn opt_overflowing_sub(self, rhs: Self) -> Option<(Self::Output, bool)> {
|
||||
let res = self.overflowing_sub(rhs);
|
||||
|
@ -395,7 +395,7 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionWrappingSub for $name {
|
||||
impl opt_ops::OptionWrappingSub for $name {
|
||||
type Output = Self;
|
||||
fn opt_wrapping_sub(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.wrapping_sub(rhs))
|
||||
|
@ -577,25 +577,25 @@ macro_rules! impl_signed_ops(
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialOrd<crate::Signed<$type>> for crate::Signed<$type> {
|
||||
impl std::cmp::PartialOrd<crate::Signed<$type>> for crate::Signed<$type> {
|
||||
fn partial_cmp(&self, other: &crate::Signed<$type>) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<$type> for crate::Signed<$type> {
|
||||
impl std::cmp::PartialEq<$type> for crate::Signed<$type> {
|
||||
fn eq(&self, other: &$type) -> bool {
|
||||
self.eq(&crate::Signed::Positive(*other))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd<$type> for crate::Signed<$type> {
|
||||
impl std::cmp::PartialOrd<$type> for crate::Signed<$type> {
|
||||
fn partial_cmp(&self, other: &$type) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(&crate::Signed::Positive(*other)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for crate::Signed<$type> {
|
||||
impl std::cmp::Ord for crate::Signed<$type> {
|
||||
fn cmp(&self, other: &crate::Signed<$type>) -> std::cmp::Ordering {
|
||||
use crate::Signed::*;
|
||||
match (self, other) {
|
||||
|
@ -607,9 +607,9 @@ macro_rules! impl_signed_ops(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionOperations for crate::Signed<$type> {}
|
||||
impl opt_ops::OptionOperations for crate::Signed<$type> {}
|
||||
|
||||
impl OptionCheckedAdd for crate::Signed<$type> {
|
||||
impl opt_ops::OptionCheckedAdd for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_checked_add(
|
||||
self,
|
||||
|
@ -621,14 +621,14 @@ macro_rules! impl_signed_ops(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionSaturatingAdd for crate::Signed<$type> {
|
||||
impl opt_ops::OptionSaturatingAdd for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_saturating_add(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.saturating_add(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedSub for crate::Signed<$type> {
|
||||
impl opt_ops::OptionCheckedSub for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_checked_sub(
|
||||
self,
|
||||
|
@ -640,7 +640,7 @@ macro_rules! impl_signed_ops(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionSaturatingSub for crate::Signed<$type> {
|
||||
impl opt_ops::OptionSaturatingSub for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_saturating_sub(self, rhs: Self) -> Option<Self::Output> {
|
||||
Some(self.saturating_sub(rhs))
|
||||
|
@ -890,7 +890,7 @@ macro_rules! impl_signed_div_mul(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedDiv<$signed_rhs> for crate::Signed<$type> {
|
||||
impl opt_ops::OptionCheckedDiv<$signed_rhs> for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_checked_div(self, rhs: $signed_rhs) -> Result<Option<Self::Output>, opt_ops::Error> {
|
||||
if rhs == 0 {
|
||||
|
@ -902,7 +902,7 @@ macro_rules! impl_signed_div_mul(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedMul<$signed_rhs> for crate::Signed<$type> {
|
||||
impl opt_ops::OptionCheckedMul<$signed_rhs> for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_checked_mul(self, rhs: $signed_rhs) -> Result<Option<Self::Output>, opt_ops::Error> {
|
||||
self.checked_mul(rhs)
|
||||
|
@ -911,14 +911,14 @@ macro_rules! impl_signed_div_mul(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionSaturatingMul<$signed_rhs> for crate::Signed<$type> {
|
||||
impl opt_ops::OptionSaturatingMul<$signed_rhs> for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_saturating_mul(self, rhs: $signed_rhs) -> Option<Self::Output> {
|
||||
Some(self.saturating_mul(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedRem<$signed_rhs> for crate::Signed<$type> {
|
||||
impl opt_ops::OptionCheckedRem<$signed_rhs> for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_checked_rem(self, rhs: $signed_rhs) -> Result<Option<Self::Output>, opt_ops::Error> {
|
||||
if rhs == 0 {
|
||||
|
@ -930,7 +930,7 @@ macro_rules! impl_signed_div_mul(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedDiv<$inner_type> for crate::Signed<$type> {
|
||||
impl opt_ops::OptionCheckedDiv<$inner_type> for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_checked_div(self, rhs: $inner_type) -> Result<Option<Self::Output>, opt_ops::Error> {
|
||||
if rhs == 0 {
|
||||
|
@ -942,7 +942,7 @@ macro_rules! impl_signed_div_mul(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedMul<$inner_type> for crate::Signed<$type> {
|
||||
impl opt_ops::OptionCheckedMul<$inner_type> for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_checked_mul(self, rhs: $inner_type) -> Result<Option<Self::Output>, opt_ops::Error> {
|
||||
self.checked_mul_unsigned(rhs)
|
||||
|
@ -951,14 +951,14 @@ macro_rules! impl_signed_div_mul(
|
|||
}
|
||||
}
|
||||
|
||||
impl OptionSaturatingMul<$inner_type> for crate::Signed<$type> {
|
||||
impl opt_ops::OptionSaturatingMul<$inner_type> for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_saturating_mul(self, rhs: $inner_type) -> Option<Self::Output> {
|
||||
Some(self.saturating_mul_unsigned(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionCheckedRem<$inner_type> for crate::Signed<$type> {
|
||||
impl opt_ops::OptionCheckedRem<$inner_type> for crate::Signed<$type> {
|
||||
type Output = Self;
|
||||
fn opt_checked_rem(self, rhs: $inner_type) -> Result<Option<Self::Output>, opt_ops::Error> {
|
||||
if rhs == 0 {
|
||||
|
@ -997,7 +997,7 @@ macro_rules! impl_signed_div_mul_trait(
|
|||
}
|
||||
}
|
||||
|
||||
impl MulDiv<$signed_rhs> for crate::Signed<$type> {
|
||||
impl muldiv::MulDiv<$signed_rhs> for crate::Signed<$type> {
|
||||
type Output = crate::Signed<$type>;
|
||||
|
||||
fn mul_div_floor(self, num: $signed_rhs, denom: $signed_rhs) -> Option<Self::Output> {
|
||||
|
@ -1049,7 +1049,7 @@ macro_rules! impl_signed_div_mul_trait(
|
|||
}
|
||||
}
|
||||
|
||||
impl MulDiv<$inner_type> for crate::Signed<$type> {
|
||||
impl muldiv::MulDiv<$inner_type> for crate::Signed<$type> {
|
||||
type Output = crate::Signed<$type>;
|
||||
|
||||
fn mul_div_floor(self, num: $inner_type, denom: $inner_type) -> Option<Self::Output> {
|
||||
|
@ -1209,7 +1209,7 @@ macro_rules! impl_format_value_traits(
|
|||
}
|
||||
}
|
||||
|
||||
impl ops::Deref for $name {
|
||||
impl std::ops::Deref for $name {
|
||||
type Target = $inner_type;
|
||||
|
||||
fn deref(&self) -> &$inner_type {
|
||||
|
@ -1217,7 +1217,7 @@ macro_rules! impl_format_value_traits(
|
|||
}
|
||||
}
|
||||
|
||||
impl ops::DerefMut for $name {
|
||||
impl std::ops::DerefMut for $name {
|
||||
fn deref_mut(&mut self) -> &mut $inner_type {
|
||||
&mut self.0
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
322
gstreamer/src/format/signed.rs
Normal file
322
gstreamer/src/format/signed.rs
Normal file
|
@ -0,0 +1,322 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use super::{Format, FormattedValueIntrinsic, FormattedValueNoneBuilder};
|
||||
use crate::utils::Displayable;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// A signed wrapper.
|
||||
///
|
||||
/// This wrapper allows representing a signed value from a type
|
||||
/// which is originaly unsigned. In C APIs, this is represented
|
||||
/// by a tuple with a signed integer positive or negative and
|
||||
/// the absolute value.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Signed<T> {
|
||||
Negative(T),
|
||||
Positive(T),
|
||||
}
|
||||
|
||||
impl<T> Signed<T> {
|
||||
pub fn is_positive(self) -> bool {
|
||||
matches!(self, Signed::Positive(_))
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns `Some(value)`, where `value` is the inner value,
|
||||
/// if `self` is positive.
|
||||
pub fn positive(self) -> Option<T> {
|
||||
match self {
|
||||
Signed::Positive(val) => Some(val),
|
||||
Signed::Negative(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Transforms the `Signed<T>` into a `Result<T, E>`,
|
||||
/// mapping `Positive(v)` to `Ok(v)` and `Negative(_)` to `Err(err)`.
|
||||
pub fn positive_or<E>(self, err: E) -> Result<T, E> {
|
||||
match self {
|
||||
Signed::Positive(val) => Ok(val),
|
||||
Signed::Negative(_) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Transforms the `Signed<T>` into a `Result<T, E>`,
|
||||
/// mapping `Positive(v)` to `Ok(v)` and `Negative(v)` to `Err(err(v))`.
|
||||
pub fn positive_or_else<E, F: FnOnce(T) -> E>(self, err: F) -> Result<T, E> {
|
||||
match self {
|
||||
Signed::Positive(val) => Ok(val),
|
||||
Signed::Negative(val) => Err(err(val)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_negative(self) -> bool {
|
||||
matches!(self, Signed::Negative(_))
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns `Some(value)`, where `value` is the inner value,
|
||||
/// if `self` is negative.
|
||||
pub fn negative(self) -> Option<T> {
|
||||
match self {
|
||||
Signed::Negative(val) => Some(val),
|
||||
Signed::Positive(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Transforms the `Signed<T>` into a `Result<T, E>`,
|
||||
/// mapping `Negative(v)` to `Ok(v)` and `Positive(_)` to `Err(err)`.
|
||||
pub fn negative_or<E>(self, err: E) -> Result<T, E> {
|
||||
match self {
|
||||
Signed::Negative(val) => Ok(val),
|
||||
Signed::Positive(_) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Transforms the `Signed<T>` into a `Result<T, E>`,
|
||||
/// mapping `Negative(v)` to `Ok(v)` and `Positive(_)` to `Err(err(v))`.
|
||||
pub fn negative_or_else<E, F: FnOnce(T) -> E>(self, err: F) -> Result<T, E> {
|
||||
match self {
|
||||
Signed::Negative(val) => Ok(val),
|
||||
Signed::Positive(val) => Err(err(val)),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns the multiplication factor for this `Signed`.
|
||||
///
|
||||
/// Returns:
|
||||
///
|
||||
/// - `1` if the value must be considered as positive.
|
||||
/// - `-1` if the value must be considered as negative.
|
||||
pub fn factor(self) -> i32 {
|
||||
match self {
|
||||
Signed::Positive(_) => 1i32,
|
||||
Signed::Negative(_) => -1i32,
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns the absolute value of `self`.
|
||||
pub fn abs(self) -> T {
|
||||
match self {
|
||||
Signed::Positive(val) | Signed::Negative(val) => val,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Neg for Signed<T> {
|
||||
type Output = Signed<T>;
|
||||
|
||||
fn neg(self) -> Self {
|
||||
match self {
|
||||
Signed::Positive(val) => Signed::Negative(val),
|
||||
Signed::Negative(val) => Signed::Positive(val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Display for Signed<T>
|
||||
where
|
||||
T: fmt::Display + FormattedValueIntrinsic,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use std::fmt::Write;
|
||||
|
||||
let (sign, val) = match self {
|
||||
Signed::Positive(val) => ('+', val),
|
||||
Signed::Negative(val) => ('-', val),
|
||||
};
|
||||
|
||||
f.write_char(sign)?;
|
||||
fmt::Display::fmt(&val, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Displayable for Signed<T>
|
||||
where
|
||||
T: fmt::Display + FormattedValueIntrinsic,
|
||||
{
|
||||
type DisplayImpl = Signed<T>;
|
||||
|
||||
fn display(self) -> Self::DisplayImpl {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Signed<Option<T>> {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Transposes a `Signed` `Option` into an `Option` of a `Signed`.
|
||||
///
|
||||
/// Note that if the inner value was `None`, the sign is lost.
|
||||
pub fn transpose(self) -> Option<Signed<T>> {
|
||||
use Signed::*;
|
||||
|
||||
match self {
|
||||
Positive(Some(val)) => Some(Positive(val)),
|
||||
Negative(Some(val)) => Some(Negative(val)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DisplayableOptionSigned<T>(Option<Signed<T>>);
|
||||
|
||||
impl<T> fmt::Display for DisplayableOptionSigned<T>
|
||||
where
|
||||
T: fmt::Display + FormattedValueIntrinsic,
|
||||
Option<T>: Displayable,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.0 {
|
||||
Some(ref signed) => fmt::Display::fmt(signed, f),
|
||||
None => fmt::Display::fmt(&Option::<T>::None.display(), f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Displayable for Option<Signed<T>>
|
||||
where
|
||||
T: fmt::Display + FormattedValueIntrinsic,
|
||||
Option<T>: Displayable,
|
||||
{
|
||||
type DisplayImpl = DisplayableOptionSigned<T>;
|
||||
|
||||
fn display(self) -> Self::DisplayImpl {
|
||||
DisplayableOptionSigned(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Displayable for Signed<Option<T>>
|
||||
where
|
||||
T: fmt::Display + FormattedValueIntrinsic,
|
||||
Option<T>: Displayable,
|
||||
{
|
||||
type DisplayImpl = DisplayableOptionSigned<T>;
|
||||
|
||||
fn display(self) -> Self::DisplayImpl {
|
||||
DisplayableOptionSigned(self.transpose())
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// A trait implemented on unsigned types which can be converted into [`crate::Signed`]s.
|
||||
pub trait UnsignedIntoSigned: Copy + Sized {
|
||||
type Signed;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Converts `self` into a `Signed` matching the given `sign`.
|
||||
fn into_signed(self, sign: i32) -> Self::Signed {
|
||||
if sign.is_positive() {
|
||||
self.into_positive()
|
||||
} else {
|
||||
self.into_negative()
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Converts `self` into a `Signed::Positive`.
|
||||
fn into_positive(self) -> Self::Signed;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Converts `self` into a `Signed::Negative`.
|
||||
fn into_negative(self) -> Self::Signed;
|
||||
}
|
||||
|
||||
impl_unsigned_int_into_signed!(u64);
|
||||
impl_signed_ops!(u64);
|
||||
impl_signed_div_mul!(u64);
|
||||
|
||||
impl_unsigned_int_into_signed!(usize);
|
||||
impl_signed_ops!(usize);
|
||||
impl_signed_div_mul!(usize);
|
||||
|
||||
impl_unsigned_int_into_signed!(u32);
|
||||
impl_signed_ops!(u32);
|
||||
impl_signed_div_mul!(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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NoneSignedBuilder: FormattedValueNoneBuilder {
|
||||
type Signed;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns the `None` value for `Self` as a `Signed<FullRange>` if such a value can be represented.
|
||||
///
|
||||
/// See details in [`FormattedValueNoneBuilder::none`].
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `Self` is `GenericFormattedValue` in which case, the `Format` must be known.
|
||||
fn none_signed() -> Self::Signed;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns the `None` value for `Self` as a `Signed<FullRange>`, if such a value can be represented.
|
||||
///
|
||||
/// See details in [`FormattedValueNoneBuilder::none_for_format`].
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `None` can't be represented by `Self` for `format` or by the requested
|
||||
/// `GenericFormattedValue` variant.
|
||||
fn none_signed_for_format(format: Format) -> Self::Signed;
|
||||
}
|
||||
|
||||
impl<T> NoneSignedBuilder for T
|
||||
where
|
||||
T: UnsignedIntoSigned + FormattedValueNoneBuilder,
|
||||
{
|
||||
type Signed = <T as UnsignedIntoSigned>::Signed;
|
||||
|
||||
fn none_signed() -> Self::Signed {
|
||||
Self::none().into_positive()
|
||||
}
|
||||
|
||||
fn none_signed_for_format(format: Format) -> Self::Signed {
|
||||
skip_assert_initialized!();
|
||||
Self::none_for_format(format).into_positive()
|
||||
}
|
||||
}
|
263
gstreamer/src/format/specific.rs
Normal file
263
gstreamer/src/format/specific.rs
Normal file
|
@ -0,0 +1,263 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{FromGlib, GlibNoneError, IntoGlib, OptionIntoGlib, TryFromGlib};
|
||||
|
||||
use super::{
|
||||
Format, FormattedValue, FormattedValueError, FormattedValueFullRange, FormattedValueIntrinsic,
|
||||
FormattedValueNoneBuilder, GenericFormattedValue,
|
||||
};
|
||||
|
||||
pub trait SpecificFormattedValue: FormattedValue {}
|
||||
|
||||
pub trait SpecificFormattedValueFullRange: FormattedValueFullRange {}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// A trait implemented on the intrinsic type of a `SpecificFormattedValue`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// - `Undefined` is the intrinsic type for `Undefined`.
|
||||
/// - `Bytes` is the intrinsic type for `Option<Bytes>`.
|
||||
pub trait SpecificFormattedValueIntrinsic: TryFromGlib<i64> + FormattedValueIntrinsic {}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Buffers(pub u64);
|
||||
impl Buffers {
|
||||
#[doc(alias = "GST_BUFFER_OFFSET_NONE")]
|
||||
pub const OFFSET_NONE: u64 = ffi::GST_BUFFER_OFFSET_NONE;
|
||||
pub const MAX: Self = Self(Self::OFFSET_NONE - 1);
|
||||
}
|
||||
|
||||
impl_common_ops_for_newtype_uint!(Buffers, u64);
|
||||
impl_signed_div_mul!(Buffers, u64);
|
||||
impl_format_value_traits!(Buffers, Buffers, Buffers, u64);
|
||||
option_glib_newtype_from_to!(Buffers, Buffers::OFFSET_NONE);
|
||||
glib_newtype_display!(
|
||||
Buffers,
|
||||
DisplayableBuffers,
|
||||
DisplayableOptionBuffers,
|
||||
"buffers"
|
||||
);
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Bytes(pub u64);
|
||||
impl Bytes {
|
||||
pub const MAX: Self = Self(u64::MAX - 1);
|
||||
}
|
||||
|
||||
impl_common_ops_for_newtype_uint!(Bytes, u64);
|
||||
impl_signed_div_mul!(Bytes, u64);
|
||||
impl_format_value_traits!(Bytes, Bytes, Bytes, u64);
|
||||
option_glib_newtype_from_to!(Bytes, u64::MAX);
|
||||
glib_newtype_display!(Bytes, DisplayableBytes, DisplayableOptionBytes, "bytes");
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Default(pub u64);
|
||||
impl Default {
|
||||
pub const MAX: Self = Self(u64::MAX - 1);
|
||||
}
|
||||
|
||||
impl_common_ops_for_newtype_uint!(Default, u64);
|
||||
impl_signed_div_mul!(Default, u64);
|
||||
impl_format_value_traits!(Default, Default, Default, u64);
|
||||
option_glib_newtype_from_to!(Default, u64::MAX);
|
||||
glib_newtype_display!(
|
||||
Default,
|
||||
DisplayableDefault,
|
||||
DisplayableOptionDefault,
|
||||
"(Default)"
|
||||
);
|
||||
|
||||
pub type Time = super::ClockTime;
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Percent(pub u32);
|
||||
impl Percent {
|
||||
#[doc(alias = "GST_FORMAT_PERCENT_MAX")]
|
||||
pub const MAX: Self = Self(ffi::GST_FORMAT_PERCENT_MAX as u32);
|
||||
#[doc(alias = "GST_FORMAT_PERCENT_SCALE")]
|
||||
pub const SCALE: u32 = ffi::GST_FORMAT_PERCENT_SCALE as u32;
|
||||
}
|
||||
|
||||
impl_common_ops_for_newtype_uint!(Percent, u32);
|
||||
impl_signed_div_mul!(Percent, u32);
|
||||
glib_newtype_display!(Percent, DisplayablePercent, DisplayableOptionPercent, "%");
|
||||
|
||||
impl FormattedValue for Option<Percent> {
|
||||
type FullRange = Option<Percent>;
|
||||
|
||||
fn default_format() -> Format {
|
||||
Format::Percent
|
||||
}
|
||||
|
||||
fn format(&self) -> Format {
|
||||
Format::Percent
|
||||
}
|
||||
|
||||
fn is_some(&self) -> bool {
|
||||
Option::is_some(self)
|
||||
}
|
||||
|
||||
unsafe fn into_raw_value(self) -> i64 {
|
||||
self.map_or(-1, |v| v.0 as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedValueFullRange for Option<Percent> {
|
||||
unsafe fn from_raw(format: Format, value: i64) -> Self {
|
||||
debug_assert_eq!(format, Format::Percent);
|
||||
Percent::try_from_glib(value as i64).ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Option<Percent>> for GenericFormattedValue {
|
||||
fn from(v: Option<Percent>) -> Self {
|
||||
skip_assert_initialized!();
|
||||
GenericFormattedValue::Percent(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Percent> for GenericFormattedValue {
|
||||
fn from(v: Percent) -> Self {
|
||||
skip_assert_initialized!();
|
||||
GenericFormattedValue::Percent(Some(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedValue for Percent {
|
||||
type FullRange = Option<Percent>;
|
||||
|
||||
fn default_format() -> Format {
|
||||
Format::Percent
|
||||
}
|
||||
|
||||
fn format(&self) -> Format {
|
||||
Format::Percent
|
||||
}
|
||||
|
||||
fn is_some(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
unsafe fn into_raw_value(self) -> i64 {
|
||||
self.0 as i64
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u64> for Percent {
|
||||
type Error = GlibNoneError;
|
||||
|
||||
fn try_from(v: u64) -> Result<Percent, GlibNoneError> {
|
||||
skip_assert_initialized!();
|
||||
unsafe { Self::try_from_glib(v as i64) }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromGlib<i64> for Percent {
|
||||
type Error = GlibNoneError;
|
||||
#[inline]
|
||||
unsafe fn try_from_glib(value: i64) -> Result<Self, Self::Error> {
|
||||
skip_assert_initialized!();
|
||||
if value < 0 || value > ffi::GST_FORMAT_PERCENT_MAX {
|
||||
Err(GlibNoneError)
|
||||
} else {
|
||||
Ok(Percent(value as u32))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for Percent {
|
||||
type Error = FormattedValueError;
|
||||
|
||||
fn try_from(value: u32) -> Result<Self, Self::Error> {
|
||||
skip_assert_initialized!();
|
||||
if value > ffi::GST_FORMAT_PERCENT_MAX as u32 {
|
||||
Err(FormattedValueError(Format::Percent))
|
||||
} else {
|
||||
Ok(Percent(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<GenericFormattedValue> for Option<Percent> {
|
||||
type Error = FormattedValueError;
|
||||
|
||||
fn try_from(v: GenericFormattedValue) -> Result<Option<Percent>, Self::Error> {
|
||||
skip_assert_initialized!();
|
||||
if let GenericFormattedValue::Percent(v) = v {
|
||||
Ok(v)
|
||||
} else {
|
||||
Err(FormattedValueError(v.format()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedValueIntrinsic for Percent {}
|
||||
impl SpecificFormattedValue for Option<Percent> {}
|
||||
impl SpecificFormattedValueFullRange for Option<Percent> {}
|
||||
impl SpecificFormattedValueIntrinsic for Percent {}
|
||||
impl FormattedValueNoneBuilder for Option<Percent> {
|
||||
fn none() -> Option<Percent> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Percent {
|
||||
type Target = u32;
|
||||
|
||||
fn deref(&self) -> &u32 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for Percent {
|
||||
fn deref_mut(&mut self) -> &mut u32 {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<u32> for Percent {
|
||||
fn as_ref(&self) -> &u32 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<u32> for Percent {
|
||||
fn as_mut(&mut self) -> &mut u32 {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
|
||||
#[error("value out of range")]
|
||||
pub struct TryPercentFromFloatError(());
|
||||
|
||||
impl TryFrom<f64> for Percent {
|
||||
type Error = TryPercentFromFloatError;
|
||||
|
||||
fn try_from(v: f64) -> Result<Self, Self::Error> {
|
||||
skip_assert_initialized!();
|
||||
if v < 0.0 || v > 1.0 {
|
||||
Err(TryPercentFromFloatError(()))
|
||||
} else {
|
||||
Ok(Percent(
|
||||
(v * ffi::GST_FORMAT_PERCENT_SCALE as f64).round() as u32
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<f32> for Percent {
|
||||
type Error = TryPercentFromFloatError;
|
||||
|
||||
fn try_from(v: f32) -> Result<Self, Self::Error> {
|
||||
skip_assert_initialized!();
|
||||
if v < 0.0 || v > 1.0 {
|
||||
Err(TryPercentFromFloatError(()))
|
||||
} else {
|
||||
Ok(Percent(
|
||||
(v * ffi::GST_FORMAT_PERCENT_SCALE as f32).round() as u32
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
111
gstreamer/src/format/undefined.rs
Normal file
111
gstreamer/src/format/undefined.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::TryFromGlib;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use super::{FormattedValue, FormattedValueFullRange, FormattedValueIntrinsic};
|
||||
use super::{FormattedValueError, GenericFormattedValue, Signed};
|
||||
use crate::Format;
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Undefined(pub i64);
|
||||
|
||||
impl FormattedValue for Undefined {
|
||||
type FullRange = Undefined;
|
||||
|
||||
fn default_format() -> Format {
|
||||
Format::Undefined
|
||||
}
|
||||
|
||||
fn format(&self) -> Format {
|
||||
Format::Undefined
|
||||
}
|
||||
|
||||
fn is_some(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
unsafe fn into_raw_value(self) -> i64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedValueFullRange for Undefined {
|
||||
unsafe fn from_raw(format: Format, value: i64) -> Self {
|
||||
debug_assert_eq!(format, Format::Undefined);
|
||||
Undefined(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Undefined> for GenericFormattedValue {
|
||||
fn from(v: Undefined) -> Self {
|
||||
skip_assert_initialized!();
|
||||
GenericFormattedValue::Undefined(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<GenericFormattedValue> for Undefined {
|
||||
type Error = FormattedValueError;
|
||||
|
||||
fn try_from(v: GenericFormattedValue) -> Result<Undefined, Self::Error> {
|
||||
skip_assert_initialized!();
|
||||
if let GenericFormattedValue::Undefined(v) = v {
|
||||
Ok(v)
|
||||
} else {
|
||||
Err(FormattedValueError(v.format()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedValueIntrinsic for Undefined {}
|
||||
|
||||
impl TryFromGlib<i64> for Undefined {
|
||||
type Error = std::convert::Infallible;
|
||||
#[inline]
|
||||
unsafe fn try_from_glib(v: i64) -> Result<Self, Self::Error> {
|
||||
skip_assert_initialized!();
|
||||
Ok(Undefined(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for Undefined {
|
||||
fn from(v: i64) -> Self {
|
||||
skip_assert_initialized!();
|
||||
Undefined(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Undefined {
|
||||
type Target = i64;
|
||||
|
||||
fn deref(&self) -> &i64 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Undefined {
|
||||
fn deref_mut(&mut self) -> &mut i64 {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<i64> for Undefined {
|
||||
fn as_ref(&self) -> &i64 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<i64> for Undefined {
|
||||
fn as_mut(&mut self) -> &mut i64 {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Undefined> for Signed<u64> {
|
||||
fn from(val: Undefined) -> Signed<u64> {
|
||||
skip_assert_initialized!();
|
||||
val.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
glib_newtype_display!(Undefined, DisplayableUndefined, "(Undefined)");
|
Loading…
Reference in a new issue