#![allow(unknown_lints)]
#![allow(unexpected_cfgs)]
#![warn(unknown_lints)]
use {
::core::{
ffi::c_void,
ptr::{self, null_mut}
},
::cty::c_int
};
#[cfg(any(
all(target_arch = "riscv32", any(target_os = "espidf", target_os = "zkvm")),
all(target_arch = "xtensa", target_os = "espidf"),
))]
pub const MIN_ALIGN: usize = 4;
#[cfg(any(
target_arch = "x86",
target_arch = "arm",
target_arch = "m68k",
target_arch = "csky",
target_arch = "loongarch32",
target_arch = "mips",
target_arch = "mips32r6",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "sparc",
target_arch = "wasm32",
target_arch = "hexagon",
// riscv32 except when handled by the 4-byte case
all(target_arch = "riscv32", not(any(target_os = "espidf", target_os = "zkvm"))),
// xtensa except when handled by the 4-byte case
all(target_arch = "xtensa", not(target_os = "espidf")),
))]
pub const MIN_ALIGN: usize = 8;
#[cfg(any(
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "arm64ec",
target_arch = "loongarch64",
target_arch = "mips64",
target_arch = "mips64r6",
target_arch = "s390x",
target_arch = "sparc64",
target_arch = "riscv64",
target_arch = "wasm64",
))]
pub const MIN_ALIGN: usize = 16;
#[cfg(all(
not(any(
all(target_arch = "riscv32", any(target_os = "espidf", target_os = "zkvm")),
all(target_arch = "xtensa", target_os = "espidf"),
target_arch = "x86",
target_arch = "arm",
target_arch = "m68k",
target_arch = "csky",
target_arch = "loongarch32",
target_arch = "mips",
target_arch = "mips32r6",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "sparc",
target_arch = "wasm32",
target_arch = "hexagon",
all(target_arch = "riscv32", not(any(target_os = "espidf", target_os = "zkvm"))),
all(target_arch = "xtensa", not(target_os = "espidf")),
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "arm64ec",
target_arch = "loongarch64",
target_arch = "mips64",
target_arch = "mips64r6",
target_arch = "s390x",
target_arch = "sparc64",
target_arch = "riscv64",
target_arch = "wasm64",
)),
any(feature = "dev", test)
))]
compile_error!("this platform is missing a value for `MIN_ALIGN`");
#[cfg(all(
not(any(
all(target_arch = "riscv32", any(target_os = "espidf", target_os = "zkvm")),
all(target_arch = "xtensa", target_os = "espidf"),
target_arch = "x86",
target_arch = "arm",
target_arch = "m68k",
target_arch = "csky",
target_arch = "loongarch32",
target_arch = "mips",
target_arch = "mips32r6",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "sparc",
target_arch = "wasm32",
target_arch = "hexagon",
all(target_arch = "riscv32", not(any(target_os = "espidf", target_os = "zkvm"))),
all(target_arch = "xtensa", not(target_os = "espidf")),
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "arm64ec",
target_arch = "loongarch64",
target_arch = "mips64",
target_arch = "mips64r6",
target_arch = "s390x",
target_arch = "sparc64",
target_arch = "riscv64",
target_arch = "wasm64",
)),
not(any(feature = "dev", test))
))]
pub const MIN_ALIGN: usize = 1;
const NULL: *mut c_void = null_mut();
pub unsafe fn try_move(
ptr: *mut c_void,
old_ptr: *mut c_void,
copy_count: usize,
old_align: usize,
old_size: usize
) {
if ptr != NULL {
unsafe {
memcpy(ptr, old_ptr, copy_count);
}
unsafe {
c_dealloc(old_ptr, old_align, old_size);
}
}
}
#[must_use = "this function allocates memory on success, and dropping the returned pointer will \
leak memory"]
pub unsafe fn c_alloc(align: usize, size: usize) -> (*mut c_void, c_int) {
if align > MIN_ALIGN && size >= align {
unsafe { c_alloc_spec(align, size) }
} else {
unsafe { (malloc(size), 0) }
}
}
#[cfg(all(not(any(target_os = "horizon", target_os = "vita")), not(windows)))]
#[inline(always)]
unsafe fn c_alloc_spec(align: usize, size: usize) -> (*mut c_void, c_int) {
#[cfg(target_vendor = "apple")]
{
if align > (1 << 31) {
return (NULL, 22);
}
}
let mut out = NULL;
let ret = unsafe { posix_memalign(&mut out as *mut *mut c_void, align, size) };
(out, if ret == 0 { -1 } else { ret })
}
#[cfg(windows)]
#[inline(always)]
unsafe fn c_alloc_spec(align: usize, size: usize) -> (*mut c_void, c_int) {
(unsafe { _aligned_malloc(size, align) }, 0)
}
#[cfg(any(target_os = "horizon", target_os = "vita"))]
#[inline(always)]
unsafe fn c_alloc_spec(layout: &Layout) -> *mut c_void {
(unsafe { memalign(layout.align(), layout.size()) }, 0)
}
#[must_use = "this function allocates memory on success, and dropping the returned pointer will \
leak memory"]
pub unsafe fn c_zalloc(align: usize, size: usize) -> (*mut c_void, c_int) {
if align > MIN_ALIGN && size >= align {
let (ptr, status) = unsafe { c_alloc_spec(align, size) };
if ptr != NULL {
unsafe {
ptr::write_bytes(ptr, 0, size);
}
}
(ptr, status)
} else {
(unsafe { calloc(1, size) }, 0)
}
}
pub unsafe fn c_dealloc(ptr: *mut c_void, _size: usize, _align: usize) {
#[cfg(windows)]
{
#[allow(clippy::used_underscore_binding)]
if _align > MIN_ALIGN && _size >= _align {
unsafe {
_aligned_free(ptr);
}
} else {
unsafe {
free(ptr);
}
}
}
#[cfg(not(windows))]
{
unsafe {
free(ptr);
}
}
}
#[cfg_attr(miri, track_caller)]
pub unsafe fn grow_aligned(
old_ptr: *mut c_void,
old_align: usize,
old_size: usize,
align: usize,
size: usize,
zeroed: bool
) -> (*mut c_void, c_int) {
let (ptr, status) =
if zeroed { unsafe { c_zalloc(align, size) } } else { unsafe { c_alloc(align, size) } };
unsafe {
try_move(ptr, old_ptr, old_size, old_align, old_size);
}
(ptr, status)
}
#[cfg_attr(miri, track_caller)]
pub unsafe fn shrink_aligned(
old_ptr: *mut c_void,
old_align: usize,
old_size: usize,
align: usize,
size: usize ) -> (*mut c_void, c_int) {
let (ptr, status) = unsafe { c_alloc(align, size) };
unsafe {
try_move(ptr, old_ptr, size, old_align, old_size);
}
(ptr, status)
}
extern "C" {
#[must_use = "this function allocates memory on success, and dropping the returned pointer \
will leak memory"]
pub fn malloc(size: usize) -> *mut c_void;
#[must_use = "this function allocates memory on success, and dropping the returned pointer \
will leak memory"]
pub fn calloc(count: usize, size: usize) -> *mut c_void;
#[must_use = "this function allocates memory on success, and dropping the returned pointer \
will leak memory"]
pub fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void;
#[cfg(all(not(windows), not(any(target_os = "horizon", target_os = "vita"))))]
#[must_use = "this function allocates memory on success, and dropping the returned pointer \
will leak memory"]
pub fn posix_memalign(out: *mut *mut c_void, align: usize, size: usize) -> c_int;
#[cfg(all(not(windows), any(target_os = "horizon", target_os = "vita")))]
#[must_use = "this function allocates memory on success, and dropping the returned pointer \
will leak memory"]
pub fn memalign(align: usize, size: usize) -> *mut c_void;
#[cfg(not(windows))]
#[must_use = "this function allocates memory on success, and dropping the returned pointer \
will leak memory"]
pub fn aligned_alloc(align: usize, size: usize) -> *mut c_void;
pub fn free(ptr: *mut c_void);
#[cfg(windows)]
#[must_use = "this function allocates memory on success, and dropping the returned pointer \
will leak memory"]
pub fn _aligned_malloc(size: usize, alignment: usize) -> *mut c_void;
#[cfg(windows)]
pub fn _aligned_free(ptr: *mut c_void);
#[cfg(windows)]
pub fn _aligned_realloc(ptr: *mut c_void, size: usize, align: usize) -> *mut c_void;
pub fn memset(ptr: *mut c_void, val: i32, count: usize) -> *mut c_void;
pub fn memcpy(dest: *mut c_void, src: *const c_void, count: usize) -> *mut c_void;
pub fn memmove(dest: *mut c_void, src: *const c_void, count: usize) -> *mut c_void;
}