@@ -248,6 +248,7 @@ impl GStr {
248248 Ok ( ( ) )
249249 }
250250 }
251+ pub const NONE : Option < & ' static GStr > = None ;
251252}
252253
253254// rustdoc-stripper-ignore-next
@@ -1793,6 +1794,92 @@ impl From<Vec<GString>> for Value {
17931794impl_from_glib_container_as_vec_string ! ( GString , * const c_char) ;
17941795impl_from_glib_container_as_vec_string ! ( GString , * mut c_char) ;
17951796
1797+ // rustdoc-stripper-ignore-next
1798+ /// A trait to accept both <code>&[str]</code> or <code>&[GStr]</code> as an argument.
1799+ pub trait IntoGStr {
1800+ fn run_with_gstr < T , F : FnOnce ( & GStr ) -> T > ( self , f : F ) -> T ;
1801+ }
1802+
1803+ impl IntoGStr for & GStr {
1804+ #[ inline]
1805+ fn run_with_gstr < T , F : FnOnce ( & GStr ) -> T > ( self , f : F ) -> T {
1806+ f ( self )
1807+ }
1808+ }
1809+
1810+ impl IntoGStr for GString {
1811+ #[ inline]
1812+ fn run_with_gstr < T , F : FnOnce ( & GStr ) -> T > ( self , f : F ) -> T {
1813+ f ( self . as_gstr ( ) )
1814+ }
1815+ }
1816+
1817+ impl IntoGStr for & GString {
1818+ #[ inline]
1819+ fn run_with_gstr < T , F : FnOnce ( & GStr ) -> T > ( self , f : F ) -> T {
1820+ f ( self . as_gstr ( ) )
1821+ }
1822+ }
1823+
1824+ // Limit borrowed from rust std CStr optimization:
1825+ // https://github.com/rust-lang/rust/blob/master/library/std/src/sys/common/small_c_string.rs#L10
1826+ const MAX_STACK_ALLOCATION : usize = 384 ;
1827+
1828+ impl IntoGStr for & str {
1829+ #[ inline]
1830+ fn run_with_gstr < T , F : FnOnce ( & GStr ) -> T > ( self , f : F ) -> T {
1831+ if self . len ( ) < MAX_STACK_ALLOCATION {
1832+ let mut s = mem:: MaybeUninit :: < [ u8 ; MAX_STACK_ALLOCATION ] > :: uninit ( ) ;
1833+ let ptr = s. as_mut_ptr ( ) as * mut u8 ;
1834+ let gs = unsafe {
1835+ ptr:: copy_nonoverlapping ( self . as_ptr ( ) , ptr, self . len ( ) ) ;
1836+ ptr. add ( self . len ( ) ) . write ( 0 ) ;
1837+ GStr :: from_utf8_with_nul_unchecked ( slice:: from_raw_parts ( ptr, self . len ( ) + 1 ) )
1838+ } ;
1839+ f ( gs)
1840+ } else {
1841+ f ( GString :: from ( self ) . as_gstr ( ) )
1842+ }
1843+ }
1844+ }
1845+
1846+ impl IntoGStr for String {
1847+ #[ inline]
1848+ fn run_with_gstr < T , F : FnOnce ( & GStr ) -> T > ( self , f : F ) -> T {
1849+ if self . len ( ) < MAX_STACK_ALLOCATION {
1850+ self . as_str ( ) . run_with_gstr ( f)
1851+ } else {
1852+ f ( GString :: from ( self ) . as_gstr ( ) )
1853+ }
1854+ }
1855+ }
1856+
1857+ impl IntoGStr for & String {
1858+ #[ inline]
1859+ fn run_with_gstr < T , F : FnOnce ( & GStr ) -> T > ( self , f : F ) -> T {
1860+ self . as_str ( ) . run_with_gstr ( f)
1861+ }
1862+ }
1863+
1864+ pub const NONE_STR : Option < & ' static str > = None ;
1865+
1866+ // rustdoc-stripper-ignore-next
1867+ /// A trait to accept both <code>[Option]<&[str]></code> or <code>[Option]<&[GStr]></code> as
1868+ /// an argument.
1869+ pub trait IntoOptionalGStr {
1870+ fn run_with_gstr < T , F : FnOnce ( Option < & GStr > ) -> T > ( self , f : F ) -> T ;
1871+ }
1872+
1873+ impl < S : IntoGStr > IntoOptionalGStr for Option < S > {
1874+ #[ inline]
1875+ fn run_with_gstr < T , F : FnOnce ( Option < & GStr > ) -> T > ( self , f : F ) -> T {
1876+ match self {
1877+ Some ( t) => t. run_with_gstr ( |s| f ( Some ( s) ) ) ,
1878+ None => f ( None ) ,
1879+ }
1880+ }
1881+ }
1882+
17961883#[ cfg( test) ]
17971884#[ allow( clippy:: disallowed_names) ]
17981885mod tests {
0 commit comments