kernel_print/
lib.rs

1//! Implements the `print!`, `println!` and `dbg!` macros so they can be used in the kernel without the use of an allocator.
2//!
3//! By default the macros are prefixed with `kernel_`. If you want to remove the prefix, you can enable the `std_name` feature.
4//!
5//! ## Usage
6//!
7//! Exactly as you'd use the original macros from the standard library.
8//!
9//! ```no_run
10//! #![no_std]
11//!
12//! // ...
13//!
14//! kernel_dbg!(2 + 2);
15//! kernel_print!("{} + {} = {}\n", 2, 2, 2 + 2);
16//! kernel_println!("{} + {} = {}", 2, 2, 2 + 2);
17//! ```
18//!
19//! ## Features
20//!
21//! - `std_name`: Allows you to use the macros without the `kernel_` prefix.
22//! - `format`: Uses the `format!` macro instead of the `core::fmt::Write` trait to convert the passed data into a string.
23
24#![no_std]
25
26extern crate alloc;
27
28#[doc(hidden)]
29pub mod writer;
30
31#[cfg(feature = "std_name")]
32#[doc(hidden)]
33pub mod std_name {
34    pub use super::kernel_dbg as dbg;
35    pub use super::kernel_print as print;
36    pub use super::kernel_println as println;
37}
38
39#[cfg(feature = "std_name")]
40pub use std_name::*;
41
42/// Macro for printing the value of a given expression for quick and dirty debugging.
43///
44/// Does not panic on failure to write - instead silently ignores errors.
45///
46/// See [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) for full documentation.
47#[macro_export]
48macro_rules! kernel_dbg {
49    () => {
50        $crate::kernel_println!("[{}:{}]", file!(), line!());
51    };
52    ($val:expr) => {
53        // Use of `match` here is intentional because it affects the lifetimes
54        // of temporaries - https://stackoverflow.com/a/48732525/1063961
55        match $val {
56            tmp => {
57                $crate::kernel_println!("[{}:{}] {} = {:#?}",
58                    file!(), line!(), stringify!($val), &tmp);
59                tmp
60            }
61        }
62    };
63    // Trailing comma with single argument is ignored
64    ($val:expr,) => { $crate::kernel_dbg!($val) };
65    ($($val:expr),+ $(,)?) => {
66        ($($crate::kernel_dbg!($val)),+,)
67    };
68}
69
70/// Prints to the standard output.
71///
72/// Does not panic on failure to write - instead silently ignores errors.
73///
74/// See [`print!`](https://doc.rust-lang.org/std/macro.print.html) for full documentation.
75#[macro_export]
76macro_rules! kernel_print {
77    ($($arg:tt)*) => {
78        $crate::__impl_print!($($arg)*);
79    };
80}
81
82#[cfg(not(feature = "format"))]
83#[macro_export]
84#[doc(hidden)]
85macro_rules! __impl_print {
86    ($($arg:tt)*) => {
87        {
88            let mut writer = $crate::writer::KernelWriter::new();
89            let _ = writer.write_fmt(format_args!($($arg)*));
90        }
91    };
92}
93
94#[cfg(feature = "format")]
95#[macro_export]
96#[doc(hidden)]
97macro_rules! __impl_print {
98    ($($arg:tt)*) => {
99        {
100            let out = alloc::format!($($arg)*);
101            let _ = $crate::writer::__kernel_println(out);
102        }
103    };
104}
105
106/// Prints to the standard output, with a newline.
107///
108/// Does not panic on failure to write - instead silently ignores errors.
109///
110/// See [`println!`](https://doc.rust-lang.org/std/macro.println.html) for full documentation.
111#[macro_export]
112macro_rules! kernel_println {
113    () => {
114        $crate::kernel_println!("")
115    };
116    ($($arg:tt)*) => {
117        $crate::__impl_println!($($arg)*);
118    };
119}
120
121#[cfg(not(feature = "format"))]
122#[macro_export]
123#[doc(hidden)]
124macro_rules! __impl_println {
125    ($($arg:tt)*) => {
126        {
127            let mut writer = $crate::writer::KernelWriter::new();
128            let _ = writer.write_fmt(format_args!($($arg)*));
129            let _ = writer.write_nl();
130        }
131    };
132}
133
134#[cfg(feature = "format")]
135#[macro_export]
136#[doc(hidden)]
137macro_rules! __impl_println {
138    ($($arg:tt)*) => {
139        {
140            let out = {
141                let mut out = alloc::format!($($arg)*);
142                out.push('\n');
143                out
144            };
145            let _ = $crate::writer::__kernel_println(out);
146        }
147    };
148}