Reputation: 10417
It seems that write!
doe not write an argument when the buffer size is inadequate.
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);
}
Output:
an error occurred when formatting an argument
0123456789
However, I want to write a formatted string as long as possible, up to the buffer size. In above example, my desired output is 0123456789012345
.
In C, we can use snprintf
to accomplish this.
#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'
}
How can I do this in rust?
Upvotes: 3
Views: 1051
Reputation: 98368
You can write your own adaptor for the trait. Something like this:
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(())
}
}
To use it just wrap a mutable reference of your original writer:
write!(FixedWriter(&mut s), "{}{}", "0123456789", "0123456789");
You can check this playground, that prints 0123456789012345
.
You could also eat the error to simulate a success, by replacing the ?
operator with:
if self.0.write_char(c).is_err() {
break;
}
, but it is not clear from the question if you need this.
Upvotes: 5