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