gst/format: use fmt::Display whenever possible

Previous implementation for the glib format new types built a
`String` for the displayable value. This commit uses `fmt`
mechanisms so as to limit useless allocations.
This commit is contained in:
François Laignel 2022-09-16 17:59:05 +02:00 committed by François Laignel
parent e0d9f886e3
commit a1dbc7a0ee
2 changed files with 74 additions and 32 deletions

View file

@ -1,5 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use crate::utils::Displayable;
use crate::ClockTime;
use crate::Format;
use glib::translate::{FromGlib, GlibNoneError, IntoGlib, OptionIntoGlib, TryFromGlib};
@ -449,8 +450,6 @@ impl Percent {
impl fmt::Display for GenericFormattedValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use crate::utils::Displayable;
match self {
Self::Undefined(val) => val.fmt(f),
Self::Default(val) => val.display().fmt(f),
@ -835,19 +834,29 @@ impl FormattedValueIntrinsic for GenericFormattedValue {}
impl_common_ops_for_newtype_uint!(Default, u64);
impl_format_value_traits!(Default, Default, Default, u64);
option_glib_newtype_from_to!(Default, u64::MAX);
option_glib_newtype_display!(Default, "(Default)");
glib_newtype_display!(
Default,
DisplayableDefault,
DisplayableOptionDefault,
"(Default)"
);
impl_common_ops_for_newtype_uint!(Bytes, u64);
impl_format_value_traits!(Bytes, Bytes, Bytes, u64);
option_glib_newtype_from_to!(Bytes, u64::MAX);
option_glib_newtype_display!(Bytes, "bytes");
glib_newtype_display!(Bytes, DisplayableBytes, DisplayableOptionBytes, "bytes");
impl_format_value_traits!(ClockTime, Time, Time, u64);
impl_common_ops_for_newtype_uint!(Buffers, u64);
impl_format_value_traits!(Buffers, Buffers, Buffers, u64);
option_glib_newtype_from_to!(Buffers, Buffers::OFFSET_NONE);
option_glib_newtype_display!(Buffers, "buffers");
glib_newtype_display!(
Buffers,
DisplayableBuffers,
DisplayableOptionBuffers,
"buffers"
);
impl FormattedValue for Undefined {
type FullRange = Undefined;
@ -945,22 +954,10 @@ impl AsMut<i64> for Undefined {
}
}
impl fmt::Display for Undefined {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} (Undefined)", self.0)
}
}
impl crate::utils::Displayable for Undefined {
type DisplayImpl = Undefined;
fn display(self) -> Undefined {
self
}
}
glib_newtype_display!(Undefined, DisplayableUndefined, "(Undefined)");
impl_common_ops_for_newtype_uint!(Percent, u32);
option_glib_newtype_display!(Percent, "%");
glib_newtype_display!(Percent, DisplayablePercent, DisplayableOptionPercent, "%");
impl FormattedValue for Option<Percent> {
type FullRange = Option<Percent>;
@ -1364,4 +1361,21 @@ mod tests {
unsafe { Option::<ClockTime>::from_raw(Format::Time, raw_ct_none) }.into_signed(-1);
assert!(signed.is_none());
}
#[test]
fn display_new_types() {
let bytes = Bytes(42);
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(Percent(42)));
assert_eq!(&format!("{gv_1}"), "42 %");
assert_eq!(
&format!("{}", GenericFormattedValue::Percent(None)),
"undef. %"
);
}
}

View file

@ -541,25 +541,53 @@ macro_rules! option_glib_newtype_from_to {
};
}
macro_rules! option_glib_newtype_display {
($name:ident, $unit:expr) => {
impl crate::utils::Displayable for Option<$name> {
type DisplayImpl = String;
// FIXME we could automatically build `$displayable_name` and
// `$displayable_option_name` if `concat_idents!` was stable.
// See: https://doc.rust-lang.org/std/macro.concat_idents.html
macro_rules! glib_newtype_display {
($name:ident, $displayable_name:ident, $unit:expr) => {
pub struct $displayable_name($name);
fn display(self) -> String {
if let Some(val) = self {
val.display()
} else {
format!("undef. {}", $unit)
}
impl std::fmt::Display for $name {
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)
}
}
impl crate::utils::Displayable for $name {
type DisplayImpl = String;
type DisplayImpl = $name;
fn display(self) -> String {
format!("{} {}", self.0, $unit)
fn display(self) -> $name {
self
}
}
};
($name:ident, $displayable_name:ident, $displayable_option_name:ident, $unit:expr) => {
glib_newtype_display!($name, $displayable_name, $unit);
pub struct $displayable_option_name(Option<$name>);
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. ")?;
f.write_str($unit)
}
}
}
impl crate::utils::Displayable for Option<$name> {
type DisplayImpl = $displayable_option_name;
fn display(self) -> Self::DisplayImpl {
$displayable_option_name(self)
}
}
};