1#![no_std]
43#![allow(dead_code)]
44#![allow(unused)]
45#![warn(unsafe_op_in_unsafe_fn)]
46
47use core::{convert::TryFrom, file, line, stringify};
48
49#[cfg(not(windows))]
51#[link(name = "c")]
52mod c {
53 extern "C" {}
54}
55
56#[doc(hidden)]
59pub const __LIBC_NEWLINE: &str = "\n";
60#[doc(hidden)]
61pub const __LIBC_STDOUT: i32 = 1;
62#[doc(hidden)]
63pub const __LIBC_STDERR: i32 = 2;
64
65#[doc(hidden)]
66pub struct __LibCWriter(i32);
67
68impl core::fmt::Write for __LibCWriter {
69 #[inline]
70 fn write_str(&mut self, s: &str) -> core::fmt::Result {
71 __libc_println(self.0, s)
72 }
73}
74
75impl __LibCWriter {
76 #[inline]
77 pub fn new(handle: i32) -> __LibCWriter {
78 __LibCWriter(handle)
79 }
80
81 #[inline]
82 pub fn write_fmt(&mut self, args: core::fmt::Arguments) -> core::fmt::Result {
83 core::fmt::Write::write_fmt(self, args)
84 }
85
86 #[inline]
87 pub fn write_str(&mut self, s: &str) -> core::fmt::Result {
88 __libc_println(self.0, s)
89 }
90
91 #[inline]
92 pub fn write_nl(&mut self) -> core::fmt::Result {
93 __libc_println(self.0, __LIBC_NEWLINE)
94 }
95}
96
97#[doc(hidden)]
98#[inline]
99pub fn __libc_println(handle: i32, msg: &str) -> core::fmt::Result {
100 let msg = msg.as_bytes();
101
102 let mut written = 0;
103 while written < msg.len() {
104 match unsafe { libc_write(handle, &msg[written..]) } {
105 None | Some(0) => break,
107 Some(res) => written += res,
108 }
109 }
110
111 Ok(())
112}
113
114#[cfg(not(windows))]
115unsafe fn libc_write(handle: i32, bytes: &[u8]) -> Option<usize> {
116 usize::try_from(unsafe {
117 libc::write(
118 handle,
119 bytes.as_ptr().cast::<core::ffi::c_void>(),
120 bytes.len(),
121 )
122 })
123 .ok()
124}
125
126#[cfg(windows)]
127unsafe fn libc_write(handle: i32, bytes: &[u8]) -> Option<usize> {
128 usize::try_from(unsafe {
129 libc::write(
130 handle,
131 bytes.as_ptr().cast::<core::ffi::c_void>(),
132 libc::c_uint::try_from(bytes.len()).unwrap_or(libc::c_uint::MAX),
133 )
134 })
135 .ok()
136}
137
138#[macro_export]
148macro_rules! libc_println {
149 () => { $crate::libc_println!("") };
150 ($($arg:tt)*) => {
151 {
152 #[allow(unused_must_use)]
153 {
154 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDOUT);
155 stm.write_fmt(format_args!($($arg)*));
156 stm.write_nl();
157 }
158 }
159 };
160}
161
162#[macro_export]
172macro_rules! libc_print {
173 ($($arg:tt)*) => {
174 {
175 #[allow(unused_must_use)]
176 {
177 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDOUT);
178 stm.write_fmt(format_args!($($arg)*));
179 }
180 }
181 };
182}
183
184#[macro_export]
194macro_rules! libc_eprintln {
195 () => { $crate::libc_eprintln!("") };
196 ($($arg:tt)*) => {
197 {
198 #[allow(unused_must_use)]
199 {
200 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDERR);
201 stm.write_fmt(format_args!($($arg)*));
202 stm.write_nl();
203 }
204 }
205 };
206}
207
208#[macro_export]
218macro_rules! libc_eprint {
219 ($($arg:tt)*) => {
220 {
221 #[allow(unused_must_use)]
222 {
223 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDERR);
224 stm.write_fmt(format_args!($($arg)*));
225 }
226 }
227 };
228}
229
230#[macro_export]
234macro_rules! libc_write {
235 ($arg:expr) => {
236 #[allow(unused_must_use)]
237 {
238 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDOUT);
239 stm.write_str($arg);
240 }
241 };
242}
243
244#[macro_export]
248macro_rules! libc_ewrite {
249 ($arg:expr) => {
250 {
251 #[allow(unused_must_use)]
252 {
253 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDERR);
254 stm.write_str($arg);
255 }
256 }
257 };
258}
259
260#[macro_export]
264macro_rules! libc_writeln {
265 ($arg:expr) => {
266 #[allow(unused_must_use)]
267 {
268 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDOUT);
269 stm.write_str($arg);
270 stm.write_nl();
271 }
272 };
273}
274
275#[macro_export]
279macro_rules! libc_ewriteln {
280 ($arg:expr) => {
281 {
282 #[allow(unused_must_use)]
283 {
284 let mut stm = $crate::__LibCWriter::new($crate::__LIBC_STDERR);
285 stm.write_str($arg);
286 stm.write_nl();
287 }
288 }
289 };
290}
291
292#[macro_export]
309macro_rules! libc_dbg {
310 () => {
311 $crate::libc_eprintln!("[{}:{}]", $file!(), $line!())
312 };
313 ($val:expr $(,)?) => {
314 match $val {
315 tmp => {
316 $crate::libc_eprintln!("[{}:{}] {} = {:#?}", file!(), line!(), stringify!($val), &tmp);
317 tmp
318 }
319 }
320 };
321 ($($val:expr),+ $(,)?) => {
322 ($($crate::libc_dbg!($val)),+,)
323 };
324}
325
326pub mod std_name {
329 pub use super::libc_dbg as dbg;
330 pub use super::libc_eprint as eprint;
331 pub use super::libc_eprintln as eprintln;
332 pub use super::libc_print as print;
333 pub use super::libc_println as println;
334
335 #[cfg(test)]
336 mod tests_std_name {
337 use super::{eprintln, println};
338
339 #[test]
340 fn test_stdout() {
341 println!("stdout fd = {}", crate::__LIBC_STDOUT);
342 }
343
344 #[test]
345 fn test_stderr() {
346 eprintln!("stderr fd = {}", crate::__LIBC_STDERR);
347 }
348 }
349}
350
351#[cfg(test)]
352mod tests {
353 #[test]
354 fn test_stdout() {
355 super::libc_println!("stdout fd = {}", super::__LIBC_STDOUT);
356 }
357
358 #[test]
359 fn test_stderr() {
360 super::libc_eprintln!("stderr fd = {}", super::__LIBC_STDERR);
361 }
362
363 #[test]
364 fn test_stdout_write() {
365 super::libc_writeln!("stdout!");
366 }
367
368 #[test]
369 fn test_stderr_write() {
370 super::libc_ewriteln!("stderr!");
371 }
372
373 #[test]
374 fn test_dbg() {
375 let a = 2;
376 let b = libc_dbg!(a * 2) + 1;
377 assert_eq!(b, 5);
378 }
379
380 #[test]
381 fn test_in_closure_expression() {
382 use super::std_name::*;
383 let _ = Result::<(), ()>::Ok(()).unwrap_or_else(|err| eprintln!("error: {:?}", err));
385 }
386}