use std::collections::HashMap;
use std::convert::AsRef;
use std::ffi::CStr;
use std::mem;
use std::os::raw::c_char;
use std::ptr;
#[cfg(all(not(target_pointer_width = "32"), not(target_env = "musl"), not(target_os="android")))]
pub type ConstantType = u64;
#[cfg(all(target_pointer_width = "32", not(target_env = "musl"), not(target_os="android")))]
pub type ConstantType = u32;
#[cfg(any(target_env = "musl", target_os="android") )]
pub type ConstantType = i32;
#[repr(C)]
struct Constant {
name: *const c_char,
value: u64,
}
extern "C" {
fn rust_get_constants() -> *const Constant;
}
lazy_static! {
static ref CONSTANTS: HashMap<String, ConstantType> = {
let mut cvals = vec![];
let mut constant = unsafe { rust_get_constants() };
loop {
let cval = unsafe { ptr::read(constant) };
if cval.name.is_null() {
break
}
cvals.push(cval);
constant = ((constant as usize) + mem::size_of::<Constant>()) as *const Constant;
}
let ret = cvals
.into_iter()
.map(|v| {
(
unsafe { CStr::from_ptr(v.name).to_string_lossy().into_owned() },
v.value as ConstantType
)
})
.collect::<HashMap<_, _>>();
ret
};
}
pub fn get_constant<S: AsRef<str>>(name: S) -> Option<ConstantType> {
CONSTANTS.get(name.as_ref()).map(|v| *v)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_existing() {
assert!(get_constant("SIOCGIFFLAGS").is_some())
}
#[test]
fn test_not_existing() {
assert!(get_constant("bad key").is_none())
}
}