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