use std::ffi::c_int;
#[inline(always)]
#[must_use]
pub const fn likely(b: bool) -> bool {
b
}
#[inline(always)]
#[must_use]
pub const fn unlikely(b: bool) -> bool {
b
}
#[macro_export]
macro_rules! likely {
($e:expr) => {
$crate::ffi::hints::likely($e)
};
}
#[macro_export]
macro_rules! unlikely {
($e:expr) => {
$crate::ffi::hints::unlikely($e)
};
}
pub const COLD_ATTRIBUTE: &str = "#[cold]";
pub const INLINE_GUIDELINES: &str = r#"
#[inline] - Suggest inlining, compiler decides
#[inline(always)] - Force inlining (use sparingly)
#[inline(never)] - Prevent inlining (for cold paths)
"#;
#[inline(always)]
pub fn assume(cond: bool) {
if cfg!(debug_assertions) {
assert!(cond, "assumption violated");
} else if !cond {
unsafe { std::hint::unreachable_unchecked() }
}
}
#[inline(always)]
pub unsafe fn assume_in_bounds(value: usize, len: usize) {
assume(value < len);
}
#[inline(always)]
pub unsafe fn assume_non_null<T>(ptr: *const T) {
assume(!ptr.is_null());
}
#[inline(always)]
pub unsafe fn assume_non_empty<T>(slice: &[T]) {
assume(!slice.is_empty());
}
#[inline(never)]
pub fn black_box<T>(x: T) -> T {
std::hint::black_box(x)
}
#[inline(always)]
pub unsafe fn unreachable_unchecked() -> ! {
unsafe { std::hint::unreachable_unchecked() }
}
#[inline(always)]
pub fn spin_loop() {
std::hint::spin_loop();
}
pub use super::data_locality::{
PrefetchLocality, prefetch_range_read, prefetch_range_write, prefetch_read, prefetch_write,
};
#[inline(always)]
pub fn early_return_on_error<T, E>(result: Result<T, E>) -> Option<T> {
if unlikely(result.is_err()) {
None
} else {
result.ok()
}
}
#[inline(always)]
pub fn early_return_on_null<T>(ptr: *const T) -> Option<*const T> {
if unlikely(ptr.is_null()) {
None
} else {
Some(ptr)
}
}
#[inline(always)]
pub fn early_return_on_none<T>(opt: Option<T>) -> Option<T> {
if unlikely(opt.is_none()) { None } else { opt }
}
#[inline(always)]
pub fn min_f32(a: f32, b: f32) -> f32 {
if a < b { a } else { b }
}
#[inline(always)]
pub fn max_f32(a: f32, b: f32) -> f32 {
if a > b { a } else { b }
}
#[inline(always)]
pub fn clamp_f32(value: f32, min: f32, max: f32) -> f32 {
max_f32(min, min_f32(value, max))
}
#[inline(always)]
pub fn min_i32(a: i32, b: i32) -> i32 {
if a < b { a } else { b }
}
#[inline(always)]
pub fn max_i32(a: i32, b: i32) -> i32 {
if a > b { a } else { b }
}
#[inline(always)]
pub fn clamp_i32(value: i32, min: i32, max: i32) -> i32 {
max_i32(min, min_i32(value, max))
}
#[inline(always)]
pub fn min_usize(a: usize, b: usize) -> usize {
if a < b { a } else { b }
}
#[inline(always)]
pub fn max_usize(a: usize, b: usize) -> usize {
if a > b { a } else { b }
}
#[inline(always)]
pub fn clamp_usize(value: usize, min: usize, max: usize) -> usize {
max_usize(min, min_usize(value, max))
}
#[unsafe(no_mangle)]
#[inline(always)]
pub extern "C" fn fz_likely(condition: c_int) -> c_int {
likely(condition != 0) as c_int
}
#[unsafe(no_mangle)]
#[inline(always)]
pub extern "C" fn fz_unlikely(condition: c_int) -> c_int {
unlikely(condition != 0) as c_int
}
#[unsafe(no_mangle)]
#[inline(never)]
pub extern "C" fn fz_black_box_int(value: c_int) -> c_int {
black_box(value)
}
#[unsafe(no_mangle)]
#[inline(always)]
pub extern "C" fn fz_spin_loop_hint() {
spin_loop();
}
#[unsafe(no_mangle)]
#[inline(always)]
pub extern "C" fn fz_assume(condition: c_int) {
assume(condition != 0);
}
#[unsafe(no_mangle)]
#[inline(always)]
pub extern "C" fn fz_min_f32(a: f32, b: f32) -> f32 {
min_f32(a, b)
}
#[unsafe(no_mangle)]
#[inline(always)]
pub extern "C" fn fz_max_f32(a: f32, b: f32) -> f32 {
max_f32(a, b)
}
#[unsafe(no_mangle)]
#[inline(always)]
pub extern "C" fn fz_clamp_f32(value: f32, min: f32, max: f32) -> f32 {
clamp_f32(value, min, max)
}
#[unsafe(no_mangle)]
#[inline(always)]
pub extern "C" fn fz_min_i32(a: i32, b: i32) -> i32 {
min_i32(a, b)
}
#[unsafe(no_mangle)]
#[inline(always)]
pub extern "C" fn fz_max_i32(a: i32, b: i32) -> i32 {
max_i32(a, b)
}
#[unsafe(no_mangle)]
#[inline(always)]
pub extern "C" fn fz_clamp_i32(value: i32, min: i32, max: i32) -> i32 {
clamp_i32(value, min, max)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_likely_unlikely() {
assert!(likely(true));
assert!(!likely(false));
assert!(unlikely(true)); assert!(!unlikely(false)); }
#[test]
fn test_min_max_f32() {
assert_eq!(min_f32(1.0, 2.0), 1.0);
assert_eq!(min_f32(2.0, 1.0), 1.0);
assert_eq!(max_f32(1.0, 2.0), 2.0);
assert_eq!(max_f32(2.0, 1.0), 2.0);
}
#[test]
fn test_clamp_f32() {
assert_eq!(clamp_f32(0.5, 0.0, 1.0), 0.5);
assert_eq!(clamp_f32(-1.0, 0.0, 1.0), 0.0);
assert_eq!(clamp_f32(2.0, 0.0, 1.0), 1.0);
}
#[test]
fn test_min_max_i32() {
assert_eq!(min_i32(1, 2), 1);
assert_eq!(min_i32(2, 1), 1);
assert_eq!(max_i32(1, 2), 2);
assert_eq!(max_i32(2, 1), 2);
}
#[test]
fn test_clamp_i32() {
assert_eq!(clamp_i32(5, 0, 10), 5);
assert_eq!(clamp_i32(-5, 0, 10), 0);
assert_eq!(clamp_i32(15, 0, 10), 10);
}
#[test]
fn test_min_max_usize() {
assert_eq!(min_usize(1, 2), 1);
assert_eq!(max_usize(1, 2), 2);
assert_eq!(clamp_usize(5, 0, 10), 5);
}
#[test]
fn test_black_box() {
let x = black_box(42);
assert_eq!(x, 42);
}
#[test]
fn test_early_return_on_error() {
let ok: Result<i32, &str> = Ok(42);
let err: Result<i32, &str> = Err("error");
assert_eq!(early_return_on_error(ok), Some(42));
assert_eq!(early_return_on_error(err), None);
}
#[test]
fn test_early_return_on_null() {
let ptr: *const i32 = &42;
let null: *const i32 = std::ptr::null();
assert!(early_return_on_null(ptr).is_some());
assert!(early_return_on_null(null).is_none());
}
#[test]
fn test_early_return_on_none() {
let some: Option<i32> = Some(42);
let none: Option<i32> = None;
assert_eq!(early_return_on_none(some), Some(42));
assert_eq!(early_return_on_none(none), None);
}
#[test]
fn test_assume() {
assume(true);
assume(1 > 0);
}
#[test]
fn test_ffi_likely() {
assert_eq!(fz_likely(1), 1);
assert_eq!(fz_likely(0), 0);
assert_eq!(fz_unlikely(1), 1);
assert_eq!(fz_unlikely(0), 0);
}
#[test]
fn test_ffi_min_max() {
assert_eq!(fz_min_f32(1.0, 2.0), 1.0);
assert_eq!(fz_max_f32(1.0, 2.0), 2.0);
assert_eq!(fz_clamp_f32(0.5, 0.0, 1.0), 0.5);
assert_eq!(fz_min_i32(1, 2), 1);
assert_eq!(fz_max_i32(1, 2), 2);
assert_eq!(fz_clamp_i32(5, 0, 10), 5);
}
#[test]
fn test_ffi_black_box() {
assert_eq!(fz_black_box_int(42), 42);
}
}