forked from mirrors/gstreamer-rs
format/Other: use u64 internally instead of i64
This commit is contained in:
parent
8a7813d04c
commit
04b6710f84
7 changed files with 293 additions and 144 deletions
|
@ -3,31 +3,45 @@
|
|||
use serde::de::{Deserialize, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
|
||||
use crate::format::{Buffers, Bytes, Default, Percent, Undefined};
|
||||
use crate::format::{Buffers, Bytes, Default, Other, Percent, Undefined};
|
||||
|
||||
// FIXME: the ser/de impl assumed `GenericFormattedValue` was always used.
|
||||
// When serializing a `SpecificFormattedValue`, we loose the type and only
|
||||
// serialize the inner value in parenthesis.
|
||||
// Manual implementation for some types that would otherwise yield representations such as:
|
||||
// "Default((Some(42)))"
|
||||
// "Default(Some((42)))"
|
||||
macro_rules! impl_serde(
|
||||
($t:ident) => {
|
||||
($t:ident, $inner:ty) => {
|
||||
impl Serialize for $t {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
self.0.serialize(serializer)
|
||||
use std::ops::Deref;
|
||||
self.deref().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'de> Deserialize<'de> for $t {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
skip_assert_initialized!();
|
||||
u64::deserialize(deserializer).map($t)
|
||||
<$inner>::deserialize(deserializer)
|
||||
.and_then(|value| {
|
||||
$t::try_from(value).map_err(|_| {
|
||||
use serde::de::{Error, Unexpected};
|
||||
D::Error::invalid_value(
|
||||
Unexpected::Unsigned(value.into()),
|
||||
&concat!("valid ", stringify!($t)),
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
impl_serde!(Buffers);
|
||||
impl_serde!(Bytes);
|
||||
impl_serde!(Default);
|
||||
impl_serde!(Buffers, u64);
|
||||
impl_serde!(Bytes, u64);
|
||||
impl_serde!(Default, u64);
|
||||
impl_serde!(Other, u64);
|
||||
impl_serde!(Percent, u32);
|
||||
|
||||
impl Serialize for Undefined {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
|
@ -42,22 +56,9 @@ impl<'de> Deserialize<'de> for Undefined {
|
|||
}
|
||||
}
|
||||
|
||||
impl Serialize for Percent {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
self.0.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Percent {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
skip_assert_initialized!();
|
||||
u32::deserialize(deserializer).map(Percent)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::format::{Buffers, Bytes, Default, Percent, Undefined};
|
||||
use crate::format::{Buffers, Bytes, Default, Other, Percent, Undefined};
|
||||
use crate::ClockTime;
|
||||
use crate::Format;
|
||||
use crate::GenericFormattedValue;
|
||||
|
@ -110,15 +111,15 @@ mod tests {
|
|||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Percent\":4200}".to_owned(), res);
|
||||
|
||||
let value = GenericFormattedValue::Other(Format::Percent, 42);
|
||||
let value = GenericFormattedValue::Other(Format::Percent, Other::try_from(42).ok());
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config.clone());
|
||||
assert_eq!(Ok("Other(Percent, 42)".to_owned()), res);
|
||||
assert_eq!(Ok("Other(Percent, Some(42))".to_owned()), res);
|
||||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Other\":[\"Percent\",42]}".to_owned(), res);
|
||||
|
||||
let value = GenericFormattedValue::Other(Format::__Unknown(7), 42);
|
||||
let value = GenericFormattedValue::new(Format::__Unknown(7), 42);
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config);
|
||||
assert_eq!(Ok("Other(__Unknown(7), 42)".to_owned()), res);
|
||||
assert_eq!(Ok("Other(__Unknown(7), Some(42))".to_owned()), res);
|
||||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Other\":[{\"__Unknown\":7},42]}".to_owned(), res);
|
||||
}
|
||||
|
@ -135,13 +136,15 @@ mod tests {
|
|||
let value_de: GenericFormattedValue = serde_json::from_str(value_json).unwrap();
|
||||
assert_eq!(value_de, GenericFormattedValue::from(Default(42)));
|
||||
|
||||
let value_ron = "Other(Percent, 42)";
|
||||
let value_ron = "Other(Percent, Some(42))";
|
||||
let gfv_value = GenericFormattedValue::Other(Format::Percent, Other::try_from(42).ok());
|
||||
|
||||
let value_de: GenericFormattedValue = ron::de::from_str(value_ron).unwrap();
|
||||
assert_eq!(value_de, GenericFormattedValue::Other(Format::Percent, 42));
|
||||
assert_eq!(value_de, gfv_value);
|
||||
|
||||
let value_json = "{\"Other\":[\"Percent\",42]}";
|
||||
let value_de: GenericFormattedValue = serde_json::from_str(value_json).unwrap();
|
||||
assert_eq!(value_de, GenericFormattedValue::Other(Format::Percent, 42));
|
||||
assert_eq!(value_de, gfv_value);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -166,7 +169,8 @@ mod tests {
|
|||
test_roundrip!(GenericFormattedValue::from(
|
||||
Percent::try_from(0.42).unwrap()
|
||||
));
|
||||
test_roundrip!(GenericFormattedValue::Other(Format::Percent, 42));
|
||||
test_roundrip!(GenericFormattedValue::Other(Format::__Unknown(7), 42));
|
||||
let gfv_value = GenericFormattedValue::Other(Format::Percent, Other::try_from(42).ok());
|
||||
test_roundrip!(gfv_value);
|
||||
test_roundrip!(GenericFormattedValue::new(Format::__Unknown(7), 42));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::FromGlib;
|
||||
use glib::translate::{FromGlib, GlibNoneError, IntoGlib, OptionIntoGlib, TryFromGlib};
|
||||
use std::fmt;
|
||||
|
||||
use crate::utils::Displayable;
|
||||
|
@ -10,9 +10,37 @@ use super::{
|
|||
};
|
||||
use super::{
|
||||
CompatibleFormattedValue, FormattedValue, FormattedValueFullRange, FormattedValueIntrinsic,
|
||||
FormattedValueNoneBuilder, UnsignedIntoSigned,
|
||||
FormattedValueNoneBuilder, SignedIntrinsic, UnsignedIntoSigned,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Other(u64);
|
||||
impl Other {
|
||||
pub const MAX: Self = Self(u64::MAX - 1);
|
||||
}
|
||||
|
||||
impl_common_ops_for_newtype_uint!(Other, u64);
|
||||
impl_signed_div_mul!(Other, u64);
|
||||
option_glib_newtype_from_to!(Other, u64::MAX);
|
||||
glib_newtype_display!(Other, DisplayableOther, DisplayableOptionOther);
|
||||
|
||||
impl TryFrom<u64> for Other {
|
||||
type Error = GlibNoneError;
|
||||
fn try_from(val: u64) -> Result<Self, GlibNoneError> {
|
||||
skip_assert_initialized!();
|
||||
unsafe { Self::try_from_glib(val) }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromGlib<i64> for Other {
|
||||
type Error = GlibNoneError;
|
||||
#[inline]
|
||||
unsafe fn try_from_glib(val: i64) -> Result<Self, GlibNoneError> {
|
||||
skip_assert_initialized!();
|
||||
Self::try_from_glib(val as u64)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum GenericFormattedValue {
|
||||
|
@ -22,7 +50,7 @@ pub enum GenericFormattedValue {
|
|||
Time(Option<ClockTime>),
|
||||
Buffers(Option<Buffers>),
|
||||
Percent(Option<Percent>),
|
||||
Other(Format, i64),
|
||||
Other(Format, Option<Other>),
|
||||
}
|
||||
|
||||
impl fmt::Display for GenericFormattedValue {
|
||||
|
@ -34,24 +62,33 @@ impl fmt::Display for GenericFormattedValue {
|
|||
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),
|
||||
Self::Other(format, val) => {
|
||||
val.display().fmt(f)?;
|
||||
fmt::Write::write_char(f, ' ')?;
|
||||
fmt::Display::fmt(&format, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Displayable for GenericFormattedValue {
|
||||
type DisplayImpl = GenericFormattedValue;
|
||||
fn display(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
Format::Default => Self::Default(unsafe { FromGlib::from_glib(value) }),
|
||||
Format::Bytes => Self::Bytes(unsafe { FromGlib::from_glib(value) }),
|
||||
Format::Time => Self::Time(unsafe { FromGlib::from_glib(value) }),
|
||||
Format::Buffers => Self::Buffers(unsafe { FromGlib::from_glib(value) }),
|
||||
Format::Percent => Self::Percent(unsafe { FromGlib::from_glib(value) }),
|
||||
Format::__Unknown(_) => Self::Other(format, unsafe { FromGlib::from_glib(value) }),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +115,7 @@ impl GenericFormattedValue {
|
|||
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,
|
||||
Self::Other(_, v) => v.into_glib() as i64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +143,7 @@ impl FormattedValue for GenericFormattedValue {
|
|||
Self::Time(v) => v.is_some(),
|
||||
Self::Buffers(v) => v.is_some(),
|
||||
Self::Percent(v) => v.is_some(),
|
||||
Self::Other(..) => true,
|
||||
Self::Other(_, v) => v.is_some(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,6 +159,7 @@ impl FormattedValueFullRange for GenericFormattedValue {
|
|||
}
|
||||
|
||||
impl FormattedValueIntrinsic for GenericFormattedValue {}
|
||||
impl SignedIntrinsic for GenericFormattedValue {}
|
||||
|
||||
impl FormattedValueNoneBuilder for GenericFormattedValue {
|
||||
#[track_caller]
|
||||
|
@ -142,7 +180,7 @@ impl FormattedValueNoneBuilder for GenericFormattedValue {
|
|||
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`"),
|
||||
unknown => Self::Other(unknown, Other::NONE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,27 +189,21 @@ impl UnsignedIntoSigned for GenericFormattedValue {
|
|||
type Signed = Signed<GenericFormattedValue>;
|
||||
|
||||
#[track_caller]
|
||||
fn into_positive(self) -> Signed<GenericFormattedValue> {
|
||||
fn into_positive(self) -> Self::Signed {
|
||||
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> {
|
||||
fn into_negative(self) -> Self::Signed {
|
||||
match self {
|
||||
GenericFormattedValue::Undefined(_) => {
|
||||
unimplemented!("`GenericFormattedValue::Undefined` is already signed")
|
||||
}
|
||||
GenericFormattedValue::Other(..) => {
|
||||
unimplemented!("`GenericFormattedValue::Other` is already signed")
|
||||
}
|
||||
unsigned_inner => Signed::Negative(unsigned_inner),
|
||||
}
|
||||
}
|
||||
|
@ -200,3 +232,56 @@ impl CompatibleFormattedValue<GenericFormattedValue> for GenericFormattedValue {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::eq_op, clippy::op_ref)]
|
||||
fn other() {
|
||||
// Check a few ops on `Other`, better converage for
|
||||
// the macro ops impl ensured as part of the `clock_time` module.
|
||||
|
||||
use opt_ops::prelude::*;
|
||||
|
||||
let other_none: Option<Other> = Other::try_from(u64::MAX).ok();
|
||||
assert!(other_none.is_none());
|
||||
|
||||
let other_10 = Other::try_from(10).unwrap();
|
||||
let other_20 = Other::try_from(20).unwrap();
|
||||
let other_30 = Other::try_from(30).unwrap();
|
||||
|
||||
assert_eq!(other_10 + other_20, other_30);
|
||||
assert_eq!(other_30 - other_20, other_10);
|
||||
|
||||
assert!(other_10 < Other::MAX);
|
||||
|
||||
assert_eq!(Some(other_10).opt_add(other_20), Some(other_30));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::eq_op, clippy::op_ref)]
|
||||
fn generic_other() {
|
||||
let gen_other_42: GenericFormattedValue =
|
||||
GenericFormattedValue::new(Format::__Unknown(128), 42);
|
||||
assert_eq!(
|
||||
gen_other_42,
|
||||
GenericFormattedValue::Other(Format::__Unknown(128), Some(Other(42)))
|
||||
);
|
||||
assert_eq!(gen_other_42.format(), Format::__Unknown(128));
|
||||
assert_eq!(gen_other_42.value(), 42);
|
||||
assert!(gen_other_42.is_some());
|
||||
|
||||
let other_none: Option<Other> = Other::NONE;
|
||||
assert!(other_none.is_none());
|
||||
|
||||
let gen_other_none: GenericFormattedValue =
|
||||
GenericFormattedValue::none_for_format(Format::__Unknown(128));
|
||||
assert!(gen_other_none.is_none());
|
||||
assert_eq!(
|
||||
gen_other_none,
|
||||
GenericFormattedValue::Other(Format::__Unknown(128), None)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,6 +183,8 @@ macro_rules! impl_non_trait_op_inner_type(
|
|||
|
||||
macro_rules! impl_unsigned_int_into_signed(
|
||||
($typ:ty) => {
|
||||
impl crate::format::SignedIntrinsic for $typ {}
|
||||
|
||||
impl crate::UnsignedIntoSigned for $typ {
|
||||
type Signed = crate::Signed<$typ>;
|
||||
|
||||
|
@ -239,6 +241,20 @@ macro_rules! impl_common_ops_for_newtype_uint(
|
|||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for $typ {
|
||||
type Target = $inner;
|
||||
|
||||
fn deref(&self) -> &$inner {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<$inner> for $typ {
|
||||
fn as_ref(&self) -> &$inner {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl_trait_op_same!($typ, Add, add, AddAssign, add_assign);
|
||||
impl_trait_op_same!($typ, Sub, sub, SubAssign, sub_assign);
|
||||
impl std::ops::Div for $typ {
|
||||
|
@ -1467,7 +1483,7 @@ macro_rules! impl_format_value_traits(
|
|||
|
||||
impl TryFrom<$inner> for $typ {
|
||||
type Error = GlibNoneError;
|
||||
fn try_from(v: $inner) -> Result<$typ, GlibNoneError> {
|
||||
fn try_from(v: $inner) -> Result<Self, GlibNoneError> {
|
||||
skip_assert_initialized!();
|
||||
unsafe { Self::try_from_glib(v as i64) }
|
||||
}
|
||||
|
@ -1481,32 +1497,6 @@ macro_rules! impl_format_value_traits(
|
|||
<$typ as TryFromGlib<u64>>::try_from_glib(val as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for $typ {
|
||||
type Target = $inner;
|
||||
|
||||
fn deref(&self) -> &$inner {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for $typ {
|
||||
fn deref_mut(&mut self) -> &mut $inner {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<$inner> for $typ {
|
||||
fn as_ref(&self) -> &$inner {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<$inner> for $typ {
|
||||
fn as_mut(&mut self) -> &mut $inner {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
|
@ -1545,16 +1535,12 @@ macro_rules! option_glib_newtype_from_to {
|
|||
// `$displayable_option_name` if `concat_idents!` was stable.
|
||||
// See: https://doc.rust-lang.org/std/macro.concat_idents.html
|
||||
macro_rules! glib_newtype_display {
|
||||
($typ:ty, $displayable_name:ident, $unit:expr) => {
|
||||
($typ:ty, $displayable_name:ident) => {
|
||||
pub struct $displayable_name($typ);
|
||||
|
||||
impl std::fmt::Display for $typ {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
use std::fmt::Write;
|
||||
|
||||
std::fmt::Display::fmt(&self.0, f)?;
|
||||
f.write_char(' ')?;
|
||||
f.write_str($unit)
|
||||
std::fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1566,8 +1552,50 @@ macro_rules! glib_newtype_display {
|
|||
}
|
||||
};
|
||||
|
||||
($typ:ty, $displayable_name:ident, $displayable_option_name:ident, $unit:expr) => {
|
||||
glib_newtype_display!($typ, $displayable_name, $unit);
|
||||
($typ:ty, $displayable_name:ident, Format::$format:ident$(,)?) => {
|
||||
pub struct $displayable_name($typ);
|
||||
|
||||
impl std::fmt::Display for $typ {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, f)?;
|
||||
std::fmt::Write::write_char(f, ' ')?;
|
||||
std::fmt::Display::fmt(&Format::$format, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::utils::Displayable for $typ {
|
||||
type DisplayImpl = $typ;
|
||||
fn display(self) -> $typ {
|
||||
self
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
($typ:ty, $displayable_name:ident, $displayable_option_name:ident) => {
|
||||
glib_newtype_display!($typ, $displayable_name);
|
||||
|
||||
pub struct $displayable_option_name(Option<$typ>);
|
||||
|
||||
impl std::fmt::Display for $displayable_option_name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
if let Some(val) = self.0.as_ref() {
|
||||
std::fmt::Display::fmt(val, f)
|
||||
} else {
|
||||
f.write_str("undef.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::utils::Displayable for Option<$typ> {
|
||||
type DisplayImpl = $displayable_option_name;
|
||||
fn display(self) -> Self::DisplayImpl {
|
||||
$displayable_option_name(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
($typ:ty, $displayable_name:ident, $displayable_option_name:ident, Format::$format:ident$(,)?) => {
|
||||
glib_newtype_display!($typ, $displayable_name, Format::$format);
|
||||
|
||||
pub struct $displayable_option_name(Option<$typ>);
|
||||
|
||||
|
@ -1577,7 +1605,7 @@ macro_rules! glib_newtype_display {
|
|||
std::fmt::Display::fmt(val, f)
|
||||
} else {
|
||||
f.write_str("undef. ")?;
|
||||
f.write_str($unit)
|
||||
std::fmt::Display::fmt(&Format::$format, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -522,6 +522,21 @@ pub trait FormattedValueNoneBuilder: FormattedValueFullRange {
|
|||
}
|
||||
}
|
||||
|
||||
use std::fmt;
|
||||
impl fmt::Display for Format {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::Undefined => f.write_str("undefined"),
|
||||
Self::Default => f.write_str("default"),
|
||||
Self::Bytes => f.write_str("bytes"),
|
||||
Self::Time => f.write_str("time"),
|
||||
Self::Buffers => f.write_str("buffers"),
|
||||
Self::Percent => f.write_str("%"),
|
||||
Self::__Unknown(format) => write!(f, "(format: {})", format),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -715,6 +730,7 @@ mod tests {
|
|||
assert_eq!(signed.positive(), Some(ct_1));
|
||||
assert!(!signed.is_negative());
|
||||
assert!(signed.negative().is_none());
|
||||
assert_eq!(signed.signum(), 1);
|
||||
|
||||
let signed = ct_1.into_negative();
|
||||
assert_eq!(signed, Signed::Negative(ct_1));
|
||||
|
@ -722,6 +738,7 @@ mod tests {
|
|||
assert_eq!(signed.negative(), Some(ct_1));
|
||||
assert!(!signed.is_positive());
|
||||
assert!(signed.positive().is_none());
|
||||
assert_eq!(signed.signum(), -1);
|
||||
|
||||
let def = Default(1);
|
||||
|
||||
|
@ -731,6 +748,7 @@ mod tests {
|
|||
assert_eq!(signed.positive(), Some(def));
|
||||
assert!(!signed.is_negative());
|
||||
assert!(signed.negative().is_none());
|
||||
assert_eq!(signed.signum(), 1);
|
||||
|
||||
let signed = def.into_negative();
|
||||
assert_eq!(signed, Signed::Negative(def));
|
||||
|
@ -738,6 +756,17 @@ mod tests {
|
|||
assert_eq!(signed.negative(), Some(def));
|
||||
assert!(!signed.is_positive());
|
||||
assert!(signed.positive().is_none());
|
||||
assert_eq!(signed.signum(), -1);
|
||||
|
||||
let ct_zero = ClockTime::ZERO;
|
||||
let p_ct_zero = ct_zero.into_positive();
|
||||
assert!(p_ct_zero.is_positive());
|
||||
assert!(!p_ct_zero.is_negative());
|
||||
assert_eq!(p_ct_zero.signum(), 0);
|
||||
let n_ct_zero = ct_zero.into_negative();
|
||||
assert!(n_ct_zero.is_negative());
|
||||
assert!(!n_ct_zero.is_positive());
|
||||
assert_eq!(n_ct_zero.signum(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -811,6 +840,20 @@ mod tests {
|
|||
&format!("{}", GenericFormattedValue::Percent(None)),
|
||||
"undef. %"
|
||||
);
|
||||
|
||||
let other: Other = 42.try_into().unwrap();
|
||||
assert_eq!(&format!("{other}"), "42");
|
||||
|
||||
let g_other = GenericFormattedValue::new(Format::__Unknown(128), 42);
|
||||
assert_eq!(&format!("{g_other}"), "42 (format: 128)");
|
||||
assert_eq!(&format!("{}", g_other.display()), "42 (format: 128)");
|
||||
|
||||
let g_other_none = GenericFormattedValue::Other(Format::__Unknown(128), None);
|
||||
assert_eq!(&format!("{g_other_none}"), "undef. (format: 128)");
|
||||
assert_eq!(
|
||||
&format!("{}", g_other_none.display()),
|
||||
"undef. (format: 128)"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -842,5 +885,21 @@ mod tests {
|
|||
|
||||
let none_s_bytes = Option::<Signed<Bytes>>::None;
|
||||
assert_eq!(&format!("{}", none_s_bytes.display()), "undef. bytes");
|
||||
|
||||
let ct_1 = 45_834_908_569_837 * ClockTime::NSECOND;
|
||||
assert_eq!(&format!("{ct_1}"), "12:43:54.908569837");
|
||||
assert_eq!(&format!("{}", ct_1.display()), "12:43:54.908569837");
|
||||
|
||||
let g_ct_1 = GenericFormattedValue::Time(Some(ct_1));
|
||||
assert_eq!(&format!("{g_ct_1}"), "12:43:54.908569837");
|
||||
assert_eq!(&format!("{}", g_ct_1.display()), "12:43:54.908569837");
|
||||
|
||||
let p_g_ct1 = g_ct_1.into_positive();
|
||||
assert_eq!(&format!("{p_g_ct1}"), "+12:43:54.908569837");
|
||||
assert_eq!(&format!("{}", p_g_ct1.display()), "+12:43:54.908569837");
|
||||
|
||||
let n_g_ct1 = g_ct_1.into_negative();
|
||||
assert_eq!(&format!("{n_g_ct1}"), "-12:43:54.908569837");
|
||||
assert_eq!(&format!("{}", n_g_ct1.display()), "-12:43:54.908569837");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::fmt;
|
||||
|
||||
use super::{Format, FormattedValueIntrinsic, FormattedValueNoneBuilder};
|
||||
use super::{Format, FormattedValueNoneBuilder};
|
||||
use crate::utils::Displayable;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
|
@ -12,7 +12,8 @@ use crate::utils::Displayable;
|
|||
/// 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)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum Signed<T> {
|
||||
Negative(T),
|
||||
Positive(T),
|
||||
|
@ -87,20 +88,6 @@ impl<T> Signed<T> {
|
|||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
@ -121,9 +108,11 @@ impl<T> std::ops::Neg for Signed<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait SignedIntrinsic {}
|
||||
|
||||
impl<T> fmt::Display for Signed<T>
|
||||
where
|
||||
T: fmt::Display + FormattedValueIntrinsic,
|
||||
T: fmt::Display + SignedIntrinsic,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use std::fmt::Write;
|
||||
|
@ -140,7 +129,7 @@ where
|
|||
|
||||
impl<T> Displayable for Signed<T>
|
||||
where
|
||||
T: fmt::Display + FormattedValueIntrinsic,
|
||||
T: fmt::Display + SignedIntrinsic,
|
||||
{
|
||||
type DisplayImpl = Signed<T>;
|
||||
|
||||
|
@ -169,7 +158,7 @@ pub struct DisplayableOptionSigned<T>(Option<Signed<T>>);
|
|||
|
||||
impl<T> fmt::Display for DisplayableOptionSigned<T>
|
||||
where
|
||||
T: fmt::Display + FormattedValueIntrinsic,
|
||||
T: fmt::Display + SignedIntrinsic,
|
||||
Option<T>: Displayable,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -182,7 +171,7 @@ where
|
|||
|
||||
impl<T> Displayable for Option<Signed<T>>
|
||||
where
|
||||
T: fmt::Display + FormattedValueIntrinsic,
|
||||
T: fmt::Display + SignedIntrinsic,
|
||||
Option<T>: Displayable,
|
||||
{
|
||||
type DisplayImpl = DisplayableOptionSigned<T>;
|
||||
|
@ -194,7 +183,7 @@ where
|
|||
|
||||
impl<T> Displayable for Signed<Option<T>>
|
||||
where
|
||||
T: fmt::Display + FormattedValueIntrinsic,
|
||||
T: fmt::Display + SignedIntrinsic,
|
||||
Option<T>: Displayable,
|
||||
{
|
||||
type DisplayImpl = DisplayableOptionSigned<T>;
|
||||
|
|
|
@ -36,7 +36,7 @@ glib_newtype_display!(
|
|||
Buffers,
|
||||
DisplayableBuffers,
|
||||
DisplayableOptionBuffers,
|
||||
"buffers"
|
||||
Format::Buffers,
|
||||
);
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
|
@ -49,7 +49,12 @@ 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");
|
||||
glib_newtype_display!(
|
||||
Bytes,
|
||||
DisplayableBytes,
|
||||
DisplayableOptionBytes,
|
||||
Format::Bytes,
|
||||
);
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Default(pub u64);
|
||||
|
@ -65,7 +70,7 @@ glib_newtype_display!(
|
|||
Default,
|
||||
DisplayableDefault,
|
||||
DisplayableOptionDefault,
|
||||
"(Default)"
|
||||
Format::Default,
|
||||
);
|
||||
|
||||
pub type Time = super::ClockTime;
|
||||
|
@ -81,7 +86,12 @@ impl Percent {
|
|||
|
||||
impl_common_ops_for_newtype_uint!(Percent, u32);
|
||||
impl_signed_div_mul!(Percent, u32);
|
||||
glib_newtype_display!(Percent, DisplayablePercent, DisplayableOptionPercent, "%");
|
||||
glib_newtype_display!(
|
||||
Percent,
|
||||
DisplayablePercent,
|
||||
DisplayableOptionPercent,
|
||||
Format::Percent,
|
||||
);
|
||||
|
||||
impl FormattedValue for Option<Percent> {
|
||||
type FullRange = Option<Percent>;
|
||||
|
@ -202,32 +212,6 @@ impl FormattedValueNoneBuilder for Option<Percent> {
|
|||
}
|
||||
}
|
||||
|
||||
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(());
|
||||
|
|
|
@ -108,4 +108,4 @@ impl From<Undefined> for Signed<u64> {
|
|||
}
|
||||
}
|
||||
|
||||
glib_newtype_display!(Undefined, DisplayableUndefined, "(Undefined)");
|
||||
glib_newtype_display!(Undefined, DisplayableUndefined, Format::Undefined);
|
||||
|
|
Loading…
Reference in a new issue