#![warn(missing_docs)]
#![warn(clippy::pedantic)]
#![cfg_attr(
not(test),
deny(
clippy::unwrap_used,
clippy::expect_used,
clippy::todo,
clippy::unimplemented,
clippy::panic
)
)]
#![allow(
clippy::doc_markdown,
clippy::module_name_repetitions,
clippy::must_use_candidate
)]
use std::num::NonZeroUsize;
#[cfg(not(target_arch = "wasm32"))]
pub mod affinity;
pub mod binformat;
#[cfg(not(target_arch = "wasm32"))]
pub mod corpus;
pub mod cpu_features;
#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod file_identity;
#[cfg(not(target_arch = "wasm32"))]
pub mod hugepages;
#[cfg(not(target_arch = "wasm32"))]
pub mod memory;
#[cfg(not(target_arch = "wasm32"))]
pub mod mlock;
#[cfg(not(target_arch = "wasm32"))]
pub mod mmap;
#[cfg(not(target_arch = "wasm32"))]
pub mod numa;
#[cfg(not(target_arch = "wasm32"))]
pub mod perf;
#[cfg(not(target_arch = "wasm32"))]
pub mod prefetch;
#[cfg(not(target_arch = "wasm32"))]
pub mod readahead;
#[cfg(not(target_arch = "wasm32"))]
pub use affinity::{pin_to_core, pin_to_numa_node, read_irq_affinity};
#[cfg(not(target_arch = "wasm32"))]
pub use binformat::FileHeader;
#[cfg(not(target_arch = "wasm32"))]
pub use corpus::{MmapCorpus, MmapRegion};
pub use cpu_features::CpuFeatures;
#[cfg(not(target_arch = "wasm32"))]
pub use hugepages::HugePageVec;
#[cfg(not(target_arch = "wasm32"))]
pub use memory::{MemoryStatus, memory_pressure};
#[cfg(not(target_arch = "wasm32"))]
pub use mmap::MmapBlock;
#[cfg(not(target_arch = "wasm32"))]
pub use readahead::{advise_sequential, evict_pages};
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error(
"allocation for {count} values of `{type_name}` overflowed. Fix: reduce the element count or use a smaller element type."
)]
AllocationOverflow {
count: usize,
type_name: &'static str,
},
#[error(
"allocation failed for {count} values of `{type_name}`. Fix: reduce the element count, enable huge pages, or free system memory."
)]
AllocationFailed {
count: usize,
type_name: &'static str,
},
#[error(
"pointer was null for a non-zero region length. Fix: pass a valid pointer or use length 0."
)]
NullPointer,
#[error(
"NUMA node {node} is not available on this machine. Fix: use a node in the range 0..{available}."
)]
InvalidNode {
node: u32,
available: usize,
},
#[error(
"{operation} failed: {source}. Fix: verify kernel support, process privileges, and resource limits."
)]
System {
operation: &'static str,
#[source]
source: std::io::Error,
},
#[error(
"could not read CPU cache metadata from `{path}`. Fix: verify `/sys` is mounted and readable, or rely on the fallback defaults."
)]
SysfsRead {
path: &'static str,
#[source]
source: std::io::Error,
},
#[error(
"could not parse CPU cache metadata from `{path}`. Fix: verify the kernel exposes numeric cache values in sysfs."
)]
SysfsParse {
path: &'static str,
},
#[error(
"invalid binary format magic bytes. Fix: ensure the file was written by a compatible version."
)]
InvalidMagic,
#[error(
"unsupported binary format version {version} (max {max_version}). Fix: upgrade the reader or downgrade the file."
)]
UnsupportedVersion {
version: u64,
max_version: u64,
},
#[error(
"section length {length} exceeds platform address space. Fix: ensure the file is not corrupted."
)]
SectionTooLarge {
length: u64,
},
#[error(
"unexpected end of data reading {context}: needed {needed} bytes, {remaining} available. Fix: ensure the file is not truncated."
)]
UnexpectedEof {
context: &'static str,
needed: usize,
remaining: usize,
},
#[error(
"could not load `{library}`: {source}. Fix: install the runtime library or rely on the portable fallback path."
)]
LibraryLoad {
library: &'static str,
#[source]
source: libloading::Error,
},
#[error(
"could not resolve `{symbol}` from `{library}`: {source}. Fix: install a compatible version of the runtime library."
)]
SymbolLoad {
library: &'static str,
symbol: &'static str,
#[source]
source: libloading::Error,
},
}
fn checked_len<T>(count: usize) -> Result<usize> {
count
.checked_mul(std::mem::size_of::<T>())
.ok_or(Error::AllocationOverflow {
count,
type_name: std::any::type_name::<T>(),
})
}
fn non_zero_len(len: usize) -> Option<NonZeroUsize> {
NonZeroUsize::new(len)
}
#[must_use]
pub fn page_size() -> usize {
#[cfg(unix)]
{
let ps = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
if ps > 0 {
return usize::try_from(ps).unwrap_or(4096);
}
}
4096
}