@@ -114,12 +114,26 @@ impl std::borrow::Borrow<[GStringPtr]> for StrV {
114
114
}
115
115
}
116
116
117
+ impl AsRef < CStrV > for StrV {
118
+ #[ inline]
119
+ fn as_ref ( & self ) -> & CStrV {
120
+ self . into ( )
121
+ }
122
+ }
123
+
124
+ impl std:: borrow:: Borrow < CStrV > for StrV {
125
+ #[ inline]
126
+ fn borrow ( & self ) -> & CStrV {
127
+ self . into ( )
128
+ }
129
+ }
130
+
117
131
impl std:: ops:: Deref for StrV {
118
- type Target = [ GStringPtr ] ;
132
+ type Target = CStrV ;
119
133
120
134
#[ inline]
121
- fn deref ( & self ) -> & [ GStringPtr ] {
122
- self . as_slice ( )
135
+ fn deref ( & self ) -> & CStrV {
136
+ self . into ( )
123
137
}
124
138
}
125
139
@@ -1359,6 +1373,208 @@ impl<const N: usize> IntoStrV for [&'_ String; N] {
1359
1373
}
1360
1374
}
1361
1375
1376
+ // rustdoc-stripper-ignore-next
1377
+ /// Representation of a borrowed `NULL`-terminated C array of `NULL`-terminated UTF-8 strings.
1378
+ ///
1379
+ /// It can be constructed safely from a `&StrV` and unsafely from a pointer to a C array.
1380
+ /// This type is very similar to `[GStringPtr]`, but with one added constraint: the underlying C array must be `NULL`-terminated.
1381
+ #[ repr( transparent) ]
1382
+ pub struct CStrV {
1383
+ inner : [ GStringPtr ] ,
1384
+ }
1385
+
1386
+ impl CStrV {
1387
+ // rustdoc-stripper-ignore-next
1388
+ /// Borrows a C array.
1389
+ /// # Safety
1390
+ ///
1391
+ /// The provided pointer **must** be `NULL`-terminated. It is undefined behavior to
1392
+ /// pass a pointer that does not uphold this condition.
1393
+ #[ inline]
1394
+ pub unsafe fn from_glib_borrow < ' a > ( ptr : * const * const c_char ) -> & ' a CStrV {
1395
+ let slice = StrV :: from_glib_borrow ( ptr) ;
1396
+ & * ( slice as * const [ GStringPtr ] as * const CStrV )
1397
+ }
1398
+
1399
+ // rustdoc-stripper-ignore-next
1400
+ /// Borrows a C array.
1401
+ /// # Safety
1402
+ ///
1403
+ /// The provided pointer **must** be `NULL`-terminated. It is undefined behavior to
1404
+ /// pass a pointer that does not uphold this condition.
1405
+ #[ inline]
1406
+ pub unsafe fn from_glib_borrow_num < ' a > ( ptr : * const * const c_char , len : usize ) -> & ' a CStrV {
1407
+ let slice = StrV :: from_glib_borrow_num ( ptr, len) ;
1408
+ & * ( slice as * const [ GStringPtr ] as * const CStrV )
1409
+ }
1410
+
1411
+ // rustdoc-stripper-ignore-next
1412
+ /// Returns the underlying pointer.
1413
+ ///
1414
+ /// This is guaranteed to be nul-terminated.
1415
+ #[ inline]
1416
+ pub const fn as_ptr ( & self ) -> * const * const c_char {
1417
+ self . inner . as_ptr ( ) as * const * const _
1418
+ }
1419
+ }
1420
+
1421
+ impl fmt:: Debug for CStrV {
1422
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1423
+ self . inner . fmt ( f)
1424
+ }
1425
+ }
1426
+
1427
+ unsafe impl Send for CStrV { }
1428
+
1429
+ unsafe impl Sync for CStrV { }
1430
+
1431
+ impl PartialEq for CStrV {
1432
+ #[ inline]
1433
+ fn eq ( & self , other : & Self ) -> bool {
1434
+ self . inner == other. inner
1435
+ }
1436
+ }
1437
+
1438
+ impl Eq for CStrV { }
1439
+
1440
+ impl PartialOrd for CStrV {
1441
+ #[ inline]
1442
+ fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
1443
+ Some ( self . cmp ( other) )
1444
+ }
1445
+ }
1446
+
1447
+ impl Ord for CStrV {
1448
+ fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
1449
+ self . inner . cmp ( & other. inner )
1450
+ }
1451
+ }
1452
+
1453
+ impl std:: hash:: Hash for CStrV {
1454
+ #[ inline]
1455
+ fn hash < H : std:: hash:: Hasher > ( & self , state : & mut H ) {
1456
+ self . inner . hash ( state)
1457
+ }
1458
+ }
1459
+
1460
+ impl PartialEq < [ & ' _ str ] > for CStrV {
1461
+ fn eq ( & self , other : & [ & ' _ str ] ) -> bool {
1462
+ for ( a, b) in Iterator :: zip ( self . iter ( ) , other. iter ( ) ) {
1463
+ if a != b {
1464
+ return false ;
1465
+ }
1466
+ }
1467
+
1468
+ true
1469
+ }
1470
+ }
1471
+
1472
+ impl PartialEq < CStrV > for [ & ' _ str ] {
1473
+ #[ inline]
1474
+ fn eq ( & self , other : & CStrV ) -> bool {
1475
+ other. eq ( self )
1476
+ }
1477
+ }
1478
+
1479
+ impl Default for & CStrV {
1480
+ #[ inline]
1481
+ fn default ( ) -> Self {
1482
+ const SLICE : & [ * const c_char ] = & [ ptr:: null ( ) ] ;
1483
+ // SAFETY: `SLICE` is indeed a valid nul-terminated array.
1484
+ unsafe { CStrV :: from_glib_borrow ( SLICE . as_ptr ( ) ) }
1485
+ }
1486
+ }
1487
+
1488
+ impl std:: ops:: Deref for CStrV {
1489
+ type Target = [ GStringPtr ] ;
1490
+
1491
+ #[ inline]
1492
+ fn deref ( & self ) -> & [ GStringPtr ] {
1493
+ & self . inner
1494
+ }
1495
+ }
1496
+
1497
+ impl < ' a > std:: iter:: IntoIterator for & ' a CStrV {
1498
+ type Item = & ' a GStringPtr ;
1499
+ type IntoIter = std:: slice:: Iter < ' a , GStringPtr > ;
1500
+
1501
+ #[ inline]
1502
+ fn into_iter ( self ) -> Self :: IntoIter {
1503
+ self . inner . iter ( )
1504
+ }
1505
+ }
1506
+
1507
+ impl < ' a > From < & ' a StrV > for & ' a CStrV {
1508
+ fn from ( value : & ' a StrV ) -> Self {
1509
+ let slice = value. as_slice ( ) ;
1510
+ // Safety: `&StrV` is a null-terminated C array of nul-terminated UTF-8 strings,
1511
+ // therefore `&StrV::as_slice()` return a a null-terminated slice of nul-terminated UTF-8 strings,
1512
+ // thus it is safe to convert it to `&CStr`.
1513
+ unsafe { & * ( slice as * const [ GStringPtr ] as * const CStrV ) }
1514
+ }
1515
+ }
1516
+
1517
+ impl FromGlibContainer < * mut c_char , * const * const c_char > for & CStrV {
1518
+ unsafe fn from_glib_none_num ( ptr : * const * const c_char , num : usize ) -> Self {
1519
+ CStrV :: from_glib_borrow_num ( ptr, num)
1520
+ }
1521
+
1522
+ unsafe fn from_glib_container_num ( _ptr : * const * const c_char , _num : usize ) -> Self {
1523
+ unimplemented ! ( ) ;
1524
+ }
1525
+
1526
+ unsafe fn from_glib_full_num ( _ptr : * const * const c_char , _num : usize ) -> Self {
1527
+ unimplemented ! ( ) ;
1528
+ }
1529
+ }
1530
+
1531
+ impl FromGlibPtrContainer < * mut c_char , * const * const c_char > for & CStrV {
1532
+ #[ inline]
1533
+ unsafe fn from_glib_none ( ptr : * const * const c_char ) -> Self {
1534
+ CStrV :: from_glib_borrow ( ptr)
1535
+ }
1536
+
1537
+ unsafe fn from_glib_container ( _ptr : * const * const c_char ) -> Self {
1538
+ unimplemented ! ( ) ;
1539
+ }
1540
+
1541
+ unsafe fn from_glib_full ( _ptr : * const * const c_char ) -> Self {
1542
+ unimplemented ! ( ) ;
1543
+ }
1544
+ }
1545
+
1546
+ impl < ' a > ToGlibPtr < ' a , * const * const c_char > for CStrV {
1547
+ type Storage = PhantomData < & ' a Self > ;
1548
+
1549
+ #[ inline]
1550
+ fn to_glib_none ( & ' a self ) -> Stash < ' a , * const * const c_char , Self > {
1551
+ Stash ( self . as_ptr ( ) , PhantomData )
1552
+ }
1553
+ }
1554
+
1555
+ impl IntoGlibPtr < * const * const c_char > for & CStrV {
1556
+ #[ inline]
1557
+ fn into_glib_ptr ( self ) -> * const * const c_char {
1558
+ self . as_ptr ( )
1559
+ }
1560
+ }
1561
+
1562
+ impl StaticType for CStrV {
1563
+ #[ inline]
1564
+ fn static_type ( ) -> crate :: Type {
1565
+ <Vec < String > >:: static_type ( )
1566
+ }
1567
+ }
1568
+
1569
+ unsafe impl < ' a > crate :: value:: FromValue < ' a > for & ' a CStrV {
1570
+ type Checker = crate :: value:: GenericValueTypeChecker < Self > ;
1571
+
1572
+ unsafe fn from_value ( value : & ' a crate :: value:: Value ) -> Self {
1573
+ let ptr = gobject_ffi:: g_value_get_boxed ( value. to_glib_none ( ) . 0 ) as * const * const c_char ;
1574
+ CStrV :: from_glib_borrow ( ptr)
1575
+ }
1576
+ }
1577
+
1362
1578
#[ cfg( test) ]
1363
1579
mod test {
1364
1580
use super :: * ;
0 commit comments