mochi_rs/
lib.rs

1#![no_std]
2#![feature(
3    core_intrinsics,
4    alloc_error_handler,
5    fmt_internals,
6    panic_info_message
7)]
8
9#[cfg_attr(feature = "dlmalloc", global_allocator)]
10static ALLOCATOR: dlmalloc::GlobalDlmalloc = dlmalloc::GlobalDlmalloc;
11
12fn as_abort<T: AsRef<str>>(message: T, file: T, line: u32, column: u32) -> ! {
13    extern "C" {
14        #[link_name = "abort"]
15        fn _abort(message: *const u8, file: *const u8, line: i32, column: i32);
16    }
17    extern crate alloc;
18    use alloc::alloc::{alloc_zeroed, dealloc};
19    use core::{alloc::Layout, ptr::copy};
20
21    let message = message.as_ref();
22    let file = file.as_ref();
23
24    // Basically, AssemblyScript places 4 bytes before the string slice to denote
25    // its length. This is why we need the extra 8 bytes.
26    if let Ok(layout) =
27        Layout::from_size_align(8 + message.len() + file.len(), core::mem::align_of::<u8>())
28    {
29        unsafe {
30            let message_len_ptr = alloc_zeroed(layout) as *mut i32;
31            *message_len_ptr = i32::try_from(message.len()).unwrap_or(-1);
32
33            let message_ptr = message_len_ptr.add(1) as *mut u8;
34            copy::<u8>(message.as_ptr(), message_ptr, message.len());
35
36            let file_len_ptr = message_len_ptr.add(message.len()) as *mut i32;
37            *file_len_ptr = i32::try_from(file.len()).unwrap_or(-1);
38
39            let file_ptr = file_len_ptr.add(1) as *mut u8;
40            copy::<u8>(file.as_ptr(), file_ptr, file.len());
41
42            _abort(
43                message_ptr,
44                file_ptr,
45                line.try_into().unwrap_or(-1),
46                column.try_into().unwrap_or(-1),
47            );
48
49            dealloc(message_len_ptr as *mut u8, layout);
50            dealloc(message_ptr, layout);
51            dealloc(file_len_ptr as *mut u8, layout);
52            dealloc(file_ptr, layout);
53        }
54    }
55
56    core::intrinsics::abort()
57}
58
59#[cfg_attr(not(test), panic_handler)]
60pub fn panic_handle(info: &core::panic::PanicInfo) -> ! {
61    // use crate::imports::Write;
62    extern crate alloc;
63    use alloc::string::String;
64    use ::core::fmt::Write;
65
66    let (file, line, col) = if let Some(location) = info.location() {
67        (location.file(), location.line(), location.column())
68    } else {
69        ("", 0, 0)
70    };
71
72    let message = if let Some(args) = info.message() {
73        let mut string = String::with_capacity(args.estimated_capacity());
74        string.write_fmt(*args).unwrap_or_default();
75        string
76    } else {
77        String::new()
78    };
79
80    as_abort(message, String::from(file), line, col)
81}
82
83mod macros;
84pub use crate::macros::*;
85
86mod imports;
87pub use imports::error;
88
89pub mod std {
90    pub use crate::imports::*;
91}
92
93pub use mochi_bind::*;
94
95pub mod structs;
96
97#[cfg(feature = "extractors")]
98pub mod extractors;