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(any(
target_os = "fuchsia",
target_os = "haiku",
target_os = "hermit",
target_os = "android",
target_os = "emscripten",
target_os = "solaris",
target_os = "illumos",
target_os = "vxworks",
target_os = "wasi",
target_env = "wasi",
))]
pub type ConstantType = libc::c_int;
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "openbsd",
target_os = "netbsd",
target_os = "redox",
target_env = "newlib",
target_env = "uclibc",
))]
pub type ConstantType = libc::c_ulong;
#[cfg(all(target_os = "linux", target_env = "musl"))]
pub type ConstantType = libc::c_int;
#[cfg(all(target_os = "linux", target_env = "gnu"))]
pub type ConstantType = libc::c_ulong;
#[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())
}
}