Skip to content

Commit b515fad

Browse files
committed
glib: add gformat! for directly formatting into a GString
1 parent 70fbbc7 commit b515fad

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

glib/src/gstring.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,10 @@ impl<'a> ToGlibPtr<'a, *mut c_char> for GStr {
573573
}
574574
}
575575

576+
// size_of::<Inner>() minus two bytes for length and enum discriminant
577+
const INLINE_LEN: usize =
578+
mem::size_of::<Option<Box<str>>>() + mem::size_of::<usize>() - mem::size_of::<u8>() * 2;
579+
576580
// rustdoc-stripper-ignore-next
577581
/// A type representing an owned, C-compatible, nul-terminated UTF-8 string.
578582
///
@@ -609,6 +613,32 @@ impl GString {
609613
Self(Inner::Native(None))
610614
}
611615
// rustdoc-stripper-ignore-next
616+
/// Formats an [`Arguments`](std::fmt::Arguments) into a [`GString`].
617+
///
618+
/// This function is the same as [`std::fmt::format`], except it returns a [`GString`]. The
619+
/// [`Arguments`](std::fmt::Arguments) instance can be created with the
620+
/// [`format_args!`](std::format_args) macro.
621+
///
622+
/// Please note that using [`gformat!`] might be preferable.
623+
pub fn format(args: fmt::Arguments) -> Self {
624+
if let Some(s) = args.as_str() {
625+
return Self::from(s);
626+
}
627+
628+
let mut s = crate::GStringBuilder::default();
629+
fmt::Write::write_fmt(&mut s, args).unwrap();
630+
let s = mem::ManuallyDrop::new(s);
631+
if s.inner.str.is_null() {
632+
debug_assert_eq!(s.inner.allocated_len, 0);
633+
GString::new()
634+
} else {
635+
debug_assert!(s.inner.allocated_len > 0 && s.inner.len > 0);
636+
GString(Inner::Foreign {
637+
ptr: unsafe { ptr::NonNull::new_unchecked(s.inner.str) },
638+
len: s.inner.len,
639+
})
640+
}
641+
}
612642
// rustdoc-stripper-ignore-next
613643
/// Creates a GLib string by consuming a byte vector.
614644
///
@@ -840,6 +870,16 @@ impl GString {
840870
}
841871
}
842872

873+
// rustdoc-stripper-ignore-next
874+
/// Creates a [`GString`] using interpolation of runtime expressions.
875+
///
876+
/// This macro is the same as [`std::format!`] except it returns a [`GString`]. It is faster than
877+
/// creating a [`String`] and then converting it manually to a [`GString`].
878+
#[macro_export]
879+
macro_rules! gformat {
880+
($($arg:tt)*) => { GString::format(std::format_args!($($arg)*)) };
881+
}
882+
843883
// rustdoc-stripper-ignore-next
844884
/// Error type indicating that a buffer did not have a trailing nul-byte.
845885
///
@@ -1869,4 +1909,10 @@ mod tests {
18691909
let gstring: GString = "foo".into();
18701910
assert!(h.contains_key(&gstring));
18711911
}
1912+
1913+
#[test]
1914+
fn gformat() {
1915+
let s = gformat!("bla bla {} bla", 123);
1916+
assert_eq!(s, "bla bla 123 bla");
1917+
}
18721918
}

0 commit comments

Comments
 (0)