diff --git a/gstreamer-audio/src/audio_meta.rs b/gstreamer-audio/src/audio_meta.rs index 825fd99c7..d79ae5bf0 100644 --- a/gstreamer-audio/src/audio_meta.rs +++ b/gstreamer-audio/src/audio_meta.rs @@ -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); diff --git a/gstreamer/src/format/clock_time.rs b/gstreamer/src/format/clock_time.rs index cdf365545..66770ec40 100644 --- a/gstreamer/src/format/clock_time.rs +++ b/gstreamer/src/format/clock_time.rs @@ -199,6 +199,66 @@ impl Signed { 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; } diff --git a/gstreamer/src/format/format_serde.rs b/gstreamer/src/format/format_serde.rs index 4e6049cff..fcbd9aa9b 100644 --- a/gstreamer/src/format/format_serde.rs +++ b/gstreamer/src/format/format_serde.rs @@ -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::::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)); diff --git a/gstreamer/src/format/generic.rs b/gstreamer/src/format/generic.rs index e319974a0..dcf464786 100644 --- a/gstreamer/src/format/generic.rs +++ b/gstreamer/src/format/generic.rs @@ -67,6 +67,21 @@ impl TryFromGlib 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())), ), ); } diff --git a/gstreamer/src/format/mod.rs b/gstreamer/src/format/mod.rs index 995691420..869043c62 100644 --- a/gstreamer/src/format/mod.rs +++ b/gstreamer/src/format/mod.rs @@ -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`. This departs from the C APIs which uses a sentinel that must +//! `Option`. 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,15 +220,16 @@ //! //! ``` //! # 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 +//! 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::::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::::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"); diff --git a/gstreamer/src/format/specific.rs b/gstreamer/src/format/specific.rs index 6ebe6ba27..bbc43b287 100644 --- a/gstreamer/src/format/specific.rs +++ b/gstreamer/src/format/specific.rs @@ -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 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)?; diff --git a/gstreamer/src/format/undefined.rs b/gstreamer/src/format/undefined.rs index 1084c7c36..9624aa5b0 100644 --- a/gstreamer/src/format/undefined.rs +++ b/gstreamer/src/format/undefined.rs @@ -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; diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index 98605a50d..876e415ca 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -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;