1#[macro_export]
3macro_rules! define_interface {
4 (command {$($variant:ident = $val:expr),*,}) => {
5 $(pub const $variant: usize = $val;)*
6 pub fn to_str(code: usize) -> alloc::string::String {
7 use alloc::string::ToString;
8 use alloc::format;
9 match code {
10 $($variant => stringify!($variant).to_string()),*,
11 _ => format!("Undefined {}", code)
12 }
13 }
14 };
15}
16
17#[macro_export]
18macro_rules! print {
19 ($($arg:tt)*) => {
20 let buffer = alloc::format!($($arg)*);
21 let _ = io::stdout().write_all(buffer.as_bytes());
22 };
23}
24
25#[macro_export]
26macro_rules! println {
27 () => {crate::print!("\n")};
28 ($fmt:expr) => {crate::print!(concat!($fmt, "\n"))};
29 ($fmt:expr, $($arg:tt)*) => {crate::print!(concat!($fmt, "\n"), $($arg)*)};
30}
31
32#[macro_export]
33macro_rules! eprint {
34 ($fmt:expr) => {
35 let buffer = concat!("\x1b[0;31m", $fmt, "\x1b[0m");
36 let _ = io::stdout().write_all(buffer.as_bytes());
37 };
38 ($fmt:expr, $($arg:tt)*) => {{
39 let buffer = alloc::format!(concat!("\x1b[0;31m", $fmt, "\x1b[0m"), $($arg)*);
40 let _ = io::stdout().write_all(buffer.as_bytes());
41 }};
42}
43
44#[macro_export]
45macro_rules! eprintln {
46 () => {crate::eprint!("\n")};
47 ($fmt:expr) => {crate::eprint!(concat!($fmt, "\n"))};
48 ($fmt:expr, $($arg:tt)*) => {crate::eprint!(concat!($fmt, "\n"), $($arg)*)};
49}
50
51#[macro_export]
52macro_rules! const_assert {
53 ($cond:expr) => {
54 let _ = [(); 0 - (!($cond) as usize)];
56 };
57}
58
59#[macro_export]
60macro_rules! const_assert_eq {
61 ($left:expr, $right:expr) => {
62 const _: () = {
63 crate::const_assert!($left == $right);
64 };
65 };
66}
67
68#[macro_export]
69macro_rules! const_assert_size {
70 ($struct:ty, $size:expr) => {
71 crate::const_assert_eq!(core::mem::size_of::<$struct>(), ($size));
72 };
73}
74
75#[cfg(test)]
76mod test {
77 extern crate alloc;
78
79 use crate::{eprintln, println};
80 use alloc::boxed::Box;
81 use alloc::string::String;
82 use alloc::vec::Vec;
83 use core::cell::RefCell;
84 use io::{stdout, Write as IoWrite};
85 use io::{ConsoleWriter, Device, Result, Write};
86
87 pub struct MockDevice {
88 buffer: RefCell<Vec<u8>>,
89 ready: bool,
90 }
91
92 impl MockDevice {
93 pub const fn new() -> Self {
94 MockDevice {
95 buffer: RefCell::new(Vec::new()),
96 ready: false,
97 }
98 }
99
100 pub fn output(&self) -> String {
101 String::from_utf8(self.buffer.borrow().to_vec()).unwrap()
102 }
103 }
104
105 impl Device for MockDevice {
106 fn initialize(&mut self) -> Result<()> {
107 self.ready = true;
108 Ok(())
109 }
110
111 fn initialized(&self) -> bool {
112 self.ready
113 }
114 }
115
116 impl Write for MockDevice {
117 fn write_all(&mut self, buf: &[u8]) -> Result<()> {
118 self.buffer.borrow_mut().extend_from_slice(buf);
119 Ok(())
120 }
121 }
122
123 impl ConsoleWriter for MockDevice {}
124
125 #[test]
126 fn println_without_arg() {
127 let mock = Box::new(MockDevice::new());
128 let mock_ptr = mock.as_ref() as *const MockDevice;
129 stdout().attach(mock).ok().unwrap();
130
131 println!();
132
133 assert_eq!(unsafe { (*mock_ptr).output() }, "\n");
134 }
135
136 #[test]
137 fn println_without_format() {
138 let mock = Box::new(MockDevice::new());
139 let mock_ptr = mock.as_ref() as *const MockDevice;
140 stdout().attach(mock).ok().unwrap();
141
142 println!("hello");
143 assert_eq!(unsafe { (*mock_ptr).output() }, "hello\n");
144 }
145
146 #[test]
147 fn println_with_format() {
148 let mock = Box::new(MockDevice::new());
149 let mock_ptr = mock.as_ref() as *const MockDevice;
150 stdout().attach(mock).ok().unwrap();
151
152 println!("number {}", 1234);
153 assert_eq!(unsafe { (*mock_ptr).output() }, "number 1234\n");
154 }
155
156 #[test]
157 fn eprintln_without_arg() {
158 let mock = Box::new(MockDevice::new());
159 let mock_ptr = mock.as_ref() as *const MockDevice;
160 stdout().attach(mock).ok().unwrap();
161
162 eprintln!();
163 assert_eq!(unsafe { (*mock_ptr).output() }, "\x1b[0;31m\n\x1b[0m");
164 }
165
166 #[test]
167 fn eprintln_without_format() {
168 let mock = Box::new(MockDevice::new());
169 let mock_ptr = mock.as_ref() as *const MockDevice;
170 stdout().attach(mock).ok().unwrap();
171
172 eprintln!("hello");
173 assert_eq!(unsafe { (*mock_ptr).output() }, "\x1b[0;31mhello\n\x1b[0m");
174 }
175
176 #[test]
177 fn eprintln_with_format() {
178 let mock = Box::new(MockDevice::new());
179 let mock_ptr = mock.as_ref() as *const MockDevice;
180 stdout().attach(mock).ok().unwrap();
181
182 eprintln!("number {}", 4321);
183 assert_eq!(
184 unsafe { (*mock_ptr).output() },
185 "\x1b[0;31mnumber 4321\n\x1b[0m"
186 );
187 }
188
189 #[test]
190 fn set_of_const_assert() {
191 const_assert!(1 != 2);
192 const_assert!(true);
193
194 const_assert_eq!(1, 1);
195 const_assert_eq!(false, false);
196
197 const_assert_size!(u32, 4);
198 const_assert_size!(u64, 8);
199 }
200}