mallockit 0.1.0

A framework for building malloc implementations in Rust
Documentation
use spin::Mutex;
use std::fmt;
use std::fmt::Write;

#[doc(hidden)]
#[cold]
pub fn _print(args: fmt::Arguments<'_>, new_line: bool, stderr: bool) {
    let mut log = if stderr { ERR.lock() } else { LOG.lock() };
    log.write_fmt(args).unwrap();
    if new_line {
        log.put_char(b'\n');
    }
    log.flush();
}

#[macro_export]
macro_rules! print {
    ($($arg:tt)*) => {{
        $crate::util::sys::log::_print(format_args!($($arg)*), false, false);
    }};
}

#[macro_export]
macro_rules! println {
    ($($arg:tt)*) => {{
        $crate::util::sys::log::_print(format_args!($($arg)*), true, false);
    }};
}

#[macro_export]
macro_rules! eprint {
    ($($arg:tt)*) => {{
        $crate::util::sys::log::_print(format_args!($($arg)*), false, true);
    }};
}

#[macro_export]
macro_rules! eprintln {
    ($($arg:tt)*) => {{
        $crate::util::sys::log::_print(format_args!($($arg)*), true, true);
    }};
}

static LOG: Mutex<Log> = Mutex::new(Log::new(false));
static ERR: Mutex<Log> = Mutex::new(Log::new(true));

struct Log {
    stderr: bool,
    cursor: usize,
    buffer: [u8; 80],
}

impl Log {
    const fn new(stderr: bool) -> Self {
        Self {
            stderr,
            cursor: 0,
            buffer: [0; 80],
        }
    }

    #[cold]
    fn flush(&mut self) {
        unsafe {
            if self.stderr {
                libc::write(2, self.buffer.as_ptr() as _, self.cursor);
            } else {
                libc::write(1, self.buffer.as_ptr() as _, self.cursor);
            }
        }
        self.cursor = 0;
    }

    fn put_char(&mut self, c: u8) {
        self.buffer[self.cursor] = c;
        self.cursor += 1;
        if self.cursor >= self.buffer.len() {
            self.flush();
        }
    }
}

impl Write for Log {
    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
        for b in s.bytes() {
            self.put_char(b);
        }
        Ok(())
    }
}