brickworks 0.0.1

Brick Rigs mod loader
use core::fmt::{self, Write};
use core::ptr;
extern "C"
{
    fn malloc( size: usize ) -> *mut ();
    fn realloc( ptr: *mut (), size: usize ) -> *mut ();
    fn free( ptr: *mut () );
}

pub struct Buffer {
    pub ptr: *mut u8,
    pub len: usize,
    pub cap: usize,
}
impl Buffer {
    pub fn new() -> Self {
        Self {
            ptr: core::ptr::null_mut(),
            len: 0,
            cap: 0,
        }
    }

    fn grow(&mut self, additional: usize) -> Result<(), ()> {
        let required = self.len + additional;

        if required <= self.cap {
            return Ok(());
        }

        let new_cap = if self.cap == 0 {
            required.max(64)
        } else {
            (self.cap * 2).max(required)
        };

        unsafe {
            let new_ptr = if self.ptr.is_null() {
                malloc(new_cap)
            } else {
                realloc(self.ptr as *mut _, new_cap)
            } as *mut u8;

            if new_ptr.is_null() {
                return Err(());
            }

            self.ptr = new_ptr;
            self.cap = new_cap;
        }

        Ok(())
    }
}

impl Write for Buffer {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.grow(s.len()).map_err(|_| fmt::Error)?;

        unsafe {
            let dst = self.ptr.add(self.len);
            ptr::copy_nonoverlapping(s.as_ptr(), dst, s.len());
        }

        self.len += s.len();
        Ok(())
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            if !self.ptr.is_null() {
                free(self.ptr as *mut _);
            }
        }
    }
}


unsafe extern "C"
{
    pub fn BrickRust_print( str: *const u8 );
}

/**
 * Sets module name for br_print
 * [ name ] your log
 * */
#[macro_export]
macro_rules! set_module_name {
    ($name: expr) => {
        #[allow(non_snake_case)]
        unsafe fn BrickRust_print( str: *const u8 )
        {
            use brickworks::logger;
            logger::brickworks_puts(
                $name.as_ptr(),
                str
                );
        }
        
    };
}

#[macro_export]
macro_rules! br_print {
    ($($arg:tt)*) => {{
        use core::fmt::Write;
        use $crate::print::Buffer;

        let mut buf = Buffer::new();
        let _ = write!(&mut buf, "{}\0", core::format_args!($($arg)*));

        unsafe {
            BrickRust_print(buf.ptr as *const u8);
        }
    }};
}