Skip to content

Commit

Permalink
Merge pull request #5 from artichoke/lopopolo/state-opaque
Browse files Browse the repository at this point in the history
Make `sysdir_search_path_enumeration_state` opaque
  • Loading branch information
lopopolo authored May 12, 2023
2 parents 15f08fc + 1c9e08e commit 5818946
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 1 deletion.
24 changes: 24 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ task :bindgen do
bindgen --use-core
--allowlist-function sysdir.*
--allowlist-type sysdir.*
--blocklist-type sysdir_search_path_enumeration_state
--allowlist-var PATH_MAX
--default-enum-style rust_non_exhaustive
--constified-enum sysdir_search_path_domain_mask_t
Expand All @@ -150,6 +151,29 @@ task :bindgen do
f.puts ''

IO.copy_stream(bindgen_io, f)

f.puts ''
f.puts <<~NEWTYPE
/// Opaque type for holding sysdir enumeration state.
#[repr(transparent)]
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub struct sysdir_search_path_enumeration_state(::core::ffi::c_uint);
impl PartialEq<::core::ffi::c_uint> for sysdir_search_path_enumeration_state {
fn eq(&self, other: &::core::ffi::c_uint) -> bool {
self.0 == *other
}
}
impl sysdir_search_path_enumeration_state {
/// Return true if the state indicates the enumeration is finished.
#[must_use]
pub fn is_finished(&self) -> bool {
self.0 == 0
}
}
NEWTYPE
end
end

Expand Down
26 changes: 26 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,30 @@ mod tests {

assert_eq!(count, 1, "Should iterate once and find `/Users`");
}

#[test]
fn example_and_linkage_with_opaque_state_helpers() {
let mut count = 0_usize;
let mut path = [0; PATH_MAX as usize];

let dir = sysdir_search_path_directory_t::SYSDIR_DIRECTORY_USER;
let domain_mask = SYSDIR_DOMAIN_MASK_LOCAL;

unsafe {
let mut state = sysdir_start_search_path_enumeration(dir, domain_mask);
loop {
let path = path.as_mut_ptr().cast::<c_char>();
state = sysdir_get_next_search_path_enumeration(state, path);
if state.is_finished() {
break;
}
let path = CStr::from_ptr(path);
let s = path.to_str().unwrap();
assert_eq!(s, "/Users");
count += 1;
}
}

assert_eq!(count, 1, "Should iterate once and find `/Users`");
}
}
21 changes: 20 additions & 1 deletion src/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ pub const SYSDIR_DOMAIN_MASK_NETWORK: sysdir_search_path_domain_mask_t = 4;
pub const SYSDIR_DOMAIN_MASK_SYSTEM: sysdir_search_path_domain_mask_t = 8;
pub const SYSDIR_DOMAIN_MASK_ALL: sysdir_search_path_domain_mask_t = 65535;
pub type sysdir_search_path_domain_mask_t = ::core::ffi::c_uint;
pub type sysdir_search_path_enumeration_state = ::core::ffi::c_uint;
extern "C" {
pub fn sysdir_start_search_path_enumeration(
dir: sysdir_search_path_directory_t,
Expand All @@ -61,3 +60,23 @@ extern "C" {
path: *mut ::core::ffi::c_char,
) -> sysdir_search_path_enumeration_state;
}

/// Opaque type for holding sysdir enumeration state.
#[repr(transparent)]
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub struct sysdir_search_path_enumeration_state(::core::ffi::c_uint);

impl PartialEq<::core::ffi::c_uint> for sysdir_search_path_enumeration_state {
fn eq(&self, other: &::core::ffi::c_uint) -> bool {
self.0 == *other
}
}

impl sysdir_search_path_enumeration_state {
/// Return true if the state indicates the enumeration is finished.
#[must_use]
pub fn is_finished(&self) -> bool {
self.0 == 0
}
}

0 comments on commit 5818946

Please sign in to comment.