1#![no_std]
43#![warn(unsafe_op_in_unsafe_fn)]
44
45use core::convert::TryFrom;
46
47#[doc(hidden)]
50pub const __LIBC_NEWLINE: &str = "\n";
51#[doc(hidden)]
52pub const __LIBC_STDOUT: i32 = 1;
53#[doc(hidden)]
54pub const __LIBC_STDERR: i32 = 2;
55
56#[doc(hidden)]
57pub struct __LibCWriter(i32);
58
59impl core::fmt::Write for __LibCWriter {
60 #[inline]
61 fn write_str(&mut self, s: &str) -> core::fmt::Result {
62 __libc_println(self.0, s)
63 }
64}
65
66impl __LibCWriter {
67 #[inline]
68 pub fn new(handle: i32) -> __LibCWriter {
69 __LibCWriter(handle)
70 }
71
72 #[inline]
73 pub fn write_fmt(&mut self, args: core::fmt::Arguments) -> core::fmt::Result {
74 core::fmt::Write::write_fmt(self, args)
75 }
76
77 #[inline]
78 pub fn write_str(&mut self, s: &str) -> core::fmt::Result {
79 __libc_println(self.0, s)
80 }
81
82 #[inline]
83 pub fn write_nl(&mut self) -> core::fmt::Result {
84 __libc_println(self.0, __LIBC_NEWLINE)
85 }
86}
87
88#[doc(hidden)]
89#[inline]
90pub fn __libc_println(handle: i32, msg: &str) -> core::fmt::Result {
91 let msg = msg.as_bytes();
92
93 let mut written = 0;
94 while written < msg.len() {
95 match unsafe { libc_write(handle, &msg[written..]) } {
96 None | Some(0) => break,
98 Some(res) => written += res,
99 }
100 }
101
102 Ok(())
103}
104
105#[cfg(not(any(all(target_family = "wasm", target_os = "unknown"), target_os = "none")))]
106mod write {
107 pub(crate) use libc::write;
108}
109
110#[cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "none"))]
111mod write {
112 unsafe extern "C" {
114 pub(crate) fn write(fd: i32, buf: *const u8, nbyte: usize) -> isize;
115 }
116}
117
118unsafe fn libc_write(handle: i32, bytes: &[u8]) -> Option<usize> {
119 usize::try_from(unsafe { write::write(handle as _, bytes.as_ptr() as _, bytes.len() as _) })
120 .ok()
121}
122
123#[macro_export]
133macro_rules! libc_println {
134 () => { $crate::libc_println!("") };
135 ($($arg:tt)*) => {
136 {
137 #[allow(unused_must_use)]
138 {
139 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDOUT);
140 stm.write_fmt(format_args!($($arg)*));
141 stm.write_nl();
142 }
143 }
144 };
145}
146
147#[macro_export]
157macro_rules! libc_print {
158 ($($arg:tt)*) => {
159 {
160 #[allow(unused_must_use)]
161 {
162 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDOUT);
163 stm.write_fmt(format_args!($($arg)*));
164 }
165 }
166 };
167}
168
169#[macro_export]
179macro_rules! libc_eprintln {
180 () => { $crate::libc_eprintln!("") };
181 ($($arg:tt)*) => {
182 {
183 #[allow(unused_must_use)]
184 {
185 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDERR);
186 stm.write_fmt(format_args!($($arg)*));
187 stm.write_nl();
188 }
189 }
190 };
191}
192
193#[macro_export]
203macro_rules! libc_eprint {
204 ($($arg:tt)*) => {
205 {
206 #[allow(unused_must_use)]
207 {
208 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDERR);
209 stm.write_fmt(format_args!($($arg)*));
210 }
211 }
212 };
213}
214
215#[macro_export]
219macro_rules! libc_write {
220 ($arg:expr) => {
221 #[allow(unused_must_use)]
222 {
223 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDOUT);
224 stm.write_str($arg);
225 }
226 };
227}
228
229#[macro_export]
233macro_rules! libc_ewrite {
234 ($arg:expr) => {{
235 #[allow(unused_must_use)]
236 {
237 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDERR);
238 stm.write_str($arg);
239 }
240 }};
241}
242
243#[macro_export]
247macro_rules! libc_writeln {
248 ($arg:expr) => {
249 #[allow(unused_must_use)]
250 {
251 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDOUT);
252 stm.write_str($arg);
253 stm.write_nl();
254 }
255 };
256}
257
258#[macro_export]
262macro_rules! libc_ewriteln {
263 ($arg:expr) => {{
264 #[allow(unused_must_use)]
265 {
266 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDERR);
267 stm.write_str($arg);
268 stm.write_nl();
269 }
270 }};
271}
272
273#[macro_export]
290macro_rules! libc_dbg {
291 () => {
292 $crate::libc_eprintln!("[{}:{}]", ::core::file!(), ::core::line!())
293 };
294 ($val:expr $(,)?) => {
295 match $val {
296 tmp => {
297 $crate::libc_eprintln!("[{}:{}] {} = {:#?}", ::core::file!(), ::core::line!(), ::core::stringify!($val), &tmp);
298 tmp
299 }
300 }
301 };
302 ($($val:expr),+ $(,)?) => {
303 ($($crate::libc_dbg!($val)),+,)
304 };
305}
306
307pub mod std_name {
310 pub use super::libc_dbg as dbg;
311 pub use super::libc_eprint as eprint;
312 pub use super::libc_eprintln as eprintln;
313 pub use super::libc_print as print;
314 pub use super::libc_println as println;
315
316 #[cfg(test)]
317 mod tests_std_name {
318 use super::{eprintln, println};
319
320 #[test]
321 fn test_stdout() {
322 println!("stdout fd = {}", crate::__LIBC_STDOUT);
323 }
324
325 #[test]
326 fn test_stderr() {
327 eprintln!("stderr fd = {}", crate::__LIBC_STDERR);
328 }
329 }
330}
331
332#[cfg(test)]
333mod tests {
334 #[test]
335 fn test_stdout() {
336 super::libc_println!("stdout fd = {}", super::__LIBC_STDOUT);
337 }
338
339 #[test]
340 fn test_stderr() {
341 super::libc_eprintln!("stderr fd = {}", super::__LIBC_STDERR);
342 }
343
344 #[test]
345 fn test_stdout_write() {
346 super::libc_writeln!("stdout!");
347 }
348
349 #[test]
350 fn test_stderr_write() {
351 super::libc_ewriteln!("stderr!");
352 }
353
354 #[test]
355 fn test_dbg() {
356 let a = 2;
357 let b = libc_dbg!(a * 2) + 1;
358 assert_eq!(b, 5);
359 }
360
361 #[test]
362 fn test_in_closure_expression() {
363 use super::std_name::*;
364 let _ = Result::<(), ()>::Ok(()).unwrap_or_else(|err| eprintln!("error: {:?}", err));
366 }
367}