pkgcraft/
eapi.rs

1use std::cmp::Ordering;
2use std::ffi::{c_char, c_int};
3
4use pkgcraft::eapi::{self, Eapi};
5use pkgcraft::utils::hash;
6
7use crate::macros::*;
8use crate::panic::ffi_catch_panic;
9use crate::utils::str_to_raw;
10
11/// Convert Eapi pointer to reference, mapping NULL to the default EAPI.
12///
13/// # Safety
14/// The argument must be an Eapi pointer or NULL.
15macro_rules! eapi_or_default {
16    ( $var:expr ) => {{
17        let eapi = unsafe { $var.as_ref() };
18        eapi.unwrap_or_default()
19    }};
20}
21pub(crate) use eapi_or_default;
22
23/// Get all known EAPIS.
24///
25/// # Safety
26/// The returned array must be freed via pkgcraft_eapis_free().
27#[no_mangle]
28pub unsafe extern "C" fn pkgcraft_eapis(len: *mut usize) -> *mut *const Eapi {
29    iter_to_array!(eapi::EAPIS.iter(), len, |&e| { e as *const _ })
30}
31
32/// Get all official EAPIS.
33///
34/// # Safety
35/// The returned array must be freed via pkgcraft_eapis_free().
36#[no_mangle]
37pub unsafe extern "C" fn pkgcraft_eapis_official(len: *mut usize) -> *mut *const Eapi {
38    iter_to_array!(eapi::EAPIS_OFFICIAL.iter(), len, |&e| { e as *const _ })
39}
40
41/// Get an EAPI from its identifier.
42///
43/// Returns NULL on error.
44///
45/// # Safety
46/// The argument must be a non-null string.
47#[no_mangle]
48pub unsafe extern "C" fn pkgcraft_eapi_from_str(s: *const c_char) -> *const Eapi {
49    ffi_catch_panic! {
50        let s = try_str_from_ptr!(s);
51        unwrap_or_panic!(s.parse::<&Eapi>())
52    }
53}
54
55/// Check if an EAPI has a feature.
56///
57/// # Safety
58/// The arguments must be a non-null Eapi pointer and non-null string.
59#[no_mangle]
60pub unsafe extern "C" fn pkgcraft_eapi_has(eapi: *const Eapi, s: *const c_char) -> bool {
61    let eapi = try_ref_from_ptr!(eapi);
62    let s = try_str_from_ptr!(s);
63    s.parse().map(|f| eapi.has(f)).unwrap_or_default()
64}
65
66/// Return an EAPI's identifier.
67///
68/// # Safety
69/// The arguments must be a non-null Eapi pointer.
70#[no_mangle]
71pub unsafe extern "C" fn pkgcraft_eapi_as_str(eapi: *const Eapi) -> *mut c_char {
72    let eapi = try_ref_from_ptr!(eapi);
73    try_ptr_from_str!(eapi.as_str())
74}
75
76/// Determine if a string is a valid EAPI.
77///
78/// Returns NULL on error.
79///
80/// # Safety
81/// The argument should point to a UTF-8 string.
82#[no_mangle]
83pub unsafe extern "C" fn pkgcraft_eapi_parse(s: *const c_char) -> *const c_char {
84    ffi_catch_panic! {
85        let val = try_str_from_ptr!(s);
86        unwrap_or_panic!(Eapi::parse(val));
87        s
88    }
89}
90
91/// Compare two Eapi objects chronologically returning -1, 0, or 1 if the first is less than, equal
92/// to, or greater than the second, respectively.
93///
94/// # Safety
95/// The arguments must be non-null Eapi pointers.
96#[no_mangle]
97pub unsafe extern "C" fn pkgcraft_eapi_cmp(e1: *const Eapi, e2: *const Eapi) -> c_int {
98    let eapi1 = try_ref_from_ptr!(e1);
99    let eapi2 = try_ref_from_ptr!(e2);
100
101    match eapi1.cmp(eapi2) {
102        Ordering::Less => -1,
103        Ordering::Equal => 0,
104        Ordering::Greater => 1,
105    }
106}
107
108/// Return the array of dependency keys for an Eapi.
109///
110/// # Safety
111/// The argument must be a non-null Eapi pointer.
112#[no_mangle]
113pub unsafe extern "C" fn pkgcraft_eapi_dep_keys(
114    eapi: *const Eapi,
115    len: *mut usize,
116) -> *mut *mut c_char {
117    let eapi = try_ref_from_ptr!(eapi);
118    iter_to_array!(eapi.dep_keys().iter(), len, str_to_raw)
119}
120
121/// Return the array of metadata keys for an Eapi.
122///
123/// # Safety
124/// The argument must be a non-null Eapi pointer.
125#[no_mangle]
126pub unsafe extern "C" fn pkgcraft_eapi_metadata_keys(
127    eapi: *const Eapi,
128    len: *mut usize,
129) -> *mut *mut c_char {
130    let eapi = try_ref_from_ptr!(eapi);
131    iter_to_array!(eapi.metadata_keys().iter(), len, str_to_raw)
132}
133
134/// Return the hash value for an Eapi.
135///
136/// # Safety
137/// The argument must be a non-null Eapi pointer.
138#[no_mangle]
139pub unsafe extern "C" fn pkgcraft_eapi_hash(eapi: *const Eapi) -> u64 {
140    let eapi = try_ref_from_ptr!(eapi);
141    hash(eapi)
142}
143
144/// Convert EAPI range into an array of Eapi objects.
145///
146/// Returns NULL on error.
147///
148/// # Safety
149/// The argument must be a non-null string.
150#[no_mangle]
151pub unsafe extern "C" fn pkgcraft_eapis_range(
152    s: *const c_char,
153    len: *mut usize,
154) -> *mut *const Eapi {
155    ffi_catch_panic! {
156        let s = try_str_from_ptr!(s);
157        let eapis = unwrap_or_panic!(eapi::range(s));
158        iter_to_array!(eapis, len, |e| { e as *const _ })
159    }
160}