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}