[英]How to test result of core::fmt::Display trait implementation in #![no_std] env
我有以下结构并想测试 Display trait 的实现:
use core::fmt::{Display, Formatter, Result};
struct B {}
impl Display for B {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(f, "A {} C", "B")
}
}
#[test]
fn it_works() {
assert_eq!(format!("{}", B {}), "A B C")
}
它在一般情况下有效,但是在#![no_std]
环境中,由于format!
缺少宏(它分配,因此不能在no_std
中使用)。
在no_std
场景中是否有惯用的方法来测试core::std::Display
特征? 我尝试使用自定义缓冲区实现创建自己的core::std::Formatter
实例以某种方式规避它,并直接测试fmt
方法,但实例化这种类型被认为是编译器内部的。
为什么不在自定义缓冲区上实现core::fmt::Write
并使用core::fmt::write!
给它?
format!
基本上是write!
到一个字符串缓冲区,两者都真正调用Write::write_fmt
, format!
具有它提供自己的(字符串)缓冲区并在错误时发生恐慌的便利。
macro_rules! write {
($dst:expr, $($arg:tt)*) => {
$dst.write_fmt($crate::format_args!($($arg)*))
};
}
macro_rules! format {
($($arg:tt)*) => {{
let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
res
}}
}
pub fn format(args: Arguments<'_>) -> string::String {
let capacity = args.estimated_capacity();
let mut output = string::String::with_capacity(capacity);
output.write_fmt(args).expect("a formatting trait implementation returned an error");
output
}
最好的选择是为测试启用标准:
#![cfg_attr(no_std, not(test))]
如果你做不到,并且你知道格式大小的上限,你可以为一个u8
数组包装器实现core::fmt::Write
并使用它。 arrayvec
已经为您提供了ArrayString
:
let mut formatted = ArrayString::<10>::new();
use core::fmt::Write;
write!(formatted, "{}", B {}).expect("failed to format, probably buffer too small");
assert_eq!(&formatted, "A B C")
游乐场。
正如@Masklinn 所提到的,只需实现core::fmt::Write
特征,就可以在没有分配和任何缓冲区的情况下做到这一点。
这是示例实现:
#![no_std]
use core::fmt::{Display, Formatter, Result, Write};
struct B {}
impl Display for B {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(f, "A {} C", "B")
}
}
struct Comparator<'a> {
valid: bool,
to_compare: &'a str
}
impl<'a> Comparator<'a> {
fn new(s: &'a str) -> Self {
Self { valid: true, to_compare: s }
}
fn is_valid(self) -> bool {
self.valid && self.to_compare.is_empty()
}
}
impl<'a> Write for Comparator<'a> {
fn write_str(&mut self, s: &str) -> Result {
if s.eq(self.to_compare) {
self.valid = self.valid && true;
self.to_compare = "";
return Ok(());
}
if self.to_compare.starts_with(s) && self.to_compare.len() >= s.len() {
self.to_compare = &self.to_compare[s.len()..];
} else {
self.valid = false
}
Ok(())
}
}
#[test]
fn it_works() {
let mut cmp = Comparator::new("A B C");
let _ = write!(&mut cmp, "{}", B{});
assert!(cmp.is_valid());
}
#[test]
fn too_short() {
let mut cmp = Comparator::new("A B");
let _ = write!(&mut cmp, "{}", B{});
assert!(!cmp.is_valid());
}
#[test]
fn too_long() {
let mut cmp = Comparator::new("A B C D");
let _ = write!(&mut cmp, "{}", B{});
assert!(!cmp.is_valid());
}
编辑:修复了代码中的错误,是:
if self.to_compare.starts_with(s) && self.to_compare.len() >= s.len() {
self.to_compare = &self.to_compare[s.len()..];
self.valid = true
} else {
self.valid = false
}
固定的:
if self.to_compare.starts_with(s) && self.to_compare.len() >= s.len() {
self.to_compare = &self.to_compare[s.len()..];
} else {
self.valid = false
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.