@@ -33,7 +33,7 @@ impl GStr {
33
33
pub fn from_str_with_nul ( s : & str ) -> Result < & Self , std:: ffi:: FromBytesWithNulError > {
34
34
let bytes = s. as_bytes ( ) ;
35
35
CStr :: from_bytes_with_nul ( bytes) ?;
36
- Ok ( unsafe { Self :: from_bytes_with_nul_unchecked ( bytes) } )
36
+ Ok ( unsafe { Self :: from_utf8_with_nul_unchecked ( bytes) } )
37
37
}
38
38
// rustdoc-stripper-ignore-next
39
39
/// Unsafely creates a GLib string wrapper from a byte slice.
@@ -42,7 +42,7 @@ impl GStr {
42
42
/// sanity checks. The provided slice **must** be valid UTF-8, nul-terminated and not contain
43
43
/// any interior nul bytes.
44
44
#[ inline]
45
- pub const unsafe fn from_bytes_with_nul_unchecked ( bytes : & [ u8 ] ) -> & Self {
45
+ pub const unsafe fn from_utf8_with_nul_unchecked ( bytes : & [ u8 ] ) -> & Self {
46
46
debug_assert ! ( !bytes. is_empty( ) && bytes[ bytes. len( ) - 1 ] == 0 ) ;
47
47
mem:: transmute ( bytes)
48
48
}
@@ -53,7 +53,7 @@ impl GStr {
53
53
#[ inline]
54
54
pub unsafe fn from_ptr < ' a > ( ptr : * const c_char ) -> & ' a Self {
55
55
let cstr = CStr :: from_ptr ( ptr) ;
56
- Self :: from_bytes_with_nul_unchecked ( cstr. to_bytes_with_nul ( ) )
56
+ Self :: from_utf8_with_nul_unchecked ( cstr. to_bytes_with_nul ( ) )
57
57
}
58
58
// rustdoc-stripper-ignore-next
59
59
/// Converts this GLib string to a byte slice containing the trailing 0 byte.
@@ -126,7 +126,7 @@ impl GStr {
126
126
#[ macro_export]
127
127
macro_rules! gstr {
128
128
( $s: literal) => {
129
- unsafe { $crate:: GStr :: from_bytes_with_nul_unchecked ( $crate:: cstr_bytes!( $s) ) }
129
+ unsafe { $crate:: GStr :: from_utf8_with_nul_unchecked ( $crate:: cstr_bytes!( $s) ) }
130
130
} ;
131
131
}
132
132
@@ -142,7 +142,7 @@ impl<'a> TryFrom<&'a CStr> for &'a GStr {
142
142
#[ inline]
143
143
fn try_from ( s : & ' a CStr ) -> Result < Self , Self :: Error > {
144
144
s. to_str ( ) ?;
145
- Ok ( unsafe { GStr :: from_bytes_with_nul_unchecked ( s. to_bytes_with_nul ( ) ) } )
145
+ Ok ( unsafe { GStr :: from_utf8_with_nul_unchecked ( s. to_bytes_with_nul ( ) ) } )
146
146
}
147
147
}
148
148
@@ -270,7 +270,7 @@ unsafe impl<'a> crate::value::FromValue<'a> for &'a GStr {
270
270
let ptr = gobject_ffi:: g_value_get_string ( value. to_glib_none ( ) . 0 ) ;
271
271
let cstr = CStr :: from_ptr ( ptr) ;
272
272
assert ! ( cstr. to_str( ) . is_ok( ) ) ;
273
- GStr :: from_bytes_with_nul_unchecked ( cstr. to_bytes_with_nul ( ) )
273
+ GStr :: from_utf8_with_nul_unchecked ( cstr. to_bytes_with_nul ( ) )
274
274
}
275
275
}
276
276
@@ -388,7 +388,7 @@ impl GString {
388
388
slice:: from_raw_parts ( ptr. as_ptr ( ) as * const _ , len + 1 )
389
389
} ,
390
390
} ;
391
- unsafe { GStr :: from_bytes_with_nul_unchecked ( bytes) }
391
+ unsafe { GStr :: from_utf8_with_nul_unchecked ( bytes) }
392
392
}
393
393
394
394
// rustdoc-stripper-ignore-next
@@ -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,69 @@ 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:: FromBytesWithNulError ;
682
683
#[ inline]
683
- fn from ( s : & str ) -> Self {
684
+ fn try_from ( s : & str ) -> Result < Self , Self :: Error > {
684
685
// Allocates with the GLib allocator
685
686
unsafe {
686
687
// No check for valid UTF-8 here
687
688
let copy = ffi:: g_malloc ( s. len ( ) + 1 ) as * mut c_char ;
688
689
ptr:: copy_nonoverlapping ( s. as_ptr ( ) as * const c_char , copy, s. len ( ) + 1 ) ;
689
690
ptr:: write ( copy. add ( s. len ( ) ) , 0 ) ;
690
691
691
- GString ( Inner :: Foreign {
692
+ // Check for interior nul bytes
693
+ let check = std:: ffi:: CStr :: from_bytes_with_nul ( std:: slice:: from_raw_parts (
694
+ copy as * const _ ,
695
+ s. len ( ) + 1 ,
696
+ ) ) ;
697
+ if let Err ( err) = check {
698
+ ffi:: g_free ( copy as * mut _ ) ;
699
+ return Err ( err) ;
700
+ }
701
+
702
+ Ok ( GString ( Inner :: Foreign {
692
703
ptr : ptr:: NonNull :: new_unchecked ( copy) ,
693
704
len : s. len ( ) ,
694
- } )
705
+ } ) )
695
706
}
696
707
}
697
708
}
698
709
699
- impl From < Vec < u8 > > for GString {
710
+ #[ derive( thiserror:: Error , Debug ) ]
711
+ pub enum GStringError {
712
+ #[ error( "invalid UTF-8" ) ]
713
+ Utf8 ( #[ from] std:: str:: Utf8Error ) ,
714
+ #[ error( "interior nul bytes" ) ]
715
+ Nul ( #[ from] std:: ffi:: NulError ) ,
716
+ }
717
+
718
+ impl TryFrom < Vec < u8 > > for GString {
719
+ type Error = GStringError ;
700
720
#[ inline]
701
- fn from ( s : Vec < u8 > ) -> Self {
721
+ fn try_from ( s : Vec < u8 > ) -> Result < Self , Self :: Error > {
702
722
// 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 ( )
723
+ // Also check if it's valid UTF-8 and has no interior nuls
724
+ let cstring = CString :: new ( s) ? ;
725
+ Ok ( cstring. try_into ( ) ? )
706
726
}
707
727
}
708
728
709
- impl From < CString > for GString {
710
- # [ inline ]
711
- fn from ( s : CString ) -> Self {
729
+ impl TryFrom < CString > for GString {
730
+ type Error = std :: str :: Utf8Error ;
731
+ fn try_from ( s : CString ) -> Result < Self , Self :: Error > {
712
732
// Moves the content of the CString
713
733
// Also check if it's valid UTF-8
714
- assert ! ( s. to_str( ) . is_ok ( ) ) ;
715
- Self ( Inner :: Native ( Some ( s) ) )
734
+ s. to_str ( ) ? ;
735
+ Ok ( Self ( Inner :: Native ( Some ( s) ) ) )
716
736
}
717
737
}
718
738
719
- impl From < & CStr > for GString {
739
+ impl TryFrom < & CStr > for GString {
740
+ type Error = std:: str:: Utf8Error ;
720
741
#[ 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 ( )
742
+ fn try_from ( c : & CStr ) -> Result < Self , Self :: Error > {
743
+ c. to_owned ( ) . try_into ( )
725
744
}
726
745
}
727
746
@@ -772,7 +791,7 @@ impl FromGlibPtrNone<*const u8> for GString {
772
791
assert ! ( !ptr. is_null( ) ) ;
773
792
let cstr = CStr :: from_ptr ( ptr as * const _ ) ;
774
793
// Also check if it's valid UTF-8
775
- cstr. to_str ( ) . unwrap ( ) . into ( )
794
+ cstr. try_into ( ) . unwrap ( )
776
795
}
777
796
}
778
797
@@ -904,16 +923,16 @@ impl<'a> ToGlibPtr<'a, *mut i8> for GString {
904
923
impl < ' a > FromGlibContainer < * const c_char , * const i8 > for GString {
905
924
unsafe fn from_glib_none_num ( ptr : * const i8 , num : usize ) -> Self {
906
925
if num == 0 || ptr. is_null ( ) {
907
- return Self :: from ( "" ) ;
926
+ return Self :: try_from ( "" ) . unwrap ( ) ;
908
927
}
909
928
let slice = slice:: from_raw_parts ( ptr as * const u8 , num) ;
910
929
// Also check if it's valid UTF-8
911
- std:: str:: from_utf8 ( slice) . unwrap ( ) . into ( )
930
+ std:: str:: from_utf8 ( slice) . unwrap ( ) . try_into ( ) . unwrap ( )
912
931
}
913
932
914
933
unsafe fn from_glib_container_num ( ptr : * const i8 , num : usize ) -> Self {
915
934
if num == 0 || ptr. is_null ( ) {
916
- return Self :: from ( "" ) ;
935
+ return Self :: try_from ( "" ) . unwrap ( ) ;
917
936
}
918
937
919
938
// Check if it's valid UTF-8
@@ -928,7 +947,7 @@ impl<'a> FromGlibContainer<*const c_char, *const i8> for GString {
928
947
929
948
unsafe fn from_glib_full_num ( ptr : * const i8 , num : usize ) -> Self {
930
949
if num == 0 || ptr. is_null ( ) {
931
- return Self :: from ( "" ) ;
950
+ return Self :: try_from ( "" ) . unwrap ( ) ;
932
951
}
933
952
934
953
// Check if it's valid UTF-8
@@ -1007,7 +1026,7 @@ unsafe impl<'a> crate::value::FromValue<'a> for GString {
1007
1026
type Checker = crate :: value:: GenericValueTypeOrNoneChecker < Self > ;
1008
1027
1009
1028
unsafe fn from_value ( value : & ' a crate :: Value ) -> Self {
1010
- Self :: from ( <& str >:: from_value ( value) )
1029
+ Self :: try_from ( <& str >:: from_value ( value) ) . unwrap ( )
1011
1030
}
1012
1031
}
1013
1032
@@ -1097,15 +1116,15 @@ mod tests {
1097
1116
1098
1117
#[ test]
1099
1118
fn test_gstring_from_str ( ) {
1100
- let gstring: GString = "foo" . into ( ) ;
1119
+ let gstring: GString = "foo" . try_into ( ) . unwrap ( ) ;
1101
1120
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1102
1121
let foo: Box < str > = gstring. into ( ) ;
1103
1122
assert_eq ! ( foo. as_ref( ) , "foo" ) ;
1104
1123
}
1105
1124
1106
1125
#[ test]
1107
1126
fn test_string_from_gstring ( ) {
1108
- let gstring = GString :: from ( "foo" ) ;
1127
+ let gstring = GString :: try_from ( "foo" ) . unwrap ( ) ;
1109
1128
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1110
1129
let s = String :: from ( gstring) ;
1111
1130
assert_eq ! ( s, "foo" ) ;
@@ -1114,7 +1133,7 @@ mod tests {
1114
1133
#[ test]
1115
1134
fn test_gstring_from_cstring ( ) {
1116
1135
let cstr = CString :: new ( "foo" ) . unwrap ( ) ;
1117
- let gstring = GString :: from ( cstr) ;
1136
+ let gstring = GString :: try_from ( cstr) . unwrap ( ) ;
1118
1137
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1119
1138
let foo: Box < str > = gstring. into ( ) ;
1120
1139
assert_eq ! ( foo. as_ref( ) , "foo" ) ;
@@ -1123,7 +1142,7 @@ mod tests {
1123
1142
#[ test]
1124
1143
fn test_string_from_gstring_from_cstring ( ) {
1125
1144
let cstr = CString :: new ( "foo" ) . unwrap ( ) ;
1126
- let gstring = GString :: from ( cstr) ;
1145
+ let gstring = GString :: try_from ( cstr) . unwrap ( ) ;
1127
1146
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1128
1147
let s = String :: from ( gstring) ;
1129
1148
assert_eq ! ( s, "foo" ) ;
@@ -1132,7 +1151,7 @@ mod tests {
1132
1151
#[ test]
1133
1152
fn test_vec_u8_to_gstring ( ) {
1134
1153
let v: & [ u8 ] = b"foo" ;
1135
- let s: GString = Vec :: from ( v) . into ( ) ;
1154
+ let s: GString = Vec :: from ( v) . try_into ( ) . unwrap ( ) ;
1136
1155
assert_eq ! ( s. as_str( ) , "foo" ) ;
1137
1156
}
1138
1157
@@ -1165,11 +1184,11 @@ mod tests {
1165
1184
fn test_hashmap ( ) {
1166
1185
use std:: collections:: HashMap ;
1167
1186
1168
- let gstring = GString :: from ( "foo" ) ;
1187
+ let gstring = GString :: try_from ( "foo" ) . unwrap ( ) ;
1169
1188
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1170
1189
let mut h: HashMap < GString , i32 > = HashMap :: new ( ) ;
1171
1190
h. insert ( gstring, 42 ) ;
1172
- let gstring: GString = "foo" . into ( ) ;
1191
+ let gstring: GString = "foo" . try_into ( ) . unwrap ( ) ;
1173
1192
assert ! ( h. contains_key( & gstring) ) ;
1174
1193
}
1175
1194
}
0 commit comments