rcore_console/
lib.rs

1//! 提供可定制实现的 `print!`、`println!` 和 `log::Log`。
2
3#![no_std]
4#![deny(warnings, missing_docs)]
5
6use core::{
7    fmt::{self, Write},
8    str::FromStr,
9};
10use spin::Once;
11
12/// 向用户提供 `log`。
13pub extern crate log;
14
15/// 这个接口定义了向控制台“输出”这件事。
16pub trait Console: Sync {
17    /// 向控制台放置一个字符。
18    fn put_char(&self, c: u8);
19
20    /// 向控制台放置一个字符串。
21    ///
22    /// 如果使用了锁,覆盖这个实现以免反复获取和释放锁。
23    #[inline]
24    fn put_str(&self, s: &str) {
25        for c in s.bytes() {
26            self.put_char(c);
27        }
28    }
29}
30
31/// 库找到输出的方法:保存一个对象引用,这是一种单例。
32static CONSOLE: Once<&'static dyn Console> = Once::new();
33
34/// 用户调用这个函数设置输出的方法。
35pub fn init_console(console: &'static dyn Console) {
36    CONSOLE.call_once(|| console);
37    log::set_logger(&Logger).unwrap();
38}
39
40/// 根据环境变量设置日志级别。
41pub fn set_log_level(env: Option<&str>) {
42    use log::LevelFilter as Lv;
43    log::set_max_level(env.and_then(|s| Lv::from_str(s).ok()).unwrap_or(Lv::Trace));
44}
45
46/// 打印一些测试信息。
47pub fn test_log() {
48    println!(
49        r"
50   ______                       __
51  / ____/___  ____  _________  / /__
52 / /   / __ \/ __ \/ ___/ __ \/ / _ \
53/ /___/ /_/ / / / (__  ) /_/ / /  __/
54\____/\____/_/ /_/____/\____/_/\___/
55===================================="
56    );
57    log::trace!("LOG TEST >> Hello, world!");
58    log::debug!("LOG TEST >> Hello, world!");
59    log::info!("LOG TEST >> Hello, world!");
60    log::warn!("LOG TEST >> Hello, world!");
61    log::error!("LOG TEST >> Hello, world!");
62    println!();
63}
64
65/// 打印。
66///
67/// 给宏用的,用户不会直接调它。
68#[doc(hidden)]
69#[inline]
70pub fn _print(args: fmt::Arguments) {
71    Logger.write_fmt(args).unwrap();
72}
73
74/// 格式化打印。
75#[macro_export]
76macro_rules! print {
77    ($($arg:tt)*) => {
78        $crate::_print(core::format_args!($($arg)*));
79    }
80}
81
82/// 格式化打印并换行。
83#[macro_export]
84macro_rules! println {
85    () => ($crate::print!("\n"));
86    ($($arg:tt)*) => {{
87        $crate::_print(core::format_args!($($arg)*));
88        $crate::println!();
89    }}
90}
91
92/// 这个 Unit struct 是 `core::fmt` 要求的。
93struct Logger;
94
95/// 实现 [`Write`] trait,格式化的基础。
96impl Write for Logger {
97    #[inline]
98    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
99        let _ = CONSOLE.get().unwrap().put_str(s);
100        Ok(())
101    }
102}
103
104/// 实现 `log::Log` trait,提供分级日志。
105impl log::Log for Logger {
106    #[inline]
107    fn enabled(&self, _metadata: &log::Metadata) -> bool {
108        true
109    }
110
111    #[inline]
112    fn log(&self, record: &log::Record) {
113        use log::Level::*;
114        let color_code: u8 = match record.level() {
115            Error => 31,
116            Warn => 93,
117            Info => 34,
118            Debug => 32,
119            Trace => 90,
120        };
121        println!(
122            "\x1b[{color_code}m[{:>5}] {}\x1b[0m",
123            record.level(),
124            record.args(),
125        );
126    }
127
128    fn flush(&self) {}
129}