forked from mirrors/gstreamer-rs
gst/format: introduce Constructor traits
Introduce a set of Constructor traits which are implemented on integer of float depending on the formatted values. This traits allows building formatted values using expressions such as: ```rust let buffer_nb = 20.buffers(); let size = 42.k_bytes(); let duration = 15.minutes() + 30.seconds(); let quantity = 42.default_format(); let progress = 20.percent(); let progress = 0.2.percent_ratio(); ```
This commit is contained in:
parent
f5a902ba49
commit
384783b242
8 changed files with 327 additions and 97 deletions
|
@ -290,12 +290,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_add_get_audio_clipping_meta() {
|
||||
use gst::prelude::*;
|
||||
|
||||
gst::init().unwrap();
|
||||
|
||||
let mut buffer = gst::Buffer::with_size(1024).unwrap();
|
||||
|
||||
let start = gst::format::Default::from_u64(1);
|
||||
let stop = gst::format::Default::from_u64(2);
|
||||
let start = 1.default_format();
|
||||
let stop = 2.default_format();
|
||||
|
||||
{
|
||||
let cmeta = AudioClippingMeta::add(buffer.get_mut().unwrap(), start, stop);
|
||||
|
|
|
@ -199,6 +199,66 @@ impl Signed<ClockTime> {
|
|||
impl_format_value_traits!(ClockTime, Time, Time, u64);
|
||||
option_glib_newtype_from_to!(ClockTime, ffi::GST_CLOCK_TIME_NONE);
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// `ClockTime` formatted value constructor trait.
|
||||
pub trait TimeFormatConstructor {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `ClockTime` formatted value from `self` interpreted as nano seconds.
|
||||
fn nseconds(self) -> ClockTime;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `ClockTime` formatted value from `self` interpreted as micro seconds.
|
||||
fn useconds(self) -> ClockTime;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `ClockTime` formatted value from `self` interpreted as milli seconds.
|
||||
fn mseconds(self) -> ClockTime;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `ClockTime` formatted value from `self` interpreted as seconds.
|
||||
fn seconds(self) -> ClockTime;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `ClockTime` formatted value from `self` interpreted as minutes.
|
||||
fn minutes(self) -> ClockTime;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `ClockTime` formatted value from `self` interpreted as hours.
|
||||
fn hours(self) -> ClockTime;
|
||||
}
|
||||
|
||||
impl TimeFormatConstructor for u64 {
|
||||
#[track_caller]
|
||||
fn nseconds(self) -> ClockTime {
|
||||
ClockTime::from_nseconds(self)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn useconds(self) -> ClockTime {
|
||||
ClockTime::from_useconds(self)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn mseconds(self) -> ClockTime {
|
||||
ClockTime::from_mseconds(self)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn seconds(self) -> ClockTime {
|
||||
ClockTime::from_seconds(self)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn minutes(self) -> ClockTime {
|
||||
ClockTime::from_seconds(self * 60)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn hours(self) -> ClockTime {
|
||||
ClockTime::from_seconds(self * 60 * 60)
|
||||
}
|
||||
}
|
||||
|
||||
impl glib::value::ValueType for ClockTime {
|
||||
type Type = Self;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,8 @@ impl<'de> Deserialize<'de> for Undefined {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::format::{Buffers, Bytes, Default, Other, Percent, Undefined};
|
||||
use crate::format::prelude::*;
|
||||
use crate::format::{Default, Other, Undefined};
|
||||
use crate::ClockTime;
|
||||
use crate::Format;
|
||||
use crate::GenericFormattedValue;
|
||||
|
@ -74,19 +75,19 @@ mod tests {
|
|||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Undefined\":42}".to_owned(), res);
|
||||
|
||||
let value = GenericFormattedValue::from(Default::from_u64(42));
|
||||
let value = GenericFormattedValue::from(42.default_format());
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config.clone());
|
||||
assert_eq!(Ok("Default(Some(42))".to_owned()), res);
|
||||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Default\":42}".to_owned(), res);
|
||||
|
||||
let value = GenericFormattedValue::from(Option::<Default>::None);
|
||||
let value = GenericFormattedValue::from(Default::NONE);
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config.clone());
|
||||
assert_eq!(Ok("Default(None)".to_owned()), res);
|
||||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Default\":null}".to_owned(), res);
|
||||
|
||||
let value = GenericFormattedValue::from(Bytes::from_usize(42));
|
||||
let value = GenericFormattedValue::from(42.bytes());
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config.clone());
|
||||
assert_eq!(Ok("Bytes(Some(42))".to_owned()), res);
|
||||
let res = serde_json::to_string(&value).unwrap();
|
||||
|
@ -98,13 +99,13 @@ mod tests {
|
|||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Time\":42123456789}".to_owned(), res);
|
||||
|
||||
let value = GenericFormattedValue::from(Buffers::from_u64(42));
|
||||
let value = GenericFormattedValue::from(42.buffers());
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config.clone());
|
||||
assert_eq!(Ok("Buffers(Some(42))".to_owned()), res);
|
||||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Buffers\":42}".to_owned(), res);
|
||||
|
||||
let percent = Percent::from_ratio(0.42);
|
||||
let percent = 0.42.percent_ratio();
|
||||
let value = GenericFormattedValue::from(percent);
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config.clone());
|
||||
assert_eq!(Ok("Percent(Some(420000))".to_owned()), res);
|
||||
|
@ -129,7 +130,7 @@ mod tests {
|
|||
fn test_deserialize() {
|
||||
let value_ron = "Default(Some(42))";
|
||||
let value_de: GenericFormattedValue = ron::de::from_str(value_ron).unwrap();
|
||||
assert_eq!(value_de, GenericFormattedValue::from(Default::from_u64(42)));
|
||||
assert_eq!(value_de, GenericFormattedValue::from(42.default_format()));
|
||||
|
||||
let value_json = "{\"Default\":42}";
|
||||
let value_de: GenericFormattedValue = serde_json::from_str(value_json).unwrap();
|
||||
|
@ -158,12 +159,12 @@ mod tests {
|
|||
|
||||
test_roundrip!(GenericFormattedValue::Undefined(Undefined::from(42)));
|
||||
test_roundrip!(GenericFormattedValue::from(Default::from_u64(42)));
|
||||
test_roundrip!(GenericFormattedValue::from(Bytes::from_u64(42)));
|
||||
test_roundrip!(GenericFormattedValue::from(42.bytes()));
|
||||
test_roundrip!(GenericFormattedValue::from(ClockTime::from_nseconds(
|
||||
42_123_456_789
|
||||
)));
|
||||
test_roundrip!(GenericFormattedValue::from(Buffers::from_u64(42)));
|
||||
test_roundrip!(GenericFormattedValue::from(Percent::from_percent(42)));
|
||||
test_roundrip!(GenericFormattedValue::from(42.buffers()));
|
||||
test_roundrip!(GenericFormattedValue::from(42.percent()));
|
||||
let gfv_value = GenericFormattedValue::Other(Format::Default, Other::try_from(42).ok());
|
||||
test_roundrip!(gfv_value);
|
||||
test_roundrip!(GenericFormattedValue::new(Format::__Unknown(7), 42));
|
||||
|
|
|
@ -67,6 +67,21 @@ impl TryFromGlib<i64> for Other {
|
|||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// `Other` formatted value constructor trait.
|
||||
pub trait OtherFormatConstructor {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds an `Other` formatted value from `self`.
|
||||
fn other_format(self) -> Other;
|
||||
}
|
||||
|
||||
impl OtherFormatConstructor for u64 {
|
||||
#[track_caller]
|
||||
fn other_format(self) -> Other {
|
||||
Other::from_u64(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum GenericFormattedValue {
|
||||
|
@ -418,7 +433,7 @@ mod tests {
|
|||
|
||||
let other_10 = Other::from_u64(10);
|
||||
let other_20 = Other::from_usize(20);
|
||||
let other_30 = Other::from_u64(30);
|
||||
let other_30 = 30.other_format();
|
||||
|
||||
assert_eq!(other_10 + other_20, other_30);
|
||||
assert_eq!(other_30 - other_20, other_10);
|
||||
|
@ -464,7 +479,7 @@ mod tests {
|
|||
p_gen_other_42,
|
||||
GenericSignedFormattedValue::Other(
|
||||
Format::__Unknown(128),
|
||||
Some(Signed::Positive(Other::from_u64(42))),
|
||||
Some(Signed::Positive(42.other_format())),
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -473,7 +488,7 @@ mod tests {
|
|||
n_gen_other_42,
|
||||
GenericSignedFormattedValue::Other(
|
||||
Format::__Unknown(128),
|
||||
Some(Signed::Negative(Other::from_u64(42))),
|
||||
Some(Signed::Negative(42.other_format())),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::ElementExtManual;
|
||||
//! # use gst::{format::prelude::*, prelude::ElementExtManual};
|
||||
//! # gst::init();
|
||||
//! # let pipeline = gst::Pipeline::new(None);
|
||||
//! # let seek_flags = gst::SeekFlags::FLUSH | gst::SeekFlags::KEY_UNIT;
|
||||
|
@ -65,6 +65,7 @@
|
|||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! use gst::prelude::*;
|
||||
//! use gst::format::{Buffers, Bytes, ClockTime, Default, Percent};
|
||||
//!
|
||||
//! // Specific formatted values implement the faillible `try_from` constructor:
|
||||
|
@ -81,45 +82,51 @@
|
|||
//! // Other formatted values also come with (panicking) constructors:
|
||||
//! let buffers_nb = Buffers::from_u64(512);
|
||||
//! let received = Bytes::from_u64(64);
|
||||
//! let sample_size = Bytes::from_usize([0u8; 4].len());
|
||||
//! let quantity = Default::from_u64(42);
|
||||
//!
|
||||
//! // `Bytes` can be built from an `usize` too:
|
||||
//! let sample_size = Bytes::from_usize([0u8; 4].len());
|
||||
//!
|
||||
//! // This can be convenient:
|
||||
//! assert_eq!(
|
||||
//! 20 * ClockTime::MSECOND,
|
||||
//! ClockTime::from_nseconds(20_000_000),
|
||||
//! );
|
||||
//! assert_eq!(
|
||||
//! 40 * ClockTime::SECOND,
|
||||
//! ClockTime::from_nseconds(40_000_000_000),
|
||||
//! 7.seconds() + 250.mseconds(),
|
||||
//! ClockTime::from_nseconds(7_250_000_000),
|
||||
//! );
|
||||
//!
|
||||
//! // `ZERO` and `NONE` can come in handy sometimes:
|
||||
//! // Those too:
|
||||
//! assert_eq!(512.buffers(), Buffers::from_u64(512));
|
||||
//! assert_eq!(64.bytes(), Bytes::from_u64(64));
|
||||
//! assert_eq!(42.default_format(), Default::from_u64(42));
|
||||
//!
|
||||
//! // The `ZERO` and `NONE` constants can come in handy sometimes:
|
||||
//! assert_eq!(*Buffers::ZERO, 0);
|
||||
//! assert!(ClockTime::NONE.is_none());
|
||||
//!
|
||||
//! // Specific formatted values provide the `ONE` value:
|
||||
//! assert_eq!(*(128 * Buffers::ONE), 128);
|
||||
//! // Specific formatted values provide the constant `ONE` value:
|
||||
//! assert_eq!(*Buffers::ONE, 1);
|
||||
//!
|
||||
//! // `Bytes` also comes with usual multipliers:
|
||||
//! assert_eq!(*(512 * Bytes::K), 512 * 1024);
|
||||
//! assert_eq!(*(8 * Bytes::M), 8 * 1024 * 1024);
|
||||
//! assert_eq!(*(4 * Bytes::G), 4 * 1024 * 1024 * 1024);
|
||||
//! assert_eq!(*(512.kibibytes()), 512 * 1024);
|
||||
//! assert_eq!(*(8.mebibytes()), 8 * 1024 * 1024);
|
||||
//! assert_eq!(*(4.gibibytes()), 4 * 1024 * 1024 * 1024);
|
||||
//!
|
||||
//! // `Percent` can be built from a floating point ratio:
|
||||
//! let a_quarter_from_ratio = Percent::from_ratio(0.25);
|
||||
//! // ... from a percent integer value:
|
||||
//! let a_quarter = Percent::from_percent(25);
|
||||
//! // ... and the macthing constants:
|
||||
//! assert_eq!(512 * Bytes::KiB, 512.kibibytes());
|
||||
//!
|
||||
//! // `Percent` can be built from a percent integer value:
|
||||
//! let a_quarter = 25.percent();
|
||||
//! // ... from a floating point ratio:
|
||||
//! let a_quarter_from_ratio = 0.25.percent_ratio();
|
||||
//! assert_eq!(a_quarter, a_quarter_from_ratio);
|
||||
//! // ... from a part per million integer value:
|
||||
//! let a_quarter_from_ppm = Percent::from_ppm(25 * 10_000);
|
||||
//! let a_quarter_from_ppm = (25 * 10_000).ppm();
|
||||
//! assert_eq!(a_quarter, a_quarter_from_ppm);
|
||||
//! // ... `MAX` which represents 100%:
|
||||
//! assert_eq!(Percent::MAX / 4, a_quarter);
|
||||
//! // ... `ONE` which is 1%:
|
||||
//! assert_eq!(25 * Percent::ONE, a_quarter);
|
||||
//! // ... and `SCALE` which is 1% in ppm:
|
||||
//! assert_eq!(Percent::SCALE, Percent::from_ppm(10_000));
|
||||
//! assert_eq!(Percent::SCALE, 10_000.ppm());
|
||||
//! ```
|
||||
//!
|
||||
//! ### Displaying a formatted value
|
||||
|
@ -129,28 +136,29 @@
|
|||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::Displayable;
|
||||
//! let time = gst::ClockTime::from_nseconds(45_834_908_569_837);
|
||||
//! # use gst::prelude::*;
|
||||
//! let time = 45_834_908_569_837.nseconds();
|
||||
//!
|
||||
//! assert_eq!(format!("{}", time), "12:43:54.908569837");
|
||||
//! assert_eq!(format!("{:.0}", time), "12:43:54");
|
||||
//! assert_eq!(format!("{time}"), "12:43:54.908569837");
|
||||
//! assert_eq!(format!("{time:.0}"), "12:43:54");
|
||||
//!
|
||||
//! let percent = gst::format::Percent::try_from(0.1234).unwrap();
|
||||
//! assert_eq!(format!("{}", percent), "12.34 %");
|
||||
//! assert_eq!(format!("{:5.1}", percent), " 12.3 %");
|
||||
//! let percent = 0.1234.percent_ratio();
|
||||
//! assert_eq!(format!("{percent}"), "12.34 %");
|
||||
//! assert_eq!(format!("{percent:5.1}"), " 12.3 %");
|
||||
//! ```
|
||||
//!
|
||||
//! ## Some operations available on specific formatted values
|
||||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::*;
|
||||
//! let cur_pos = gst::ClockTime::ZERO;
|
||||
//!
|
||||
//! // All four arithmetic operations can be used:
|
||||
//! let fwd = cur_pos + 2 * gst::ClockTime::SECOND / 3 - gst::ClockTime::MSECOND;
|
||||
//! let fwd = cur_pos + 2.seconds() / 3 - 5.mseconds();
|
||||
//!
|
||||
//! // Examples of operations which make sure not to overflow:
|
||||
//! let bwd = cur_pos.saturating_sub(2 * gst::ClockTime::SECOND);
|
||||
//! let bwd = cur_pos.saturating_sub(2.seconds());
|
||||
//! let further = cur_pos.checked_mul(2).expect("Overflowed");
|
||||
//!
|
||||
//! // Specific formatted values can be compared:
|
||||
|
@ -172,7 +180,7 @@
|
|||
//!
|
||||
//! // Specific formatted values implement the `MulDiv` trait:
|
||||
//! # use gst::prelude::MulDiv;
|
||||
//! # let (samples, rate) = (1024u64, 48000u64);
|
||||
//! # let (samples, rate) = (1024u64, 48_000u64);
|
||||
//! let duration = samples
|
||||
//! .mul_div_round(*gst::ClockTime::SECOND, rate)
|
||||
//! .map(gst::ClockTime::from_nseconds);
|
||||
|
@ -196,7 +204,7 @@
|
|||
//! # Optional specific formatted values
|
||||
//!
|
||||
//! Optional specific formatted values are represented as a standard Rust
|
||||
//! `Option<F>`. This departs from the C APIs which uses a sentinel that must
|
||||
//! `Option<F>`. This departs from the C APIs which use a sentinel that must
|
||||
//! be checked in order to figure out whether the value is defined.
|
||||
//!
|
||||
//! Besides giving access to the usual `Option` features, this ensures the APIs
|
||||
|
@ -212,13 +220,14 @@
|
|||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::format::prelude::*;
|
||||
//! # gst::init();
|
||||
//! # let seek_flags = gst::SeekFlags::FLUSH | gst::SeekFlags::KEY_UNIT;
|
||||
//! let seek_evt = gst::event::Seek::new(
|
||||
//! 1.0f64,
|
||||
//! seek_flags,
|
||||
//! gst::SeekType::Set,
|
||||
//! 10 * gst::ClockTime::SECOND, // start at 10s
|
||||
//! 10.seconds(), // start at 10s
|
||||
//! gst::SeekType::Set,
|
||||
//! gst::ClockTime::NONE, // stop is undefined
|
||||
//! );
|
||||
|
@ -234,8 +243,8 @@
|
|||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::Displayable;
|
||||
//! let opt_time = Some(45_834_908_569_837 * gst::ClockTime::NSECOND);
|
||||
//! # use gst::prelude::*;
|
||||
//! let opt_time = Some(45_834_908_569_837.nseconds());
|
||||
//!
|
||||
//! assert_eq!(format!("{}", opt_time.display()), "12:43:54.908569837");
|
||||
//! assert_eq!(format!("{:.0}", opt_time.display()), "12:43:54");
|
||||
|
@ -251,13 +260,13 @@
|
|||
//! assert!(pts.is_some());
|
||||
//!
|
||||
//! // All four arithmetic operations can be used. Ex.:
|
||||
//! let fwd = pts.opt_add(2 * gst::ClockTime::SECOND);
|
||||
//! let fwd = pts.opt_add(2.seconds());
|
||||
//! // `pts` is defined, so `fwd` will contain the addition result in `Some`,
|
||||
//! assert!(fwd.is_some());
|
||||
//! // otherwise `fwd` would be `None`.
|
||||
//!
|
||||
//! // Examples of operations which make sure not to overflow:
|
||||
//! let bwd = pts.opt_saturating_sub(2 * gst::ClockTime::SECOND);
|
||||
//! let bwd = pts.opt_saturating_sub(2.seconds());
|
||||
//! let further = pts.opt_checked_mul(2).expect("Overflowed");
|
||||
//!
|
||||
//! // Optional specific formatted values can be compared:
|
||||
|
@ -289,12 +298,13 @@
|
|||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::*;
|
||||
//! # gst::init();
|
||||
//! # let segment = gst::FormattedSegment::<gst::ClockTime>::new();
|
||||
//! use gst::Signed::*;
|
||||
//! match segment.to_running_time_full(2 * gst::ClockTime::SECOND) {
|
||||
//! Some(Positive(pos_rtime)) => println!("positive rtime {}", pos_rtime),
|
||||
//! Some(Negative(pos_rtime)) => println!("negative rtime {}", pos_rtime),
|
||||
//! match segment.to_running_time_full(2.seconds()) {
|
||||
//! Some(Positive(pos_rtime)) => println!("positive rtime {pos_rtime}"),
|
||||
//! Some(Negative(neg_rtime)) => println!("negative rtime {neg_rtime}"),
|
||||
//! None => println!("undefined rtime"),
|
||||
//! }
|
||||
//! ```
|
||||
|
@ -303,30 +313,31 @@
|
|||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::UnsignedIntoSigned;
|
||||
//! let pos = gst::ClockTime::SECOND;
|
||||
//! # use gst::prelude::*;
|
||||
//! let step = 10.mseconds();
|
||||
//!
|
||||
//! let positive_one_sec = pos.into_positive();
|
||||
//! assert!(positive_one_sec.is_positive());
|
||||
//! let positive_step = step.into_positive();
|
||||
//! assert!(positive_step.is_positive());
|
||||
//!
|
||||
//! let negative_one_sec = pos.into_negative();
|
||||
//! assert!(negative_one_sec.is_negative());
|
||||
//! let negative_step = step.into_negative();
|
||||
//! assert!(negative_step.is_negative());
|
||||
//! ```
|
||||
//!
|
||||
//! ### Handling one sign only
|
||||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::UnsignedIntoSigned;
|
||||
//! # use gst::prelude::*;
|
||||
//! # struct NegativeError;
|
||||
//! let p_one_sec = gst::ClockTime::SECOND.into_positive();
|
||||
//! let pos_step = 10.mseconds().into_positive();
|
||||
//! assert!(pos_step.is_positive());
|
||||
//!
|
||||
//! let one_sec = p_one_sec.positive().expect("positive");
|
||||
//! let one_sec_or_zero = p_one_sec.positive().unwrap_or(gst::ClockTime::ZERO);
|
||||
//! let abs_step_or_panic = pos_step.positive().expect("positive");
|
||||
//! let abs_step_or_zero = pos_step.positive().unwrap_or(gst::ClockTime::ZERO);
|
||||
//!
|
||||
//! let one_sec_or_err = p_one_sec.positive_or(NegativeError);
|
||||
//! let one_sec_or_else_err = p_one_sec.positive_or_else(|value| {
|
||||
//! println!("{} is negative", value);
|
||||
//! let abs_step_or_err = pos_step.positive_or(NegativeError);
|
||||
//! let abs_step_or_else_err = pos_step.positive_or_else(|step| {
|
||||
//! println!("{step} is negative");
|
||||
//! NegativeError
|
||||
//! });
|
||||
//! ```
|
||||
|
@ -335,14 +346,14 @@
|
|||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::Displayable;
|
||||
//! # use gst::prelude::*;
|
||||
//! # gst::init();
|
||||
//! # let mut segment = gst::FormattedSegment::<gst::ClockTime>::new();
|
||||
//! # segment.set_start(10 * gst::ClockTime::SECOND);
|
||||
//! # segment.set_start(10.seconds());
|
||||
//! let start = segment.start().unwrap();
|
||||
//! assert_eq!(format!("{:.0}", start), "0:00:10");
|
||||
//! assert_eq!(format!("{start:.0}"), "0:00:10");
|
||||
//!
|
||||
//! let p_rtime = segment.to_running_time_full(20 * gst::ClockTime::SECOND);
|
||||
//! let p_rtime = segment.to_running_time_full(20.seconds());
|
||||
//! // Use `display()` with optional signed values.
|
||||
//! assert_eq!(format!("{:.0}", p_rtime.display()), "+0:00:10");
|
||||
//!
|
||||
|
@ -360,9 +371,9 @@
|
|||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::UnsignedIntoSigned;
|
||||
//! # use gst::prelude::*;
|
||||
//! let p_one_sec = gst::ClockTime::SECOND.into_positive();
|
||||
//! let p_two_sec = (2 * gst::ClockTime::SECOND).into_positive();
|
||||
//! let p_two_sec = 2.seconds().into_positive();
|
||||
//! let n_one_sec = gst::ClockTime::SECOND.into_negative();
|
||||
//!
|
||||
//! assert_eq!(p_one_sec + p_one_sec, p_two_sec);
|
||||
|
@ -394,9 +405,9 @@
|
|||
//! }
|
||||
//!
|
||||
//! // Signed formatted values implement the `MulDiv` trait:
|
||||
//! # use gst::prelude::MulDiv;
|
||||
//! # let rate = 48000u64;
|
||||
//! let samples = (1024 * gst::format::Default::ONE).into_negative();
|
||||
//! # use gst::prelude::*;
|
||||
//! # let rate = 48_000u64;
|
||||
//! let samples = 1024.default_format().into_negative();
|
||||
//! let duration = samples
|
||||
//! .mul_div_round(*gst::ClockTime::SECOND, rate)
|
||||
//! .map(|signed_default| {
|
||||
|
@ -415,9 +426,9 @@
|
|||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::*;
|
||||
//! let p_one_sec = gst::ClockTime::SECOND.into_positive();
|
||||
//! let p_two_sec = (2 * gst::ClockTime::SECOND).into_positive();
|
||||
//! let n_one_sec = gst::ClockTime::SECOND.into_negative();
|
||||
//! let p_one_sec = 1.seconds().into_positive();
|
||||
//! let p_two_sec = 2.seconds().into_positive();
|
||||
//! let n_one_sec = 1.seconds().into_negative();
|
||||
//!
|
||||
//! // Signed `ClockTime` addition with optional and non-optional operands.
|
||||
//! assert_eq!(Some(p_one_sec).opt_add(p_one_sec), Some(p_two_sec));
|
||||
|
@ -443,9 +454,9 @@
|
|||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::{Displayable, ElementExtManual};
|
||||
//! # use gst::prelude::*;
|
||||
//! # gst::init();
|
||||
//! # let event = gst::event::SegmentDone::new(512 * gst::format::Buffers::ONE);
|
||||
//! # let event = gst::event::SegmentDone::new(512.buffers());
|
||||
//! if let gst::EventView::SegmentDone(seg_done_evt) = event.view() {
|
||||
//! use gst::GenericFormattedValue::*;
|
||||
//! match seg_done_evt.get() {
|
||||
|
@ -474,7 +485,7 @@ use thiserror::Error;
|
|||
mod macros;
|
||||
|
||||
mod clock_time;
|
||||
pub use clock_time::ClockTime;
|
||||
pub use clock_time::*;
|
||||
#[cfg(feature = "serde")]
|
||||
mod clock_time_serde;
|
||||
|
||||
|
@ -496,6 +507,15 @@ pub use specific::*;
|
|||
mod undefined;
|
||||
pub use undefined::*;
|
||||
|
||||
pub mod prelude {
|
||||
pub use super::{
|
||||
BuffersFormatConstructor, BytesFormatConstructor, DefaultFormatConstructor, FormattedValue,
|
||||
FormattedValueNoneBuilder, NoneSignedBuilder, OtherFormatConstructor,
|
||||
PercentFormatFloatConstructor, PercentFormatIntegerConstructor, TimeFormatConstructor,
|
||||
UndefinedFormatConstructor, UnsignedIntoSigned,
|
||||
};
|
||||
}
|
||||
|
||||
use crate::Format;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Error)]
|
||||
|
@ -654,11 +674,11 @@ mod tests {
|
|||
fn incompatible() {
|
||||
with_compatible_formats(
|
||||
ClockTime::ZERO,
|
||||
GenericFormattedValue::Buffers(Some(42 * Buffers::ONE)),
|
||||
GenericFormattedValue::Buffers(Some(42.buffers())),
|
||||
)
|
||||
.unwrap_err();
|
||||
with_compatible_formats(
|
||||
GenericFormattedValue::Buffers(Some(42 * Buffers::ONE)),
|
||||
GenericFormattedValue::Buffers(Some(42.buffers())),
|
||||
ClockTime::NONE,
|
||||
)
|
||||
.unwrap_err();
|
||||
|
@ -915,14 +935,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn display_new_types() {
|
||||
let bytes = 42 * Bytes::ONE;
|
||||
let bytes = 42.bytes();
|
||||
assert_eq!(&format!("{bytes}"), "42 bytes");
|
||||
assert_eq!(&format!("{}", bytes.display()), "42 bytes");
|
||||
|
||||
assert_eq!(&format!("{}", Some(bytes).display()), "42 bytes");
|
||||
assert_eq!(&format!("{}", Bytes::NONE.display()), "undef. bytes");
|
||||
|
||||
let gv_1 = GenericFormattedValue::Percent(Some(42 * Percent::ONE));
|
||||
let gv_1 = GenericFormattedValue::Percent(Some(42.percent()));
|
||||
assert_eq!(&format!("{gv_1}"), "42 %");
|
||||
assert_eq!(
|
||||
&format!("{}", GenericFormattedValue::Percent(None)),
|
||||
|
@ -950,7 +970,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn display_signed() {
|
||||
let bytes_42 = 42 * Bytes::ONE;
|
||||
let bytes_42 = 42.bytes();
|
||||
let p_bytes = bytes_42.into_positive();
|
||||
assert_eq!(&format!("{p_bytes}"), "+42 bytes");
|
||||
assert_eq!(&format!("{}", p_bytes.display()), "+42 bytes");
|
||||
|
|
|
@ -60,18 +60,37 @@ impl_format_value_traits!(Buffers, Buffers, Buffers, u64);
|
|||
option_glib_newtype_from_to!(Buffers, Buffers::OFFSET_NONE);
|
||||
glib_newtype_display!(Buffers, DisplayableOptionBuffers, Format::Buffers);
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// `Buffers` formatted value constructor trait.
|
||||
pub trait BuffersFormatConstructor {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `Buffers` formatted value from `self`.
|
||||
fn buffers(self) -> Buffers;
|
||||
}
|
||||
|
||||
impl BuffersFormatConstructor for u64 {
|
||||
#[track_caller]
|
||||
fn buffers(self) -> Buffers {
|
||||
Buffers::from_u64(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Bytes(u64);
|
||||
impl Bytes {
|
||||
#[allow(non_upper_case_globals)]
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// 1K Bytes (1024).
|
||||
pub const K: Self = Self(1024);
|
||||
/// 1 kibibyte (1024).
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const KiB: Self = Self(1024);
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// 1M Bytes (1024 * 1024).
|
||||
pub const M: Self = Self(1024 * 1024);
|
||||
/// 1 mebibyte (1024 * 1024).
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const MiB: Self = Self(1024 * 1024);
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// 1G Bytes (1024 * 1024 * 1024).
|
||||
pub const G: Self = Self(1024 * 1024 * 1024);
|
||||
/// 1 gibibyte (1024 * 1024 * 1024).
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const GiB: Self = Self(1024 * 1024 * 1024);
|
||||
pub const MAX: Self = Self(u64::MAX - 1);
|
||||
}
|
||||
|
||||
|
@ -107,6 +126,52 @@ impl_format_value_traits!(Bytes, Bytes, Bytes, u64);
|
|||
option_glib_newtype_from_to!(Bytes, u64::MAX);
|
||||
glib_newtype_display!(Bytes, DisplayableOptionBytes, Format::Bytes);
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// `Bytes` formatted value constructor trait.
|
||||
///
|
||||
/// These constructors use the [unambiguous conventions] for byte units.
|
||||
///
|
||||
/// [unambiguous conventions]: https://en.wikipedia.org/wiki/Byte#Multiple-byte_units
|
||||
pub trait BytesFormatConstructor {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `Bytes` formatted value from `self`.
|
||||
fn bytes(self) -> Bytes;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `Bytes` formatted value from `self` interpreted as kibibytes (1024).
|
||||
fn kibibytes(self) -> Bytes;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `Bytes` formatted value from `self` interpreted as mebibytes (1024²).
|
||||
fn mebibytes(self) -> Bytes;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `Bytes` formatted value from `self` interpreted as gibibytes (1024³).
|
||||
fn gibibytes(self) -> Bytes;
|
||||
}
|
||||
|
||||
impl BytesFormatConstructor for u64 {
|
||||
#[track_caller]
|
||||
fn bytes(self) -> Bytes {
|
||||
Bytes::from_u64(self)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn kibibytes(self) -> Bytes {
|
||||
Bytes::from_u64(self * 1024)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn mebibytes(self) -> Bytes {
|
||||
Bytes::from_u64(self * 1024 * 1024)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn gibibytes(self) -> Bytes {
|
||||
Bytes::from_u64(self * 1024 * 1024 * 1024)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Default(u64);
|
||||
impl Default {
|
||||
|
@ -145,6 +210,21 @@ impl_format_value_traits!(Default, Default, Default, u64);
|
|||
option_glib_newtype_from_to!(Default, u64::MAX);
|
||||
glib_newtype_display!(Default, DisplayableOptionDefault, Format::Default);
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// `Default` formatted value constructor trait.
|
||||
pub trait DefaultFormatConstructor {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `Default` formatted value from `self`.
|
||||
fn default_format(self) -> Default;
|
||||
}
|
||||
|
||||
impl DefaultFormatConstructor for u64 {
|
||||
#[track_caller]
|
||||
fn default_format(self) -> Default {
|
||||
Default::from_u64(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub type Time = super::ClockTime;
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
|
@ -345,6 +425,45 @@ impl TryFrom<f32> for Percent {
|
|||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// `Percent` formatted value from integer constructor trait.
|
||||
pub trait PercentFormatIntegerConstructor {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `Percent` formatted value from `self` interpreted as a percent.
|
||||
fn percent(self) -> Percent;
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `Percent` formatted value from `self` interpreted as parts per million.
|
||||
fn ppm(self) -> Percent;
|
||||
}
|
||||
|
||||
impl PercentFormatIntegerConstructor for u32 {
|
||||
#[track_caller]
|
||||
fn percent(self) -> Percent {
|
||||
Percent::from_percent(self)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn ppm(self) -> Percent {
|
||||
Percent::from_ppm(self)
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// `Percent` formatted value from float constructor trait.
|
||||
pub trait PercentFormatFloatConstructor {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a `Percent` formatted value from `self` interpreted as a ratio.
|
||||
fn percent_ratio(self) -> Percent;
|
||||
}
|
||||
|
||||
impl PercentFormatFloatConstructor for f32 {
|
||||
#[track_caller]
|
||||
fn percent_ratio(self) -> Percent {
|
||||
Percent::try_from(self).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Percent {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&(self.0 as f32 / (*Percent::SCALE) as f32), f)?;
|
||||
|
|
|
@ -14,6 +14,21 @@ impl Undefined {
|
|||
pub const ONE: Undefined = Undefined(1);
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// `Undefined` formatted value constructor trait.
|
||||
pub trait UndefinedFormatConstructor {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds an `Undefined` formatted value from `self`.
|
||||
fn undefined_format(self) -> Undefined;
|
||||
}
|
||||
|
||||
impl UndefinedFormatConstructor for i64 {
|
||||
#[track_caller]
|
||||
fn undefined_format(self) -> Undefined {
|
||||
Undefined(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl FormattedValue for Undefined {
|
||||
type FullRange = Undefined;
|
||||
|
||||
|
|
|
@ -337,9 +337,7 @@ pub mod prelude {
|
|||
|
||||
pub use muldiv::MulDiv;
|
||||
|
||||
pub use crate::format::{
|
||||
FormattedValue, FormattedValueNoneBuilder, NoneSignedBuilder, UnsignedIntoSigned,
|
||||
};
|
||||
pub use crate::format::prelude::*;
|
||||
pub use crate::utils::Displayable;
|
||||
|
||||
pub use crate::memory::MemoryType;
|
||||
|
|
Loading…
Reference in a new issue