Skip to content

Commit baac1cc

Browse files
committed
glib: add gformat! for directly formatting into a GString
1 parent 23165e1 commit baac1cc

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
///
@@ -610,6 +614,32 @@ impl GString {
610614
Self(Inner::Native(None))
611615
}
612616
// rustdoc-stripper-ignore-next
617+
/// Formats an [`Arguments`](std::fmt::Arguments) into a [`GString`].
618+
///
619+
/// This function is the same as [`std::fmt::format`], except it returns a [`GString`]. The
620+
/// [`Arguments`](std::fmt::Arguments) instance can be created with the
621+
/// [`format_args!`](std::format_args) macro.
622+
///
623+
/// Please note that using [`gformat!`] might be preferable.
624+
pub fn format(args: fmt::Arguments) -> Self {
625+
if let Some(s) = args.as_str() {
626+
return Self::from(s);
627+
}
628+
629+
let mut s = crate::GStringBuilder::default();
630+
fmt::Write::write_fmt(&mut s, args).unwrap();
631+
let s = mem::ManuallyDrop::new(s);
632+
if s.inner.str.is_null() {
633+
debug_assert_eq!(s.inner.allocated_len, 0);
634+
GString::new()
635+
} else {
636+
debug_assert!(s.inner.allocated_len > 0 && s.inner.len > 0);
637+
GString(Inner::Foreign {
638+
ptr: unsafe { ptr::NonNull::new_unchecked(s.inner.str) },
639+
len: s.inner.len,
640+
})
641+
}
642+
}
613643
// rustdoc-stripper-ignore-next
614644
/// Creates a GLib string by consuming a byte vector.
615645
///
@@ -841,6 +871,16 @@ impl GString {
841871
}
842872
}
843873

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

0 commit comments

Comments
 (0)