//! Panic reporting utilities.
//!
//! Integrate this with your kernel's `#[panic_handler]` to emit diagnostics through
//! your chosen `Sink`. These helpers are minimal and avoid allocation.
//!
//! Example integration:
//! ```ignore
//! use core::panic::PanicInfo;
//! use os_observatory::sink::RingBufferSink;
//! use os_observatory::panic::report_panic;
//!
//! static SINK: RingBufferSink<1024> = RingBufferSink::new();
//!
//! #[panic_handler]
//! fn panic(info: &PanicInfo) -> ! {
//!     report_panic(&SINK, info);
//!     loop {}
//! }
//! ```

use core::fmt::Write;

use crate::sink::Sink;

/// Emits a panic report to the provided `Sink`.
///
/// The format is single-line to remain reentrant-friendly:
/// `[PANIC] location=<file:line>`
pub fn report_panic<S: Sink>(sink: &S, info: &core::panic::PanicInfo<'_>) {
    struct W<'a, S: Sink>(&'a S);
    impl<'a, S: Sink> Write for W<'a, S> {
        fn write_str(&mut self, s: &str) -> core::fmt::Result {
            let _ = self.0.write_str(s);
            Ok(())
        }
    }
    let mut w = W(sink);
    let _ = w.write_str("[PANIC] ");
    if let Some(loc) = info.location() {
        let _ = w.write_str("location=");
        let _ = w.write_str(loc.file());
        let _ = w.write_str(":");
        // write line number decimal without allocation
        let line = loc.line();
        write_dec(&mut w, line);
    }
    let _ = w.write_str("\n");
}

fn write_dec<W: Write>(w: &mut W, mut n: u32) {
    let mut buf = [0u8; 10];
    let mut i = 10;
    if n == 0 {
        let _ = w.write_str("0");
        return;
    }
    while n > 0 {
        i -= 1;
        buf[i] = b'0' + (n % 10) as u8;
        n /= 10;
    }
    let _ = w.write_str(core::str::from_utf8(&buf[i..]).unwrap_or("?"));
}

