@@ -4,15 +4,15 @@ use crate::translate::*;
4
4
use crate :: types:: { StaticType , Type } ;
5
5
use crate :: value:: { FromValue , ToValue } ;
6
6
use crate :: Value ;
7
- use std:: borrow:: Borrow ;
7
+ use std:: borrow:: { Borrow , Cow } ;
8
8
use std:: cmp:: Ordering ;
9
- use std:: ffi:: { CStr , CString , OsStr } ;
9
+ use std:: ffi:: { CStr , CString , OsStr , OsString } ;
10
10
use std:: fmt;
11
11
use std:: hash;
12
12
use std:: mem;
13
13
use std:: ops:: Deref ;
14
14
use std:: os:: raw:: { c_char, c_void} ;
15
- use std:: path:: Path ;
15
+ use std:: path:: { Path , PathBuf } ;
16
16
use std:: ptr;
17
17
use std:: slice;
18
18
use std:: string:: String ;
@@ -327,6 +327,13 @@ impl<'a> TryFrom<&'a CStr> for &'a GStr {
327
327
}
328
328
}
329
329
330
+ impl < ' a > From < & ' a GStr > for Cow < ' a , GStr > {
331
+ #[ inline]
332
+ fn from ( s : & ' a GStr ) -> Self {
333
+ Cow :: Borrowed ( s)
334
+ }
335
+ }
336
+
330
337
impl PartialEq < GStr > for String {
331
338
fn eq ( & self , other : & GStr ) -> bool {
332
339
self . as_str ( ) == other. as_str ( )
@@ -1232,6 +1239,42 @@ impl From<GString> for Box<str> {
1232
1239
}
1233
1240
}
1234
1241
1242
+ impl From < GString > for Vec < u8 > {
1243
+ #[ inline]
1244
+ fn from ( value : GString ) -> Vec < u8 > {
1245
+ value. into_bytes_with_nul ( )
1246
+ }
1247
+ }
1248
+
1249
+ impl TryFrom < GString > for CString {
1250
+ type Error = GStringInteriorNulError < GString > ;
1251
+ #[ inline]
1252
+ fn try_from ( value : GString ) -> Result < Self , Self :: Error > {
1253
+ if let Some ( nul_pos) = memchr:: memchr ( 0 , value. as_bytes ( ) ) {
1254
+ return Err ( GStringInteriorNulError (
1255
+ value,
1256
+ GStrInteriorNulError ( nul_pos) ,
1257
+ ) ) ;
1258
+ }
1259
+ let v = value. into_bytes_with_nul ( ) ;
1260
+ Ok ( unsafe { CString :: from_vec_with_nul_unchecked ( v) } )
1261
+ }
1262
+ }
1263
+
1264
+ impl From < GString > for OsString {
1265
+ #[ inline]
1266
+ fn from ( s : GString ) -> Self {
1267
+ OsString :: from ( String :: from ( s) )
1268
+ }
1269
+ }
1270
+
1271
+ impl From < GString > for PathBuf {
1272
+ #[ inline]
1273
+ fn from ( s : GString ) -> Self {
1274
+ PathBuf :: from ( OsString :: from ( s) )
1275
+ }
1276
+ }
1277
+
1235
1278
impl From < String > for GString {
1236
1279
#[ inline]
1237
1280
fn from ( mut s : String ) -> Self {
@@ -1258,6 +1301,16 @@ impl From<Box<str>> for GString {
1258
1301
}
1259
1302
}
1260
1303
1304
+ impl < ' a > From < Cow < ' a , str > > for GString {
1305
+ #[ inline]
1306
+ fn from ( s : Cow < ' a , str > ) -> Self {
1307
+ match s {
1308
+ Cow :: Borrowed ( s) => Self :: from ( s) ,
1309
+ Cow :: Owned ( s) => Self :: from ( s) ,
1310
+ }
1311
+ }
1312
+ }
1313
+
1261
1314
impl From < & GStr > for GString {
1262
1315
#[ inline]
1263
1316
fn from ( s : & GStr ) -> GString {
@@ -1286,22 +1339,73 @@ impl From<&str> for GString {
1286
1339
}
1287
1340
}
1288
1341
1289
- impl From < CString > for GString {
1342
+ impl TryFrom < CString > for GString {
1343
+ type Error = GStringUtf8Error < CString > ;
1290
1344
#[ inline]
1291
- fn from ( s : CString ) -> Self {
1292
- // Moves the content of the CString
1293
- // Also check if it's valid UTF-8
1294
- let s = String :: from_utf8 ( s. into_bytes_with_nul ( ) ) . unwrap ( ) ;
1295
- Self ( Inner :: Native ( Some ( s. into_boxed_str ( ) ) ) )
1345
+ fn try_from ( value : CString ) -> Result < Self , Self :: Error > {
1346
+ if value. as_bytes ( ) . is_empty ( ) {
1347
+ Ok ( Self ( Inner :: Native ( None ) ) )
1348
+ } else {
1349
+ // Moves the content of the CString
1350
+ // Also check if it's valid UTF-8
1351
+ let s = String :: from_utf8 ( value. into_bytes_with_nul ( ) ) . map_err ( |e| {
1352
+ let err = e. utf8_error ( ) ;
1353
+ GStringUtf8Error (
1354
+ unsafe { CString :: from_vec_with_nul_unchecked ( e. into_bytes ( ) ) } ,
1355
+ err,
1356
+ )
1357
+ } ) ?;
1358
+ Ok ( Self ( Inner :: Native ( Some ( s. into ( ) ) ) ) )
1359
+ }
1296
1360
}
1297
1361
}
1298
1362
1299
- impl From < & CStr > for GString {
1363
+ impl TryFrom < OsString > for GString {
1364
+ type Error = GStringFromError < OsString > ;
1300
1365
#[ inline]
1301
- fn from ( c : & CStr ) -> Self {
1302
- // Creates a copy with the GLib allocator
1303
- // Also check if it's valid UTF-8
1304
- c. to_str ( ) . unwrap ( ) . into ( )
1366
+ fn try_from ( value : OsString ) -> Result < Self , Self :: Error > {
1367
+ Self :: from_string_checked ( value. into_string ( ) . map_err ( GStringFromError :: Unspecified ) ?)
1368
+ . map_err ( |e| GStringFromError :: from ( e) . convert ( OsString :: from) )
1369
+ }
1370
+ }
1371
+
1372
+ impl TryFrom < PathBuf > for GString {
1373
+ type Error = GStringFromError < PathBuf > ;
1374
+ #[ inline]
1375
+ fn try_from ( value : PathBuf ) -> Result < Self , Self :: Error > {
1376
+ GString :: try_from ( value. into_os_string ( ) ) . map_err ( |e| e. convert ( PathBuf :: from) )
1377
+ }
1378
+ }
1379
+
1380
+ impl TryFrom < & CStr > for GString {
1381
+ type Error = std:: str:: Utf8Error ;
1382
+ #[ inline]
1383
+ fn try_from ( value : & CStr ) -> Result < Self , Self :: Error > {
1384
+ // Check if it's valid UTF-8
1385
+ value. to_str ( ) ?;
1386
+ let gstr = unsafe { GStr :: from_utf8_with_nul_unchecked ( value. to_bytes_with_nul ( ) ) } ;
1387
+ Ok ( gstr. to_owned ( ) )
1388
+ }
1389
+ }
1390
+
1391
+ impl < ' a > From < Cow < ' a , GStr > > for GString {
1392
+ #[ inline]
1393
+ fn from ( s : Cow < ' a , GStr > ) -> Self {
1394
+ s. into_owned ( )
1395
+ }
1396
+ }
1397
+
1398
+ impl < ' a > From < GString > for Cow < ' a , GStr > {
1399
+ #[ inline]
1400
+ fn from ( s : GString ) -> Self {
1401
+ Cow :: Owned ( s)
1402
+ }
1403
+ }
1404
+
1405
+ impl < ' a > From < & ' a GString > for Cow < ' a , GStr > {
1406
+ #[ inline]
1407
+ fn from ( s : & ' a GString ) -> Self {
1408
+ Cow :: Borrowed ( s. as_gstr ( ) )
1305
1409
}
1306
1410
}
1307
1411
@@ -1699,7 +1803,7 @@ mod tests {
1699
1803
#[ test]
1700
1804
fn test_gstring_from_cstring ( ) {
1701
1805
let cstr = CString :: new ( "foo" ) . unwrap ( ) ;
1702
- let gstring = GString :: from ( cstr) ;
1806
+ let gstring = GString :: try_from ( cstr) . unwrap ( ) ;
1703
1807
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1704
1808
let foo: Box < str > = gstring. into ( ) ;
1705
1809
assert_eq ! ( foo. as_ref( ) , "foo" ) ;
@@ -1708,7 +1812,7 @@ mod tests {
1708
1812
#[ test]
1709
1813
fn test_string_from_gstring_from_cstring ( ) {
1710
1814
let cstr = CString :: new ( "foo" ) . unwrap ( ) ;
1711
- let gstring = GString :: from ( cstr) ;
1815
+ let gstring = GString :: try_from ( cstr) . unwrap ( ) ;
1712
1816
assert_eq ! ( gstring. as_str( ) , "foo" ) ;
1713
1817
let s = String :: from ( gstring) ;
1714
1818
assert_eq ! ( s, "foo" ) ;
0 commit comments