oort_api 0.86.0

APIs for Oort, a space fleet programming game.
Documentation
use std::fmt::Display;
use std::io::Cursor;
use std::io::Write;
use std::panic::PanicHookInfo;

pub const PANIC_BUFFER_SIZE: usize = 1024;
#[unsafe(no_mangle)]
pub static mut PANIC_BUFFER: [u8; PANIC_BUFFER_SIZE] = [0; PANIC_BUFFER_SIZE];

pub unsafe fn install() {
    std::panic::set_hook(Box::new(panic_hook));
}

pub unsafe fn reset() {
    unsafe {
        PANIC_BUFFER[0] = 0;
    }
}

fn panic_hook(info: &PanicHookInfo) {
    unsafe {
        let location = info.location().unwrap();
        let file = location.file();
        let line = location.line();
        let column = location.column();
        let payload = info.payload();
        let payload = payload
            .downcast_ref::<&str>()
            .map(|x| x as &dyn Display)
            .or_else(|| payload.downcast_ref::<String>().map(|x| x as &dyn Display))
            .expect("panic payload of type `&str` or `String`");

        const PREFIX: &str = "/tmp/oort-ai/ai/src/";
        let mut file = file.strip_prefix(PREFIX).unwrap_or(file);
        if file == "user.rs" {
            file = "lib.rs";
        }

        let panic_buffer_ref = &mut *std::ptr::addr_of_mut!(PANIC_BUFFER);
        let mut cursor = Cursor::new(&mut panic_buffer_ref[..]);
        let _ = write!(
            cursor,
            "ship panicked at '{payload}', {file}:{line}:{column}"
        );
        let _ = cursor.write(&[0]);
    }
}