@@ -114,12 +114,26 @@ impl std::borrow::Borrow<[GStringPtr]> for StrV {
114114 }
115115}
116116
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+
117131impl std:: ops:: Deref for StrV {
118- type Target = [ GStringPtr ] ;
132+ type Target = CStrV ;
119133
120134 #[ inline]
121- fn deref ( & self ) -> & [ GStringPtr ] {
122- self . as_slice ( )
135+ fn deref ( & self ) -> & CStrV {
136+ self . into ( )
123137 }
124138}
125139
@@ -1359,6 +1373,208 @@ impl<const N: usize> IntoStrV for [&'_ String; N] {
13591373 }
13601374}
13611375
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+
13621578#[ cfg( test) ]
13631579mod test {
13641580 use super :: * ;
0 commit comments