use crate::{R::Rchar, base::s::{Sexp, SExt, r_type::lib_r::{calloc, free, realloc, malloc}}};
use crate::{format, println};
use core::{any::Any, ffi::c_void, fmt::{Debug, Display}, panic::PanicPayload};
#[cfg(not(test))]
use core::fmt::Write;
extern crate alloc;
use alloc::alloc::{GlobalAlloc, Layout};
pub use alloc::{string::{String, ToString}, vec::Vec, boxed::Box};
#[path = "base.no-std.unwind.rs"]
pub mod unwind;
pub fn handle_panic<R, F: FnOnce() -> R>(f: F) -> R {
let thing : Sexp<_> = match unsafe {unwind::catch_unwind(f)} {
Ok(ret) => return ret,
Err(info) => {
match info.downcast::<Sexp<Rchar>>(){
Ok(charexp)=>*charexp,
Err(info)=>Sexp::raw_from(format!("{:?}", info)).into()
}
}
};
unsafe {thing.error()}
}
pub struct SimpleAllocator();
#[global_allocator]
static ALLOCATOR: SimpleAllocator = SimpleAllocator();
unsafe impl Sync for SimpleAllocator {}
unsafe impl GlobalAlloc for SimpleAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
unsafe {
malloc(layout.size()) as *mut u8
}
}
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
unsafe {
calloc(layout.size().div_euclid(layout.align()), layout.align()) as *mut u8
}
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
unsafe { free(ptr as *mut c_void) }
}
unsafe fn realloc(&self, ptr: *mut u8, _layout: Layout, new_size: usize) -> *mut u8 {
unsafe { realloc(ptr as *mut c_void, new_size) as *mut u8 }
}
}
#[cfg(not(test))]
#[panic_handler]
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
let charsxp : Sexp<_> = {
const REASON:&str="Fatal: cannot write to string during panic handling.";
let mut message = String::new();
#[cfg(feature="panic-info-message")]
write!(&mut message,"Panic occured: {}", info.message()).expect(REASON);
#[cfg(not(feature="panic-info-message"))]
write!(&mut message,"Panic occured: (message ignored)").expect(REASON);
if let Some(i) = info.location() {
write!(
&mut message,
"\n at {}, line {}, column {}.",
i.file(),
i.line(),
i.column(),
).expect(REASON)
}
Sexp::raw_from(message.as_str()).into()
};
let reason = unsafe {panic_unwind::__rust_start_panic(&mut RewrapBox(Box::new(charsxp)))};
println!("Unhandled panic occurred, may cause memory leak, be caution!\nNote: This panic omits some deconstructor and may cause memory leak, please restart R as soon as possible to avoid further issues.\n panic_unwind::reason = {}",reason);
unsafe {
charsxp.error();
}
}
#[derive(Debug)]
pub struct RewrapBox(Box<dyn Any + Send>);
impl Display for RewrapBox {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
<Self as Debug>::fmt(self, f)
}
}
unsafe impl PanicPayload for RewrapBox {
fn take_box(&mut self) -> *mut (dyn Any + Send) {
Box::into_raw(core::mem::replace(&mut self.0, Box::new(())))
}
fn get(&mut self) -> &(dyn Any + Send) {
&*self.0
}
}