Description
Would it be possible to add a method like Encoding::encode_mut
except have it return &str
instead of ()
? The purpose of such a method would be to allow for downstream code to use stack-allocated strings without having to use unsafe
code or call core::str::from_utf8
and incur unnecessary overhead of UTF-8 validation.
Essentially the method would look similar to below with possible changes to call str::from_utf8_unchecked
on a sub-slice of output
in the event it's not guaranteed the entirety of output
would be written to:
pub fn encode_mut_str<'a: 'b, 'b>(&self, input: &[u8], output: &'a mut [u8]) -> &'b str {
self.encode_mut(input, output);
// SAFETY:
// Encoded data is always valid UTF-8.
unsafe { str::from_utf8_unchecked(output) }
}
Currently downstream code is forced to do either
use data_encoding::BASE64URL_NOPAD;
pub fn foo() {
let input = [0];
let mut output = [0; 2];
BASE64URL_NOPAD.encode_mut(input.as_slice(), output.as_mut_slice());
// SAFETY:
// `data_encoding::Encoding::encode_mut` always encodes UTF-8 data.
let val = unsafe { str::from_utf8_unchecked(output.as_slice()) };
}
or
use data_encoding::BASE64URL_NOPAD;
pub fn foo() {
let input = [0];
let mut output = [0; 2];
BASE64URL_NOPAD.encode_mut(input.as_slice(), output.as_mut_slice());
let val = str::from_utf8(output.as_slice()).unwrap_or_else(|_e| unreachable!("there is a bug in data_encoding::Encoding::encode_mut"));
}
With encode_mut_str
, then the above could be written like:
use data_encoding::BASE64URL_NOPAD;
pub fn foo() {
let input = [0];
let mut output = [0; 2];
let val = BASE64URL_NOPAD.encode_mut_str(input.as_slice(), output.as_mut_slice());
}
When unsafe
code is used, it's a lot better for the code to be entirely localized and not have to rely on an external crate to uphold the safety invariants. I realize this can be considered micro-optimization, but I thought I'd ask.