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