use core::{alloc::{GlobalAlloc, Layout}, ffi::{c_int, c_void}, sync::atomic::{AtomicBool, Ordering}};
#[link(name = "c")]
unsafe extern "C" {
fn posix_memalign(out: *mut *mut c_void, align: usize, size: usize) -> c_int;
fn free(ptr: *mut c_void);
fn mmap(address: *mut c_void, size: usize, protection: c_int, flags: c_int, fd: c_int, offset: i64) -> *mut c_void;
fn munmap(address: *mut c_void, size: usize) -> c_int;
fn sched_yield() -> c_int;
fn _exit(code: c_int) -> !;
fn write(fd: c_int, bytes: *const c_void, count: usize) -> isize;
}
#[link(name = "log")]
unsafe extern "C" {
fn __android_log_write(priority: c_int, tag: *const u8, text: *const u8) -> c_int;
}
struct AndroidAllocator;
#[cfg_attr(not(feature = "std"), global_allocator)]
#[cfg_attr(feature = "std", allow(dead_code))] static ALLOC: AndroidAllocator = AndroidAllocator;
unsafe impl GlobalAlloc for AndroidAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let mut ptr = core::ptr::null_mut();
let result = unsafe { posix_memalign(&mut ptr, layout.align().max(core::mem::size_of::<usize>()), layout.size().max(1)) };
if result == 0 { ptr.cast() } else { core::ptr::null_mut() }
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
unsafe { free(ptr.cast()) };
}
}
pub unsafe fn pages_alloc(size: usize) -> *mut u8 {
let ptr = unsafe { mmap(core::ptr::null_mut(), size.max(1), 3, 0x22, -1, 0) };
if ptr as usize == usize::MAX { core::ptr::null_mut() } else { ptr.cast() }
}
pub unsafe fn pages_free(ptr: *mut u8, size: usize) {
if !ptr.is_null() {
unsafe { munmap(ptr.cast(), size.max(1)) };
}
}
pub fn yield_now() {
unsafe { sched_yield() };
}
pub fn exit(code: i32) -> ! {
unsafe { _exit(code) }
}
static CONSOLE: AtomicBool = AtomicBool::new(false);
#[unsafe(no_mangle)]
pub extern "C" fn jfgui_console() {
CONSOLE.store(true, Ordering::Relaxed);
}
fn log(bytes: &[u8], priority: i32) {
if CONSOLE.load(Ordering::Relaxed) {
unsafe { write(if priority == 6 { 2 } else { 1 }, bytes.as_ptr().cast(), bytes.len()) };
return;
}
for chunk in bytes.chunks(1000) {
let mut text = [0u8; 1001];
text[..chunk.len()].copy_from_slice(chunk);
unsafe { __android_log_write(priority, c"jfgui".as_ptr().cast(), text.as_ptr()) };
}
}
pub fn write_stdout(bytes: &[u8]) { log(bytes, 4); }
pub fn write_stderr(bytes: &[u8]) { log(bytes, 6); }
#[cfg(not(feature = "std"))]
#[unsafe(no_mangle)]
pub extern "C" fn rust_eh_personality() -> ! { exit(4) }