为什么在传递参数时 fmt::Arguments as_str 不起作用?
Why does fmt::Arguments as_str not work when arguments are passed?
我正在用 no_std
为我的 OS 制作一个 VGA 打印宏,但由于某种原因无法正常工作。我正在使用 vga crate 这样我就不必自己完成所有 VGA 代码。我有一个名为 _print
:
的函数
use core::fmt::{Arguments, Write};
use vga::colors::Color16;
use vga::writers::{Graphics640x480x16, GraphicsWriter};
pub fn _print(args: Arguments) {
unsafe {
let mut i: usize = 0;
for (_offset, character) in args.as_str().unwrap().chars().enumerate() {
Mode.draw_character(CurrentTextX + i, CurrentTextY, character, CurrentTextColor);
i += 8;
}
}
}
然后我有一个名为 vprint!
的宏:
#[macro_export]
macro_rules! vprint {
($($arg:tt)*) => {
crate::videographicsarray::_print(format_args!($($arg)*));
};
}
我没有使用 alloc
。我看到过与此完全相同的代码,但由于某种原因我的代码不起作用。它显示我输入的文本,但如果我传递任何参数,它就会出现恐慌。我做错了什么?
您的代码会出现错误,因为如果没有参数,as_str()
只有 returns Some
。所以当你立即 unwrap()
它会恐慌,例如你有参数要格式化。
Get the formatted string, if it has no arguments to be formatted.
This can be used to avoid allocations in the most trivial case.
您可以使用 args.to_string()
代替 args.as_str().unwrap()
,将其格式化为 String
。所以它实际上是格式化的,不管有没有参数。
pub fn _print(args: Arguments) {
unsafe {
let mut i: usize = 0;
for (_offset, character) in args.to_string().chars().enumerate() {
Mode.draw_character(CurrentTextX + i, CurrentTextY, character, CurrentTextColor);
i += 8;
}
}
}
如果你想避免不必要的分配,那么你可以使用unwrap_or_else()
并且只做to_string()
如果 as_str()
returns None
。在包装 Cow
时避免将 &str
转换为 String
。
use std::borrow::Cow;
let formatted_str = args
.as_str()
.map(Cow::Borrowed)
.unwrap_or_else(|| Cow::Owned(args.to_string()));
no_std
因为您使用的是 no_std
而不是 alloc
箱子。然后你可以定义一个 u8
缓冲区来格式化。例如。使用 let buf = [u8; N];
,其中 N
足以 space 用于您的格式化字符串。
之后,您可以围绕 &mut [u8]
缓冲区实现自己的包装器,该缓冲区实现 core::fmt::Write
trait. You can use that wrapper along with with core::fmt::write()
.
您可以使用此答案中的 struct WriteTo
,而不是自己实施:
pub fn _print(args: Arguments) {
let mut buf = [0u8; 64];
let formatted_str: &str = write_to::show(&mut buf, args).unwrap();
unsafe {
let mut i: usize = 0;
for (_offset, _character) in formatted_str.chars().enumerate() {
Mode.draw_character(CurrentTextX + i, CurrentTextY, character, CurrentTextColor);
i += 8;
}
}
}
我正在用 no_std
为我的 OS 制作一个 VGA 打印宏,但由于某种原因无法正常工作。我正在使用 vga crate 这样我就不必自己完成所有 VGA 代码。我有一个名为 _print
:
use core::fmt::{Arguments, Write};
use vga::colors::Color16;
use vga::writers::{Graphics640x480x16, GraphicsWriter};
pub fn _print(args: Arguments) {
unsafe {
let mut i: usize = 0;
for (_offset, character) in args.as_str().unwrap().chars().enumerate() {
Mode.draw_character(CurrentTextX + i, CurrentTextY, character, CurrentTextColor);
i += 8;
}
}
}
然后我有一个名为 vprint!
的宏:
#[macro_export]
macro_rules! vprint {
($($arg:tt)*) => {
crate::videographicsarray::_print(format_args!($($arg)*));
};
}
我没有使用 alloc
。我看到过与此完全相同的代码,但由于某种原因我的代码不起作用。它显示我输入的文本,但如果我传递任何参数,它就会出现恐慌。我做错了什么?
您的代码会出现错误,因为如果没有参数,as_str()
只有 returns Some
。所以当你立即 unwrap()
它会恐慌,例如你有参数要格式化。
Get the formatted string, if it has no arguments to be formatted.
This can be used to avoid allocations in the most trivial case.
您可以使用 args.to_string()
代替 args.as_str().unwrap()
,将其格式化为 String
。所以它实际上是格式化的,不管有没有参数。
pub fn _print(args: Arguments) {
unsafe {
let mut i: usize = 0;
for (_offset, character) in args.to_string().chars().enumerate() {
Mode.draw_character(CurrentTextX + i, CurrentTextY, character, CurrentTextColor);
i += 8;
}
}
}
如果你想避免不必要的分配,那么你可以使用unwrap_or_else()
并且只做to_string()
如果 as_str()
returns None
。在包装 Cow
时避免将 &str
转换为 String
。
use std::borrow::Cow;
let formatted_str = args
.as_str()
.map(Cow::Borrowed)
.unwrap_or_else(|| Cow::Owned(args.to_string()));
no_std
因为您使用的是 no_std
而不是 alloc
箱子。然后你可以定义一个 u8
缓冲区来格式化。例如。使用 let buf = [u8; N];
,其中 N
足以 space 用于您的格式化字符串。
之后,您可以围绕 &mut [u8]
缓冲区实现自己的包装器,该缓冲区实现 core::fmt::Write
trait. You can use that wrapper along with with core::fmt::write()
.
您可以使用此答案中的 struct WriteTo
,而不是自己实施:
pub fn _print(args: Arguments) {
let mut buf = [0u8; 64];
let formatted_str: &str = write_to::show(&mut buf, args).unwrap();
unsafe {
let mut i: usize = 0;
for (_offset, _character) in formatted_str.chars().enumerate() {
Mode.draw_character(CurrentTextX + i, CurrentTextY, character, CurrentTextColor);
i += 8;
}
}
}