1 //! Minimal versions of standard-library panicking and printing macros.
2 //!
3 //! We're avoiding static initializers, so we can't have things like string
4 //! literals. Replace the standard assert macros with simpler implementations.
5 
6 use crate::bindings::wasi::cli::stderr::get_stderr;
7 
8 #[allow(dead_code, reason = "useful for debugging")]
9 #[doc(hidden)]
print(message: &[u8])10 pub fn print(message: &[u8]) {
11     let _ = get_stderr().blocking_write_and_flush(message);
12 }
13 
14 /// A minimal `eprint` for debugging.
15 #[allow(unused_macros, reason = "useful for debugging")]
16 macro_rules! eprint {
17     ($arg:tt) => {{
18         // We have to expand string literals into byte arrays to prevent them
19         // from getting statically initialized.
20         let message = byte_array_literals::str!($arg);
21         $crate::macros::print(&message);
22     }};
23 }
24 
25 /// A minimal `eprintln` for debugging.
26 #[allow(unused_macros, reason = "useful for debugging")]
27 macro_rules! eprintln {
28     ($arg:tt) => {{
29         // We have to expand string literals into byte arrays to prevent them
30         // from getting statically initialized.
31         let message = byte_array_literals::str_nl!($arg);
32         $crate::macros::print(&message);
33     }};
34 }
35 
36 #[allow(dead_code, reason = "useful for debugging")]
37 #[doc(hidden)]
eprint_unreachable(line: u32)38 pub fn eprint_unreachable(line: u32) {
39     eprint!("unreachable executed at adapter line ");
40     crate::macros::eprint_u32(line);
41 }
42 
eprint_u32(x: u32)43 fn eprint_u32(x: u32) {
44     if x == 0 {
45         eprint!("0");
46     } else {
47         eprint_u32_impl(x)
48     }
49 
50     fn eprint_u32_impl(x: u32) {
51         if x != 0 {
52             eprint_u32_impl(x / 10);
53 
54             let digit = [b'0' + ((x % 10) as u8)];
55             crate::macros::print(&digit);
56         }
57     }
58 }
59 
60 #[allow(dead_code, reason = "useful for debugging")]
61 #[doc(hidden)]
unreachable(line: u32) -> !62 pub fn unreachable(line: u32) -> ! {
63     crate::macros::eprint_unreachable(line);
64     eprint!("\n");
65     #[cfg(target_arch = "wasm32")]
66     core::arch::wasm32::unreachable();
67     // This is here to keep rust-analyzer happy when building for native:
68     #[cfg(not(target_arch = "wasm32"))]
69     std::process::abort();
70 }
71 
72 /// A minimal `unreachable`.
73 macro_rules! unreachable {
74     () => {{
75         crate::macros::unreachable(line!());
76     }};
77 
78     ($arg:tt) => {{
79         crate::macros::eprint_unreachable(line!());
80         eprint!(": ");
81         eprintln!($arg);
82         eprint!("\n");
83         #[cfg(target_arch = "wasm32")]
84         core::arch::wasm32::unreachable();
85         // This is here to keep rust-analyzer happy when building for native:
86         #[cfg(not(target_arch = "wasm32"))]
87         std::process::abort();
88     }};
89 }
90 
91 #[allow(dead_code, reason = "useful for debugging")]
92 #[doc(hidden)]
assert_fail(line: u32) -> !93 pub fn assert_fail(line: u32) -> ! {
94     eprint!("assertion failed at adapter line ");
95     crate::macros::eprint_u32(line);
96     #[cfg(target_arch = "wasm32")]
97     core::arch::wasm32::unreachable();
98     // This is here to keep rust-analyzer happy when building for native:
99     #[cfg(not(target_arch = "wasm32"))]
100     std::process::abort();
101 }
102 
103 /// A minimal `assert`.
104 macro_rules! assert {
105     ($cond:expr $(,)?) => {
106         if !$cond {
107             crate::macros::assert_fail(line!());
108         }
109     };
110 }
111 
112 /// A minimal `assert_eq`.
113 macro_rules! assert_eq {
114     ($left:expr, $right:expr $(,)?) => {
115         assert!($left == $right);
116     };
117 }
118