pkgcraft/dep/
use_dep.rs

1use std::cmp::Ordering;
2use std::ffi::{c_char, c_int, CString};
3use std::ops::Deref;
4use std::ptr;
5
6use pkgcraft::dep;
7use pkgcraft::utils::hash;
8
9use crate::macros::*;
10use crate::panic::ffi_catch_panic;
11use crate::utils::boxed;
12
13/// Opaque wrapper for pkgcraft::dep::UseDep.
14#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub struct UseDepWrapper(dep::UseDep);
16
17/// C-compatible wrapper for pkgcraft::dep::UseDep.
18#[derive(Debug, Clone)]
19#[repr(C)]
20pub struct UseDep {
21    flag: *mut c_char,
22    kind: dep::UseDepKind,
23    enabled: bool,
24    // underscore suffix to avoid reserved keyword with cython bindings
25    default_: *mut bool,
26    dep: *mut UseDepWrapper,
27}
28
29impl From<dep::UseDep> for UseDep {
30    fn from(u: dep::UseDep) -> Self {
31        UseDep {
32            kind: u.kind(),
33            enabled: u.enabled(),
34            flag: try_ptr_from_str!(u.flag()),
35            default_: u.default().map(boxed).unwrap_or(ptr::null_mut()),
36            dep: boxed(UseDepWrapper(u)),
37        }
38    }
39}
40
41impl Deref for UseDep {
42    type Target = dep::UseDep;
43
44    fn deref(&self) -> &Self::Target {
45        let wrapper = try_ref_from_ptr!(self.dep);
46        &wrapper.0
47    }
48}
49
50impl Drop for UseDep {
51    fn drop(&mut self) {
52        unsafe {
53            drop(CString::from_raw(self.flag));
54            if !self.default_.is_null() {
55                drop(Box::from_raw(self.default_));
56            }
57            drop(Box::from_raw(self.dep));
58        }
59    }
60}
61
62/// Parse a string into a package USE dependency.
63///
64/// Returns NULL on error.
65///
66/// # Safety
67/// The argument must be a non-null string.
68#[no_mangle]
69pub unsafe extern "C" fn pkgcraft_use_dep_new(s: *const c_char) -> *mut UseDep {
70    ffi_catch_panic! {
71        let s = try_str_from_ptr!(s);
72        let use_dep = unwrap_or_panic!(dep::UseDep::try_new(s).map(|u| u.into()));
73        Box::into_raw(Box::new(use_dep))
74    }
75}
76
77/// Compare two package USE dependencies returning -1, 0, or 1 if the first is less than, equal to,
78/// or greater than the second, respectively.
79///
80/// # Safety
81/// The arguments must be non-null UseDep pointers.
82#[no_mangle]
83pub unsafe extern "C" fn pkgcraft_use_dep_cmp(u1: *mut UseDep, u2: *mut UseDep) -> c_int {
84    let u1 = try_ref_from_ptr!(u1);
85    let u2 = try_ref_from_ptr!(u2);
86
87    match u1.cmp(u2) {
88        Ordering::Less => -1,
89        Ordering::Equal => 0,
90        Ordering::Greater => 1,
91    }
92}
93
94/// Return the hash value for a package USE dependency.
95///
96/// # Safety
97/// The argument must be a non-null UseDep pointer.
98#[no_mangle]
99pub unsafe extern "C" fn pkgcraft_use_dep_hash(u: *mut UseDep) -> u64 {
100    let use_dep = try_ref_from_ptr!(u);
101    hash(use_dep.deref())
102}
103
104/// Return the string for a package USE dependency.
105///
106/// # Safety
107/// The argument must be a non-null UseDep pointer.
108#[no_mangle]
109pub unsafe extern "C" fn pkgcraft_use_dep_str(u: *mut UseDep) -> *mut c_char {
110    let u = try_ref_from_ptr!(u);
111    try_ptr_from_str!(u.to_string())
112}
113
114/// Free a package USE dependency.
115///
116/// # Safety
117/// The argument must be a UseDep pointer or NULL.
118#[no_mangle]
119pub unsafe extern "C" fn pkgcraft_use_dep_free(u: *mut UseDep) {
120    if !u.is_null() {
121        unsafe { drop(Box::from_raw(u)) };
122    }
123}