@@ -426,7 +426,7 @@ impl GString {
426
426
427
427
impl Clone for GString {
428
428
fn clone ( & self ) -> GString {
429
- self . as_str ( ) . into ( )
429
+ self . as_gstr ( ) . to_owned ( )
430
430
}
431
431
}
432
432
@@ -651,23 +651,23 @@ impl From<GString> for Box<str> {
651
651
}
652
652
}
653
653
654
- impl From < String > for GString {
654
+ impl TryFrom < String > for GString {
655
+ type Error = std:: ffi:: NulError ;
655
656
#[ inline]
656
- fn from ( s : String ) -> Self {
657
+ fn try_from ( s : String ) -> Result < Self , Self :: Error > {
657
658
// 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) ) ) )
663
662
}
664
663
}
665
664
666
- impl From < Box < str > > for GString {
665
+ impl TryFrom < Box < str > > for GString {
666
+ type Error = std:: ffi:: NulError ;
667
667
#[ inline]
668
- fn from ( s : Box < str > ) -> Self {
668
+ fn try_from ( s : Box < str > ) -> Result < Self , Self :: Error > {
669
669
// Moves the content of the String
670
- s. into_string ( ) . into ( )
670
+ s. into_string ( ) . try_into ( )
671
671
}
672
672
}
673
673
@@ -678,50 +678,48 @@ impl From<&GStr> for GString {
678
678
}
679
679
}
680
680
681
- impl From < & str > for GString {
681
+ impl TryFrom < & str > for GString {
682
+ type Error = std:: ffi:: NulError ;
682
683
#[ 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 ( )
696
686
}
697
687
}
698
688
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 ;
700
699
#[ inline]
701
- fn from ( s : Vec < u8 > ) -> Self {
700
+ fn try_from ( s : Vec < u8 > ) -> Result < Self , Self :: Error > {
702
701
// 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 ( ) ? )
706
705
}
707
706
}
708
707
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 > {
712
711
// Moves the content of the CString
713
712
// 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) ) ) )
716
715
}
717
716
}
718
717
719
- impl From < & CStr > for GString {
718
+ impl TryFrom < & CStr > for GString {
719
+ type Error = std:: str:: Utf8Error ;
720
720
#[ 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 ( )
725
723
}
726
724
}
727
725
@@ -772,7 +770,7 @@ impl FromGlibPtrNone<*const u8> for GString {
772
770
assert ! ( !ptr. is_null( ) ) ;
773
771
let cstr = CStr :: from_ptr ( ptr as * const _ ) ;
774
772
// Also check if it's valid UTF-8
775
- cstr. to_str ( ) . unwrap ( ) . into ( )
773
+ cstr. try_into ( ) . unwrap ( )
776
774
}
777
775
}
778
776
@@ -904,16 +902,16 @@ impl<'a> ToGlibPtr<'a, *mut i8> for GString {
904
902
impl < ' a > FromGlibContainer < * const c_char , * const i8 > for GString {
905
903
unsafe fn from_glib_none_num ( ptr : * const i8 , num : usize ) -> Self {
906
904
if num == 0 || ptr. is_null ( ) {
907
- return Self :: from ( "" ) ;
905
+ return Self :: try_from ( "" ) . unwrap ( ) ;
908
906
}
909
907
let slice = slice:: from_raw_parts ( ptr as * const u8 , num) ;
910
908
// 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 ( )
912
910
}
913
911
914
912
unsafe fn from_glib_container_num ( ptr : * const i8 , num : usize ) -> Self {
915
913
if num == 0 || ptr. is_null ( ) {
916
- return Self :: from ( "" ) ;
914
+ return Self :: try_from ( "" ) . unwrap ( ) ;
917
915
}
918
916
919
917
// Check if it's valid UTF-8
@@ -928,7 +926,7 @@ impl<'a> FromGlibContainer<*const c_char, *const i8> for GString {
928
926
929
927
unsafe fn from_glib_full_num ( ptr : * const i8 , num : usize ) -> Self {
930
928
if num == 0 || ptr. is_null ( ) {
931
- return Self :: from ( "" ) ;
929
+ return Self :: try_from ( "" ) . unwrap ( ) ;
932
930
}
933
931
934
932
// Check if it's valid UTF-8
@@ -1007,7 +1005,7 @@ unsafe impl<'a> crate::value::FromValue<'a> for GString {
1007
1005
type Checker = crate :: value:: GenericValueTypeOrNoneChecker < Self > ;
1008
1006
1009
1007
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 ( )
1011
1009
}
1012
1010
}
1013
1011
@@ -1097,15 +1095,15 @@ mod tests {
1097
1095
1098
1096
#[ test]
1099
1097
fn test_gstring_from_str ( ) {
1100
- let gstring: GString = "foo" . into ( ) ;
1098
+ let gstring: GString = "foo" . try_into ( ) . unwrap ( ) ;
1101
1099
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1102
1100
let foo: Box < str > = gstring. into ( ) ;
1103
1101
assert_eq ! ( foo. as_ref( ) , "foo" ) ;
1104
1102
}
1105
1103
1106
1104
#[ test]
1107
1105
fn test_string_from_gstring ( ) {
1108
- let gstring = GString :: from ( "foo" ) ;
1106
+ let gstring = GString :: try_from ( "foo" ) . unwrap ( ) ;
1109
1107
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1110
1108
let s = String :: from ( gstring) ;
1111
1109
assert_eq ! ( s, "foo" ) ;
@@ -1114,7 +1112,7 @@ mod tests {
1114
1112
#[ test]
1115
1113
fn test_gstring_from_cstring ( ) {
1116
1114
let cstr = CString :: new ( "foo" ) . unwrap ( ) ;
1117
- let gstring = GString :: from ( cstr) ;
1115
+ let gstring = GString :: try_from ( cstr) . unwrap ( ) ;
1118
1116
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1119
1117
let foo: Box < str > = gstring. into ( ) ;
1120
1118
assert_eq ! ( foo. as_ref( ) , "foo" ) ;
@@ -1123,7 +1121,7 @@ mod tests {
1123
1121
#[ test]
1124
1122
fn test_string_from_gstring_from_cstring ( ) {
1125
1123
let cstr = CString :: new ( "foo" ) . unwrap ( ) ;
1126
- let gstring = GString :: from ( cstr) ;
1124
+ let gstring = GString :: try_from ( cstr) . unwrap ( ) ;
1127
1125
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1128
1126
let s = String :: from ( gstring) ;
1129
1127
assert_eq ! ( s, "foo" ) ;
@@ -1132,7 +1130,7 @@ mod tests {
1132
1130
#[ test]
1133
1131
fn test_vec_u8_to_gstring ( ) {
1134
1132
let v: & [ u8 ] = b"foo" ;
1135
- let s: GString = Vec :: from ( v) . into ( ) ;
1133
+ let s: GString = Vec :: from ( v) . try_into ( ) . unwrap ( ) ;
1136
1134
assert_eq ! ( s. as_str( ) , "foo" ) ;
1137
1135
}
1138
1136
@@ -1165,11 +1163,11 @@ mod tests {
1165
1163
fn test_hashmap ( ) {
1166
1164
use std:: collections:: HashMap ;
1167
1165
1168
- let gstring = GString :: from ( "foo" ) ;
1166
+ let gstring = GString :: try_from ( "foo" ) . unwrap ( ) ;
1169
1167
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1170
1168
let mut h: HashMap < GString , i32 > = HashMap :: new ( ) ;
1171
1169
h. insert ( gstring, 42 ) ;
1172
- let gstring: GString = "foo" . into ( ) ;
1170
+ let gstring: GString = "foo" . try_into ( ) . unwrap ( ) ;
1173
1171
assert ! ( h. contains_key( & gstring) ) ;
1174
1172
}
1175
1173
}
0 commit comments