use std::cmp::Ordering;
use std::ffi::{c_char, c_int, CString};
use std::ops::Deref;
use pkgcraft::pkg::ebuild::keyword;
use pkgcraft::utils::hash;
use crate::macros::*;
use crate::panic::ffi_catch_panic;
use crate::utils::boxed;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct KeywordWrapper(keyword::Keyword);
#[derive(Debug, Clone)]
#[repr(C)]
pub struct Keyword {
status: keyword::KeywordStatus,
arch: *mut c_char,
keyword: *mut KeywordWrapper,
}
impl From<keyword::Keyword> for Keyword {
fn from(value: keyword::Keyword) -> Self {
Keyword {
status: value.status(),
arch: try_ptr_from_str!(value.arch().as_ref()),
keyword: boxed(KeywordWrapper(value)),
}
}
}
impl Deref for Keyword {
type Target = keyword::Keyword;
fn deref(&self) -> &Self::Target {
let wrapper = try_ref_from_ptr!(self.keyword);
&wrapper.0
}
}
impl Drop for Keyword {
fn drop(&mut self) {
unsafe {
drop(CString::from_raw(self.arch));
drop(Box::from_raw(self.keyword));
}
}
}
#[no_mangle]
pub unsafe extern "C" fn pkgcraft_keyword_new(s: *const c_char) -> *mut Keyword {
ffi_catch_panic! {
let s = try_str_from_ptr!(s);
let keyword = unwrap_or_panic!(keyword::Keyword::try_new(s));
Box::into_raw(Box::new(keyword.into()))
}
}
#[no_mangle]
pub unsafe extern "C" fn pkgcraft_keyword_cmp(k1: *mut Keyword, k2: *mut Keyword) -> c_int {
let k1 = try_ref_from_ptr!(k1);
let k2 = try_ref_from_ptr!(k2);
match k1.cmp(k2) {
Ordering::Less => -1,
Ordering::Equal => 0,
Ordering::Greater => 1,
}
}
#[no_mangle]
pub unsafe extern "C" fn pkgcraft_keyword_hash(k: *mut Keyword) -> u64 {
let keyword = try_ref_from_ptr!(k);
hash(keyword.deref())
}
#[no_mangle]
pub unsafe extern "C" fn pkgcraft_keyword_str(k: *mut Keyword) -> *mut c_char {
let keyword = try_ref_from_ptr!(k);
try_ptr_from_str!(keyword.to_string())
}
#[no_mangle]
pub unsafe extern "C" fn pkgcraft_keyword_free(k: *mut Keyword) {
if !k.is_null() {
unsafe { drop(Box::from_raw(k)) };
}
}