1#![no_std]
3#![warn(clippy::all)]
4#![warn(clippy::pedantic)]
5use sc::syscall;
6
7
8pub const __STDOUT: usize = 1;
10
11pub const __STDERR: usize = 2;
13
14#[macro_export]
16macro_rules! unix_print {
17 ($($arg:tt)*) => {
18 let mut __unix_print_writer = $crate::UnixWriter::stdout();
19 let _ = core::fmt::Write::write_fmt(&mut __unix_print_writer, format_args!($($arg)*));
20 }
21}
22
23#[macro_export]
25macro_rules! unix_println {
26 () => {
27 let _ = $crate::__write_to_handle($crate::__STDOUT, "\n".as_bytes());
28 };
29 ($($arg:tt)*) => {
30 let mut __unix_print_writer = $crate::UnixWriter::stdout();
31 let _ = core::fmt::Write::write_fmt(&mut __unix_print_writer, format_args!($($arg)*));
32 let _ = __unix_print_writer.write_newline();
33
34 }
35}
36
37#[macro_export]
39macro_rules! unix_eprint {
40 ($($arg:tt)*) => {
41 let mut __unix_print_writer = $crate::UnixWriter::stderr();
42 let _ = core::fmt::Write::write_fmt(&mut __unix_print_writer, format_args!($($arg)*));
43 }
44}
45
46#[macro_export]
48macro_rules! unix_eprintln {
49 () => {
50 let _ = $crate::__write_to_handle($crate::__STDERR, "\n".as_bytes());
51 };
52 ($($arg:tt)*) => {
53 let mut __unix_print_writer = $crate::UnixWriter::stderr();
54 let _ = core::fmt::Write::write_fmt(&mut __unix_print_writer, format_args!($($arg)*));
55 let _ = __unix_print_writer.write_newline();
56
57 }
58}
59
60#[macro_export]
62macro_rules! unix_dbg {
63 () => {
64 $crate::unix_eprintln!("[{}:{}]", core::file!(), core::line!())
65 };
66 ($val:expr $(,)?) => {
67 match $val {
68 tmp => {
69 $crate::unix_eprintln!("[{}:{}] {} = {:#?}",
70 core::file!(), core::line!(), core::stringify!($val), &tmp);
71 tmp
72 }
73 }
74 };
75 ($($val:expr),+ $(,)?) => {
76 ($($crate::dbg!($val)),+,)
77 };
78}
79
80#[allow(clippy::cast_possible_wrap)]
82#[must_use]
83pub fn __write_to_handle(fd: usize, msg: &[u8]) -> isize {
84 unsafe {
85 syscall!(WRITE, fd, msg.as_ptr(), msg.len()) as isize
86 }
87}
88
89#[allow(clippy::cast_sign_loss)]
90fn try_print(fd: usize, msg: &str) -> core::fmt::Result {
91 let buf = msg.as_bytes();
92 let len = buf.len();
93 let mut flushed = 0;
94 loop {
95 let res = __write_to_handle(fd, &buf[flushed..]);
96 match res.cmp(&0) {
97 core::cmp::Ordering::Less => return Err(core::fmt::Error),
98 core::cmp::Ordering::Equal => return Ok(()),
99 core::cmp::Ordering::Greater => {
100 flushed += res as usize;
102 if flushed >= len {
103 return Ok(())
104 }
105 }
106 }
107 }
108}
109
110pub struct UnixWriter(usize);
111
112impl UnixWriter {
113 #[must_use]
114 pub fn stdout() -> Self {
115 Self(__STDOUT)
116 }
117
118 #[must_use]
119 pub fn stderr() -> Self {
120 Self(__STDERR)
121 }
122
123 pub fn write_newline(&self) -> core::fmt::Result {
126 try_print(self.0, "\n")
127 }
128}
129
130impl core::fmt::Write for UnixWriter {
131 fn write_str(&mut self, s: &str) -> core::fmt::Result {
132 try_print(self.0, s)
133 }
134}
135
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140
141 #[test]
142 fn test_prints() {
143 unix_println!("-- First");
144 unix_print!("My first");
145 unix_print!(" two messages");
146 unix_print!(" were cutoff but it's fine");
147 unix_println!();
148 unix_println!("-- Second\nHello there {}", "me");
149 }
150
151 #[test]
152 fn test_eprints() {
153 unix_eprintln!("-- First");
154 unix_eprint!("My first");
155 unix_eprint!(" two messages");
156 unix_eprint!(" were cutoff but it's fine");
157 unix_eprintln!();
158 unix_eprintln!("-- Second\nHello there {}", "me");
159 }
160
161 #[test]
162 fn test_dbgs() {
163 unix_dbg!();
164 let val = 5;
165 let res = unix_dbg!(val) - 5;
166 assert_eq!(0, res);
167 }
168
169}