我该如何在Rust中以缓冲区大小为限制写入格式化字符串?

3

当缓冲区大小不足时,write!似乎不会写入参数。

use std::fmt::Write;
use arrayvec::ArrayString; // 'arrayvec' crate

fn main() {
    const SIZE: usize = 16;
    let mut s = ArrayString::<SIZE>::new();
    match write!(s, "{}{}", "0123456789", "0123456789") {
        Ok(_) => println!("success!"),
        Err(err) => println!("{}", err),
    }
    println!("{}", s);
}

输出:

an error occurred when formatting an argument
0123456789

然而,我想尽可能长地编写格式化字符串,直到达到缓冲区大小。在上面的例子中,我的期望输出是0123456789012345
在C语言中,我们可以使用snprintf来实现此目的。
#include <stdio.h>
#include <stdlib.h>

int main() {
    char buf[16];
    snprintf(buf, 16, "%s%s", "0123456789", "0123456789");
    printf("%s\n", buf); // output is "012345678901234", due to '\0'
}

我该如何使用Rust完成这个操作?

1个回答

5
你可以编写自己的适配器来实现这个特性。类似这样:

struct FixedWriter<'a, W>(&'a mut W);

impl<'a, W: Write> Write for FixedWriter<'a, W> {
    fn write_str(&mut self, s: &str) -> Result<(), std::fmt::Error> {
        for c in s.chars() {
            self.0.write_char(c)?;
        }
        Ok(())
    } 
}

要使用它,只需将原始writer的可变引用包装起来:

write!(FixedWriter(&mut s), "{}{}", "0123456789", "0123456789");

您可以查看这个playground,它会输出0123456789012345

您也可以忽略错误以模拟成功,只需用以下代码替换?运算符:

if self.0.write_char(c).is_err() {
    break;
}

但从问题中并不清楚你是否需要这个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接