#[macro_export]
macro_rules! access_dirent {
($entry_ptr:expr, d_reclen) => {{
(*$entry_ptr).d_reclen as usize }};
($entry_ptr:expr, d_namlen) => {{
#[cfg(has_d_namlen)]
{
(*$entry_ptr).d_namlen as usize
}
#[cfg(not(has_d_namlen))]
{
compile_error!("d_namlen field is not available on this platform - use d_reclen or strlen instead")
}
}};
($entry_ptr:expr, d_off) => {{
(*$entry_ptr).d_off
}};
($entry_ptr:expr,d_name) => {{
(&raw const (*$entry_ptr).d_name).cast::<_>() }};
($entry_ptr:expr, d_type) => {{
#[cfg(not(has_d_type))]
{
libc::DT_UNKNOWN }
#[cfg(has_d_type)]
{
(*$entry_ptr).d_type
}}};
($entry_ptr:expr, d_ino) => {{
#[cfg(all(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly"
),has_d_ino))]
{
(*$entry_ptr).d_fileno as u64
}
#[cfg(all(not(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly"
)),has_d_ino))]
{
(*$entry_ptr).d_ino as _
}
#[cfg(not(has_d_ino))]
{
0
}
}};
}
macro_rules! access_stat {
($stat_struct:expr, st_mtimensec) => {{
#[cfg(target_os = "netbsd")]
{
$stat_struct.st_mtimensec as _
}
#[cfg(not(target_os = "netbsd"))]
{
$stat_struct.st_mtime_nsec as _
}
}};
($stat_struct:expr, st_mtime) => {{ $stat_struct.st_mtime as _ }};
($stat_struct:expr, st_ino) => {{
#[cfg(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly"
))]
{
$stat_struct.st_ino as u64
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly"
)))]
{
$stat_struct.st_ino as _
}
}};
($stat_struct:expr, $field:ident) => {{ $stat_struct.$field as _ }};
}
macro_rules! read_direntries {
($dir:expr) => {{
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "openbsd",
target_os = "netbsd",
target_os = "illumos",
target_os = "solaris"
))]
{
$dir.getdents()
}
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
{
$dir.getdirentries()
}
#[cfg(not(any(
target_os = "linux",
target_os = "android",
target_os = "macos",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "illumos",
target_os = "solaris"
)))]
{
$dir.readdir()
}
}};
}
#[macro_export]
macro_rules! const_assert {
($cond:expr $(,)?) => {
const _: () = {
if !$cond {
panic!(concat!("const assertion failed: ", stringify!($cond)));
}
};
};
($cond:expr, $($arg:tt)+) => {
const _: () = {
if !$cond {
panic!($($arg)+);
}
};
};
}
macro_rules! skip_dot_or_dot_dot_entries {
($entry:expr, $action:expr) => {{
#[allow(unused_unsafe)]
unsafe {
#[cfg(has_d_namlen)]
{
let namelen = access_dirent!($entry, d_namlen);
if namelen <= 2 {
let f2b: [u8; 2] = *access_dirent!($entry, d_name);
if f2b[0] == b'.' {
match (namelen, f2b[1]) {
(1, _) | (2, b'.') => $action,
_ => (),
}
}
}
}
#[cfg(not(has_d_namlen))]
{
let f3b: [u8; 3] = *access_dirent!($entry, d_name);
if f3b[0] == b'.' {
match f3b[1..] {
[b'\0', _] | [b'.', b'\0'] => $action,
_ => (),
}
}
}
}
}};
}
#[macro_export]
macro_rules! const_from_env {
($(#[$meta:meta])* $name:ident: $t:ty = $env:expr, $default:expr) => {
$(#[$meta])*
#[doc(hidden)]
pub const $name: $t = {
#[allow(clippy::single_call_fn)]
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_sign_loss)] #[allow(clippy::indexing_slicing)]
#[allow(clippy::integer_division_remainder_used)]
#[allow(clippy::integer_division)] #[allow(clippy::missing_asserts_for_indexing)] const fn parse_env(s: &str) -> $t {
let s_bytes = s.as_bytes();
if s_bytes.len() == 0 {
panic!(concat!("Empty environment variable: ", stringify!($env)));
}
if !s_bytes.is_ascii(){
panic!(concat!("Non ASCII characters in", stringify!($env)));
}
const TYPE_OF:&str=stringify!($t);
const TYPE_OF_AS_BYTES:&[u8]=TYPE_OF.as_bytes();
$crate::const_assert!(!matches!(TYPE_OF_AS_BYTES,b"f128"),"f128 not tested(due to experimental nature)");
$crate::const_assert!(!matches!(TYPE_OF_AS_BYTES,b"f16"),"f16 not tested(due to experimental nature)");
assert!(!(s_bytes[0]==b'-' && TYPE_OF_AS_BYTES[0]==b'u'),concat!("Negative detected in unsigned env var ",stringify!($env)));
$crate::const_assert!(TYPE_OF_AS_BYTES[0] != b'u' || $default >= <$t>::MIN,concat!("Negative default not allowed for ", stringify!($default)));
const IS_FLOAT: bool = TYPE_OF_AS_BYTES[0]==b'f';
let is_negative = s_bytes[0] == b'-';
let is_positive = s_bytes[0] == b'+';
let start_idx:usize = if is_negative || is_positive { 1 } else { 0 };
if IS_FLOAT {
const TEN: $t = 10 as $t;
const ZERO: $t = 0 as $t;
let mut integer_part: $t = ZERO;
let mut fraction_part: $t = ZERO;
let mut fraction_divisor: $t = 1 as $t;
let mut in_fraction = false;
let mut i = start_idx;
while i < s_bytes.len() {
let b = s_bytes[i];
match b {
b'0'..=b'9' => {
let digit = (b - b'0') as $t;
if in_fraction {
fraction_divisor *= TEN;
fraction_part = fraction_part * TEN + digit;
} else {
integer_part = integer_part * TEN + digit;
}
}
b'.' => {
if in_fraction {
panic!(concat!("Multiple decimal points in: ", stringify!($env)));
}
in_fraction = true;
}
_ => panic!(concat!("Invalid float value in: ", stringify!($env))),
}
i += 1;
}
let mut result = integer_part + (fraction_part / fraction_divisor);
if is_negative {
result = ZERO -result;
}
result
} else {
const TEN:$t = 10 as $t;
const ZERO:$t = 0 as $t;
let mut n = 0 as $t;
let mut i = start_idx;
while i < s_bytes.len() {
let b = s_bytes[i];
match b {
b'0'..=b'9' => {
n = n * TEN + (b - b'0') as $t;
}
_ => panic!(concat!("Invalid numeric value in: ", stringify!($env))),
}
i += 1;
}
if is_negative {
n = ZERO - n; }
n
}
}
match option_env!($env) {
Some(val) => parse_env(val),
None => $default as _,
}
};
};
}
macro_rules! return_os_error {
() => {{
return Err(std::io::Error::last_os_error().into());
}};
}
macro_rules! stat_syscall {
($syscall:ident, $fd:expr, $path:expr, $flags:expr) => {{
let mut stat_buf = core::mem::MaybeUninit::<libc::stat>::uninit();
let res = unsafe {
$syscall(
$fd,
$path,
stat_buf.as_mut_ptr(),
$flags,
)
};
if res == 0 {
Ok(unsafe { stat_buf.assume_init() })
} else {
Err(std::io::Error::last_os_error().into())
}
}};
($syscall:ident, $fd:expr, $path:expr, $flags:expr,DTYPE) => {{
let mut stat_buf = core::mem::MaybeUninit::<libc::stat>::uninit();
let res = unsafe {
$syscall(
$fd,
$path,
stat_buf.as_mut_ptr(),
$flags,
)
};
if res == 0 {
$crate::fs::FileType::from_stat(&unsafe { stat_buf.assume_init() })
} else {
$crate::fs::FileType::Unknown
}
}};
($syscall:ident, $path_ptr:expr) => {{
let mut stat_buf = core::mem::MaybeUninit::<libc::stat>::uninit();
let res = unsafe { $syscall($path_ptr, stat_buf.as_mut_ptr()) };
if res == 0 {
Ok(unsafe { stat_buf.assume_init() })
} else {
Err(std::io::Error::last_os_error().into())
}
}};
}