@@ -426,7 +426,7 @@ impl GString {
426426
427427impl Clone for GString {
428428 fn clone ( & self ) -> GString {
429- self . as_str ( ) . into ( )
429+ self . as_gstr ( ) . to_owned ( )
430430 }
431431}
432432
@@ -651,23 +651,23 @@ impl From<GString> for Box<str> {
651651 }
652652}
653653
654- impl From < String > for GString {
654+ impl TryFrom < String > for GString {
655+ type Error = std:: ffi:: NulError ;
655656 #[ inline]
656- fn from ( s : String ) -> Self {
657+ fn try_from ( s : String ) -> Result < Self , Self :: Error > {
657658 // Moves the content of the String
658- unsafe {
659- // No check for valid UTF-8 here
660- let cstr = CString :: from_vec_unchecked ( s. into_bytes ( ) ) ;
661- GString ( Inner :: Native ( Some ( cstr) ) )
662- }
659+ // Check for interior nul bytes
660+ let cstr = CString :: new ( s. into_bytes ( ) ) ?;
661+ Ok ( GString ( Inner :: Native ( Some ( cstr) ) ) )
663662 }
664663}
665664
666- impl From < Box < str > > for GString {
665+ impl TryFrom < Box < str > > for GString {
666+ type Error = std:: ffi:: NulError ;
667667 #[ inline]
668- fn from ( s : Box < str > ) -> Self {
668+ fn try_from ( s : Box < str > ) -> Result < Self , Self :: Error > {
669669 // Moves the content of the String
670- s. into_string ( ) . into ( )
670+ s. into_string ( ) . try_into ( )
671671 }
672672}
673673
@@ -678,50 +678,48 @@ impl From<&GStr> for GString {
678678 }
679679}
680680
681- impl From < & str > for GString {
681+ impl TryFrom < & str > for GString {
682+ type Error = std:: ffi:: NulError ;
682683 #[ inline]
683- fn from ( s : & str ) -> Self {
684- // Allocates with the GLib allocator
685- unsafe {
686- // No check for valid UTF-8 here
687- let copy = ffi:: g_malloc ( s. len ( ) + 1 ) as * mut c_char ;
688- ptr:: copy_nonoverlapping ( s. as_ptr ( ) as * const c_char , copy, s. len ( ) + 1 ) ;
689- ptr:: write ( copy. add ( s. len ( ) ) , 0 ) ;
690-
691- GString ( Inner :: Foreign {
692- ptr : ptr:: NonNull :: new_unchecked ( copy) ,
693- len : s. len ( ) ,
694- } )
695- }
684+ fn try_from ( s : & str ) -> Result < Self , Self :: Error > {
685+ s. to_owned ( ) . try_into ( )
696686 }
697687}
698688
699- impl From < Vec < u8 > > for GString {
689+ #[ derive( thiserror:: Error , Debug ) ]
690+ pub enum GStringError {
691+ #[ error( "invalid UTF-8" ) ]
692+ Utf8 ( #[ from] std:: str:: Utf8Error ) ,
693+ #[ error( "interior nul bytes" ) ]
694+ Nul ( #[ from] std:: ffi:: NulError ) ,
695+ }
696+
697+ impl TryFrom < Vec < u8 > > for GString {
698+ type Error = GStringError ;
700699 #[ inline]
701- fn from ( s : Vec < u8 > ) -> Self {
700+ fn try_from ( s : Vec < u8 > ) -> Result < Self , Self :: Error > {
702701 // Moves the content of the Vec
703- // Also check if it's valid UTF-8
704- let cstring = CString :: new ( s) . expect ( "CString::new failed" ) ;
705- cstring. into ( )
702+ // Also check if it's valid UTF-8 and has no interior nuls
703+ let cstring = CString :: new ( s) ? ;
704+ Ok ( cstring. try_into ( ) ? )
706705 }
707706}
708707
709- impl From < CString > for GString {
710- # [ inline ]
711- fn from ( s : CString ) -> Self {
708+ impl TryFrom < CString > for GString {
709+ type Error = std :: str :: Utf8Error ;
710+ fn try_from ( s : CString ) -> Result < Self , Self :: Error > {
712711 // Moves the content of the CString
713712 // Also check if it's valid UTF-8
714- assert ! ( s. to_str( ) . is_ok ( ) ) ;
715- Self ( Inner :: Native ( Some ( s) ) )
713+ s. to_str ( ) ? ;
714+ Ok ( Self ( Inner :: Native ( Some ( s) ) ) )
716715 }
717716}
718717
719- impl From < & CStr > for GString {
718+ impl TryFrom < & CStr > for GString {
719+ type Error = std:: str:: Utf8Error ;
720720 #[ inline]
721- fn from ( c : & CStr ) -> Self {
722- // Creates a copy with the GLib allocator
723- // Also check if it's valid UTF-8
724- c. to_str ( ) . unwrap ( ) . into ( )
721+ fn try_from ( c : & CStr ) -> Result < Self , Self :: Error > {
722+ c. to_owned ( ) . try_into ( )
725723 }
726724}
727725
@@ -772,7 +770,7 @@ impl FromGlibPtrNone<*const u8> for GString {
772770 assert ! ( !ptr. is_null( ) ) ;
773771 let cstr = CStr :: from_ptr ( ptr as * const _ ) ;
774772 // Also check if it's valid UTF-8
775- cstr. to_str ( ) . unwrap ( ) . into ( )
773+ cstr. try_into ( ) . unwrap ( )
776774 }
777775}
778776
@@ -904,16 +902,16 @@ impl<'a> ToGlibPtr<'a, *mut i8> for GString {
904902impl < ' a > FromGlibContainer < * const c_char , * const i8 > for GString {
905903 unsafe fn from_glib_none_num ( ptr : * const i8 , num : usize ) -> Self {
906904 if num == 0 || ptr. is_null ( ) {
907- return Self :: from ( "" ) ;
905+ return Self :: try_from ( "" ) . unwrap ( ) ;
908906 }
909907 let slice = slice:: from_raw_parts ( ptr as * const u8 , num) ;
910908 // Also check if it's valid UTF-8
911- std:: str:: from_utf8 ( slice) . unwrap ( ) . into ( )
909+ std:: str:: from_utf8 ( slice) . unwrap ( ) . try_into ( ) . unwrap ( )
912910 }
913911
914912 unsafe fn from_glib_container_num ( ptr : * const i8 , num : usize ) -> Self {
915913 if num == 0 || ptr. is_null ( ) {
916- return Self :: from ( "" ) ;
914+ return Self :: try_from ( "" ) . unwrap ( ) ;
917915 }
918916
919917 // Check if it's valid UTF-8
@@ -928,7 +926,7 @@ impl<'a> FromGlibContainer<*const c_char, *const i8> for GString {
928926
929927 unsafe fn from_glib_full_num ( ptr : * const i8 , num : usize ) -> Self {
930928 if num == 0 || ptr. is_null ( ) {
931- return Self :: from ( "" ) ;
929+ return Self :: try_from ( "" ) . unwrap ( ) ;
932930 }
933931
934932 // Check if it's valid UTF-8
@@ -1007,7 +1005,7 @@ unsafe impl<'a> crate::value::FromValue<'a> for GString {
10071005 type Checker = crate :: value:: GenericValueTypeOrNoneChecker < Self > ;
10081006
10091007 unsafe fn from_value ( value : & ' a crate :: Value ) -> Self {
1010- Self :: from ( <& str >:: from_value ( value) )
1008+ Self :: try_from ( <& str >:: from_value ( value) ) . unwrap ( )
10111009 }
10121010}
10131011
@@ -1097,15 +1095,15 @@ mod tests {
10971095
10981096 #[ test]
10991097 fn test_gstring_from_str ( ) {
1100- let gstring: GString = "foo" . into ( ) ;
1098+ let gstring: GString = "foo" . try_into ( ) . unwrap ( ) ;
11011099 assert_eq ! ( gstring. as_str( ) , "foo" ) ;
11021100 let foo: Box < str > = gstring. into ( ) ;
11031101 assert_eq ! ( foo. as_ref( ) , "foo" ) ;
11041102 }
11051103
11061104 #[ test]
11071105 fn test_string_from_gstring ( ) {
1108- let gstring = GString :: from ( "foo" ) ;
1106+ let gstring = GString :: try_from ( "foo" ) . unwrap ( ) ;
11091107 assert_eq ! ( gstring. as_str( ) , "foo" ) ;
11101108 let s = String :: from ( gstring) ;
11111109 assert_eq ! ( s, "foo" ) ;
@@ -1114,7 +1112,7 @@ mod tests {
11141112 #[ test]
11151113 fn test_gstring_from_cstring ( ) {
11161114 let cstr = CString :: new ( "foo" ) . unwrap ( ) ;
1117- let gstring = GString :: from ( cstr) ;
1115+ let gstring = GString :: try_from ( cstr) . unwrap ( ) ;
11181116 assert_eq ! ( gstring. as_str( ) , "foo" ) ;
11191117 let foo: Box < str > = gstring. into ( ) ;
11201118 assert_eq ! ( foo. as_ref( ) , "foo" ) ;
@@ -1123,7 +1121,7 @@ mod tests {
11231121 #[ test]
11241122 fn test_string_from_gstring_from_cstring ( ) {
11251123 let cstr = CString :: new ( "foo" ) . unwrap ( ) ;
1126- let gstring = GString :: from ( cstr) ;
1124+ let gstring = GString :: try_from ( cstr) . unwrap ( ) ;
11271125 assert_eq ! ( gstring. as_str( ) , "foo" ) ;
11281126 let s = String :: from ( gstring) ;
11291127 assert_eq ! ( s, "foo" ) ;
@@ -1132,7 +1130,7 @@ mod tests {
11321130 #[ test]
11331131 fn test_vec_u8_to_gstring ( ) {
11341132 let v: & [ u8 ] = b"foo" ;
1135- let s: GString = Vec :: from ( v) . into ( ) ;
1133+ let s: GString = Vec :: from ( v) . try_into ( ) . unwrap ( ) ;
11361134 assert_eq ! ( s. as_str( ) , "foo" ) ;
11371135 }
11381136
@@ -1165,11 +1163,11 @@ mod tests {
11651163 fn test_hashmap ( ) {
11661164 use std:: collections:: HashMap ;
11671165
1168- let gstring = GString :: from ( "foo" ) ;
1166+ let gstring = GString :: try_from ( "foo" ) . unwrap ( ) ;
11691167 assert_eq ! ( gstring. as_str( ) , "foo" ) ;
11701168 let mut h: HashMap < GString , i32 > = HashMap :: new ( ) ;
11711169 h. insert ( gstring, 42 ) ;
1172- let gstring: GString = "foo" . into ( ) ;
1170+ let gstring: GString = "foo" . try_into ( ) . unwrap ( ) ;
11731171 assert ! ( h. contains_key( & gstring) ) ;
11741172 }
11751173}
0 commit comments