Skip to content

Commit 1587623

Browse files
committed
glib: add gformat! for directly formatting into a GString
1 parent b36865b commit 1587623

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
@@ -583,6 +583,10 @@ impl<'a> ToGlibPtr<'a, *mut c_char> for GStr {
583583
}
584584
}
585585

586+
// size_of::<Inner>() minus two bytes for length and enum discriminant
587+
const INLINE_LEN: usize =
588+
mem::size_of::<Option<Box<str>>>() + mem::size_of::<usize>() - mem::size_of::<u8>() * 2;
589+
586590
// rustdoc-stripper-ignore-next
587591
/// A type representing an owned, C-compatible, nul-terminated UTF-8 string.
588592
///
@@ -619,6 +623,32 @@ impl GString {
619623
Self(Inner::Native(None))
620624
}
621625
// rustdoc-stripper-ignore-next
626+
/// Formats an [`Arguments`](std::fmt::Arguments) into a [`GString`].
627+
///
628+
/// This function is the same as [`std::fmt::format`], except it returns a [`GString`]. The
629+
/// [`Arguments`](std::fmt::Arguments) instance can be created with the
630+
/// [`format_args!`](std::format_args) macro.
631+
///
632+
/// Please note that using [`gformat!`] might be preferable.
633+
pub fn format(args: fmt::Arguments) -> Self {
634+
if let Some(s) = args.as_str() {
635+
return Self::from(s);
636+
}
637+
638+
let mut s = crate::GStringBuilder::default();
639+
fmt::Write::write_fmt(&mut s, args).unwrap();
640+
let s = mem::ManuallyDrop::new(s);
641+
if s.inner.str.is_null() {
642+
debug_assert_eq!(s.inner.allocated_len, 0);
643+
GString::new()
644+
} else {
645+
debug_assert!(s.inner.allocated_len > 0 && s.inner.len > 0);
646+
GString(Inner::Foreign {
647+
ptr: unsafe { ptr::NonNull::new_unchecked(s.inner.str) },
648+
len: s.inner.len,
649+
})
650+
}
651+
}
622652
// rustdoc-stripper-ignore-next
623653
/// Creates a GLib string by consuming a byte vector.
624654
///
@@ -876,6 +906,16 @@ impl GString {
876906
}
877907
}
878908

909+
// rustdoc-stripper-ignore-next
910+
/// Creates a [`GString`] using interpolation of runtime expressions.
911+
///
912+
/// This macro is the same as [`std::format!`] except it returns a [`GString`]. It is faster than
913+
/// creating a [`String`] and then converting it manually to a [`GString`].
914+
#[macro_export]
915+
macro_rules! gformat {
916+
($($arg:tt)*) => { GString::format(std::format_args!($($arg)*)) };
917+
}
918+
879919
// rustdoc-stripper-ignore-next
880920
/// Error type indicating that a buffer did not have a trailing nul-byte.
881921
///
@@ -1963,4 +2003,10 @@ mod tests {
19632003
assert_ne!(ptr, gstring.as_ptr() as *const _);
19642004
}
19652005
}
2006+
2007+
#[test]
2008+
fn gformat() {
2009+
let s = gformat!("bla bla {} bla", 123);
2010+
assert_eq!(s, "bla bla 123 bla");
2011+
}
19662012
}

0 commit comments

Comments
 (0)