Skip to content

Commit f56c2b3

Browse files
committed
Add glib::CStrV
This type represents a borrowed reference to a `NULL`-terminated array of `NULL`-terminated UTF-8 strings. Signed-off-by: fbrouille <fbrouille@users.noreply.github.com>
1 parent 63875ab commit f56c2b3

File tree

3 files changed

+59
-2
lines changed

3 files changed

+59
-2
lines changed

glib/src/collections/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ pub mod slist;
1313
pub use slist::SList;
1414

1515
pub mod strv;
16-
pub use strv::StrV;
16+
pub use strv::{CStrV, StrV};

glib/src/collections/strv.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,20 @@ impl std::ops::Deref for StrV {
123123
}
124124
}
125125

126+
impl AsRef<CStrV> for StrV {
127+
#[inline]
128+
fn as_ref(&self) -> &CStrV {
129+
self.into()
130+
}
131+
}
132+
133+
impl std::borrow::Borrow<CStrV> for StrV {
134+
#[inline]
135+
fn borrow(&self) -> &CStrV {
136+
self.into()
137+
}
138+
}
139+
126140
impl std::iter::Extend<GString> for StrV {
127141
#[inline]
128142
fn extend<I: IntoIterator<Item = GString>>(&mut self, iter: I) {
@@ -1359,6 +1373,49 @@ 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+
/// Returns the underlying pointer.
1401+
///
1402+
/// This is guaranteed to be nul-terminated.
1403+
#[inline]
1404+
pub const fn as_ptr(&self) -> *const *const c_char {
1405+
self.inner.as_ptr() as *const *const _
1406+
}
1407+
}
1408+
1409+
impl<'a> From<&'a StrV> for &'a CStrV {
1410+
fn from(value: &'a StrV) -> Self {
1411+
let slice = value.as_slice();
1412+
// Safety: `&StrV` is a null-terminated C array of nul-terminated UTF-8 strings,
1413+
// therefore `&StrV::as_slice()` return a a null-terminated slice of nul-terminated UTF-8 strings,
1414+
// thus it is safe to convert it to `&CStr`.
1415+
unsafe { &*(slice as *const [GStringPtr] as *const CStrV) }
1416+
}
1417+
}
1418+
13621419
#[cfg(test)]
13631420
mod test {
13641421
use super::*;

glib/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ mod exit_code;
120120
pub use exit_code::{ExitCode, InvalidExitCode};
121121

122122
pub mod collections;
123-
pub use collections::{List, PtrSlice, SList, Slice, StrV};
123+
pub use collections::{CStrV, List, PtrSlice, SList, Slice, StrV};
124124

125125
pub use self::auto::*;
126126
#[allow(clippy::too_many_arguments)]

0 commit comments

Comments
 (0)