@@ -435,7 +435,7 @@ impl GString {
435
435
436
436
impl Clone for GString {
437
437
fn clone ( & self ) -> GString {
438
- self . as_str ( ) . into ( )
438
+ self . as_gstr ( ) . to_owned ( )
439
439
}
440
440
}
441
441
@@ -445,9 +445,9 @@ impl fmt::Debug for GString {
445
445
}
446
446
}
447
447
448
- impl Drop for GString {
448
+ impl Drop for Inner {
449
449
fn drop ( & mut self ) {
450
- if let Inner :: Foreign { ptr, .. } = self . 0 {
450
+ if let Inner :: Foreign { ptr, .. } = self {
451
451
unsafe {
452
452
ffi:: g_free ( ptr. as_ptr ( ) as * mut _ ) ;
453
453
}
@@ -660,23 +660,23 @@ impl From<GString> for Box<str> {
660
660
}
661
661
}
662
662
663
- impl From < String > for GString {
663
+ impl TryFrom < String > for GString {
664
+ type Error = std:: ffi:: NulError ;
664
665
#[ inline]
665
- fn from ( s : String ) -> Self {
666
+ fn try_from ( s : String ) -> Result < Self , Self :: Error > {
666
667
// Moves the content of the String
667
- unsafe {
668
- // No check for valid UTF-8 here
669
- let cstr = CString :: from_vec_unchecked ( s. into_bytes ( ) ) ;
670
- GString ( Inner :: Native ( Some ( cstr) ) )
671
- }
668
+ // Check for interior nul bytes
669
+ let cstr = CString :: new ( s. into_bytes ( ) ) ?;
670
+ Ok ( GString ( Inner :: Native ( Some ( cstr) ) ) )
672
671
}
673
672
}
674
673
675
- impl From < Box < str > > for GString {
674
+ impl TryFrom < Box < str > > for GString {
675
+ type Error = std:: ffi:: NulError ;
676
676
#[ inline]
677
- fn from ( s : Box < str > ) -> Self {
677
+ fn try_from ( s : Box < str > ) -> Result < Self , Self :: Error > {
678
678
// Moves the content of the String
679
- s. into_string ( ) . into ( )
679
+ s. into_string ( ) . try_into ( )
680
680
}
681
681
}
682
682
@@ -687,50 +687,68 @@ impl From<&GStr> for GString {
687
687
}
688
688
}
689
689
690
- impl From < & str > for GString {
690
+ impl TryFrom < & str > for GString {
691
+ type Error = std:: ffi:: FromBytesWithNulError ;
691
692
#[ inline]
692
- fn from ( s : & str ) -> Self {
693
+ fn try_from ( s : & str ) -> Result < Self , Self :: Error > {
693
694
// Allocates with the GLib allocator
694
695
unsafe {
695
696
// No check for valid UTF-8 here
696
697
let copy = ffi:: g_malloc ( s. len ( ) + 1 ) as * mut c_char ;
697
698
ptr:: copy_nonoverlapping ( s. as_ptr ( ) as * const c_char , copy, s. len ( ) + 1 ) ;
698
699
ptr:: write ( copy. add ( s. len ( ) ) , 0 ) ;
699
700
700
- GString ( Inner :: Foreign {
701
+ let inner = Inner :: Foreign {
701
702
ptr : ptr:: NonNull :: new_unchecked ( copy) ,
702
703
len : s. len ( ) ,
703
- } )
704
+ } ;
705
+
706
+ // Check for interior nul bytes
707
+ std:: ffi:: CStr :: from_bytes_with_nul ( std:: slice:: from_raw_parts (
708
+ copy as * const _ ,
709
+ s. len ( ) + 1 ,
710
+ ) ) ?;
711
+
712
+ Ok ( GString ( inner) )
704
713
}
705
714
}
706
715
}
707
716
708
- impl From < Vec < u8 > > for GString {
717
+ #[ derive( thiserror:: Error , Debug ) ]
718
+ pub enum GStringError {
719
+ #[ error( "invalid UTF-8" ) ]
720
+ Utf8 ( #[ from] std:: str:: Utf8Error ) ,
721
+ #[ error( "interior nul bytes" ) ]
722
+ Nul ( #[ from] std:: ffi:: NulError ) ,
723
+ }
724
+
725
+ impl TryFrom < Vec < u8 > > for GString {
726
+ type Error = GStringError ;
709
727
#[ inline]
710
- fn from ( s : Vec < u8 > ) -> Self {
728
+ fn try_from ( s : Vec < u8 > ) -> Result < Self , Self :: Error > {
711
729
// Moves the content of the Vec
712
- // Also check if it's valid UTF-8
713
- let cstring = CString :: new ( s) . expect ( "CString::new failed" ) ;
714
- cstring. into ( )
730
+ // Also check if it's valid UTF-8 and has no interior nuls
731
+ let cstring = CString :: new ( s) ? ;
732
+ Ok ( cstring. try_into ( ) ? )
715
733
}
716
734
}
717
735
718
- impl From < CString > for GString {
719
- # [ inline ]
720
- fn from ( s : CString ) -> Self {
736
+ impl TryFrom < CString > for GString {
737
+ type Error = std :: str :: Utf8Error ;
738
+ fn try_from ( s : CString ) -> Result < Self , Self :: Error > {
721
739
// Moves the content of the CString
722
740
// Also check if it's valid UTF-8
723
- assert ! ( s. to_str( ) . is_ok ( ) ) ;
724
- Self ( Inner :: Native ( Some ( s) ) )
741
+ s. to_str ( ) ? ;
742
+ Ok ( Self ( Inner :: Native ( Some ( s) ) ) )
725
743
}
726
744
}
727
745
728
- impl From < & CStr > for GString {
746
+ impl TryFrom < & CStr > for GString {
747
+ type Error = std:: str:: Utf8Error ;
729
748
#[ inline]
730
- fn from ( c : & CStr ) -> Self {
731
- // Creates a copy with the GLib allocator
732
- // Also check if it's valid UTF-8
733
- c. to_str ( ) . unwrap ( ) . into ( )
749
+ fn try_from ( c : & CStr ) -> Result < Self , Self :: Error > {
750
+ let g: & GStr = c. try_into ( ) ?;
751
+ Ok ( g. to_owned ( ) )
734
752
}
735
753
}
736
754
@@ -781,7 +799,7 @@ impl FromGlibPtrNone<*const u8> for GString {
781
799
assert ! ( !ptr. is_null( ) ) ;
782
800
let cstr = CStr :: from_ptr ( ptr as * const _ ) ;
783
801
// Also check if it's valid UTF-8
784
- cstr. to_str ( ) . unwrap ( ) . into ( )
802
+ cstr. try_into ( ) . unwrap ( )
785
803
}
786
804
}
787
805
@@ -913,16 +931,16 @@ impl<'a> ToGlibPtr<'a, *mut i8> for GString {
913
931
impl < ' a > FromGlibContainer < * const c_char , * const i8 > for GString {
914
932
unsafe fn from_glib_none_num ( ptr : * const i8 , num : usize ) -> Self {
915
933
if num == 0 || ptr. is_null ( ) {
916
- return Self :: from ( "" ) ;
934
+ return Self :: try_from ( "" ) . unwrap ( ) ;
917
935
}
918
936
let slice = slice:: from_raw_parts ( ptr as * const u8 , num) ;
919
937
// Also check if it's valid UTF-8
920
- std:: str:: from_utf8 ( slice) . unwrap ( ) . into ( )
938
+ std:: str:: from_utf8 ( slice) . unwrap ( ) . try_into ( ) . unwrap ( )
921
939
}
922
940
923
941
unsafe fn from_glib_container_num ( ptr : * const i8 , num : usize ) -> Self {
924
942
if num == 0 || ptr. is_null ( ) {
925
- return Self :: from ( "" ) ;
943
+ return Self :: try_from ( "" ) . unwrap ( ) ;
926
944
}
927
945
928
946
// Check if it's valid UTF-8
@@ -937,7 +955,7 @@ impl<'a> FromGlibContainer<*const c_char, *const i8> for GString {
937
955
938
956
unsafe fn from_glib_full_num ( ptr : * const i8 , num : usize ) -> Self {
939
957
if num == 0 || ptr. is_null ( ) {
940
- return Self :: from ( "" ) ;
958
+ return Self :: try_from ( "" ) . unwrap ( ) ;
941
959
}
942
960
943
961
// Check if it's valid UTF-8
@@ -1016,7 +1034,7 @@ unsafe impl<'a> crate::value::FromValue<'a> for GString {
1016
1034
type Checker = crate :: value:: GenericValueTypeOrNoneChecker < Self > ;
1017
1035
1018
1036
unsafe fn from_value ( value : & ' a crate :: Value ) -> Self {
1019
- Self :: from ( <& str >:: from_value ( value) )
1037
+ Self :: try_from ( <& str >:: from_value ( value) ) . unwrap ( )
1020
1038
}
1021
1039
}
1022
1040
@@ -1106,15 +1124,15 @@ mod tests {
1106
1124
1107
1125
#[ test]
1108
1126
fn test_gstring_from_str ( ) {
1109
- let gstring: GString = "foo" . into ( ) ;
1127
+ let gstring: GString = "foo" . try_into ( ) . unwrap ( ) ;
1110
1128
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1111
1129
let foo: Box < str > = gstring. into ( ) ;
1112
1130
assert_eq ! ( foo. as_ref( ) , "foo" ) ;
1113
1131
}
1114
1132
1115
1133
#[ test]
1116
1134
fn test_string_from_gstring ( ) {
1117
- let gstring = GString :: from ( "foo" ) ;
1135
+ let gstring = GString :: try_from ( "foo" ) . unwrap ( ) ;
1118
1136
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1119
1137
let s = String :: from ( gstring) ;
1120
1138
assert_eq ! ( s, "foo" ) ;
@@ -1123,7 +1141,7 @@ mod tests {
1123
1141
#[ test]
1124
1142
fn test_gstring_from_cstring ( ) {
1125
1143
let cstr = CString :: new ( "foo" ) . unwrap ( ) ;
1126
- let gstring = GString :: from ( cstr) ;
1144
+ let gstring = GString :: try_from ( cstr) . unwrap ( ) ;
1127
1145
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1128
1146
let foo: Box < str > = gstring. into ( ) ;
1129
1147
assert_eq ! ( foo. as_ref( ) , "foo" ) ;
@@ -1132,7 +1150,7 @@ mod tests {
1132
1150
#[ test]
1133
1151
fn test_string_from_gstring_from_cstring ( ) {
1134
1152
let cstr = CString :: new ( "foo" ) . unwrap ( ) ;
1135
- let gstring = GString :: from ( cstr) ;
1153
+ let gstring = GString :: try_from ( cstr) . unwrap ( ) ;
1136
1154
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1137
1155
let s = String :: from ( gstring) ;
1138
1156
assert_eq ! ( s, "foo" ) ;
@@ -1141,7 +1159,7 @@ mod tests {
1141
1159
#[ test]
1142
1160
fn test_vec_u8_to_gstring ( ) {
1143
1161
let v: & [ u8 ] = b"foo" ;
1144
- let s: GString = Vec :: from ( v) . into ( ) ;
1162
+ let s: GString = Vec :: from ( v) . try_into ( ) . unwrap ( ) ;
1145
1163
assert_eq ! ( s. as_str( ) , "foo" ) ;
1146
1164
}
1147
1165
@@ -1174,11 +1192,11 @@ mod tests {
1174
1192
fn test_hashmap ( ) {
1175
1193
use std:: collections:: HashMap ;
1176
1194
1177
- let gstring = GString :: from ( "foo" ) ;
1195
+ let gstring = GString :: try_from ( "foo" ) . unwrap ( ) ;
1178
1196
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1179
1197
let mut h: HashMap < GString , i32 > = HashMap :: new ( ) ;
1180
1198
h. insert ( gstring, 42 ) ;
1181
- let gstring: GString = "foo" . into ( ) ;
1199
+ let gstring: GString = "foo" . try_into ( ) . unwrap ( ) ;
1182
1200
assert ! ( h. contains_key( & gstring) ) ;
1183
1201
}
1184
1202
}
0 commit comments