blonk
November 11, 2020, 12:36am
1
I have a function which may generate a small buffer. The caller can:
not care about this buffer
want the buffer (String)
want to store the buffer to a file
How would you go about accomplishing this?
My first thought was something like:
fn do_something<T: SomeWriterTrait>(out: Option<T>) {
if let Some(out) = out {
out.write(the_buffer);
}
}
But I'm unsure what trait I should be using which can write to something that can be extracted as a String
as well as be written to a file.
Any tips?
Yandros
November 11, 2020, 1:29am
2
Best solution is to use ::std::
io
::Write
, but then you won't be able to use String
directly since it requires the emitted / written bytes be valid UTF-8, which is not something the io::Write
trait requires or enforces.
So you need to drop the String
requirement, and use a Vec<u8>
instead. Later on, if you want back a String
, you can upgrade the Vec<u8>
back to a String
using one of the functions dedicated to that purpose (which either fail or perform a lossy conversion when encountering invalid UTF-8 sequences):
use ::std::string::FromUtf8Error; // Contains the `Vec<u8>` inside.
trait StringWithMutBytes {
fn with_mut_bytes<R> (
self: &'_ mut Self,
f: impl FnOnce(&'_ mut Vec<u8>) -> R,
) -> Result<(), FromUtf8Error>
;
}
impl StringWithMutBytes for String {
fn with_mut_bytes<R> (
self: &'_ mut Self,
f: impl FnOnce(&'_ mut Vec<u8>) -> R,
) -> Result<R, Vec<u8>>
{
let mut vec: Vec<u8> = ::core::mem::take(self).into();
let ret = f(&mut vec);
*self = String::from_utf8(vec)?;
Ok(ret)
}
}
this way, you can write:
use ::std::io;
fn do_something (out: &'_ mut dyn io::Write)
-> io::Result<()>
{
let the_buffer = b"World!";
out.write_all(the_buffer)
}
Possible callers:
// String
let mut s = String::new("Hello, ");
s.with_mut_bytes(|v| Ok({
do_something(v)?;
}))??;
assert_eq!(s, "Hello, World!");
// File
let mut file = File::create("…");
do_something(&mut file)?;
drop(file);
assert_eq!(::std::fs::read_to_string("…")?, "World!");
// Dummy
do_something(&mut io::sink()); // dummy out
1 Like
system
Closed
February 9, 2021, 1:29am
3
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.