Closed 17dec closed 5 years ago
Unfortunately io::Write
is not a good fit for base-58 as it is not a streaming encoding, you cannot output the first byte until you have processed the entire input. So writing to an io::Write
would require allocating a temporary buffer to do the encoding into then writing the result into the io::Write
. I also want there to be a roadblock in front of users that may be considering using base-58 for large amounts of data, because it's non-streaming it's a very bad encoding to use for these use-cases. The intended use is for short identifiers that must be encoded into format that humans can easily compare and notice discrepancies between.
What I think would make sense for encoding into a stack allocated buffer is adding two additional output functions:
impl EncodeBuilder {
pub fn into_slice(self, output: &mut [u8]) -> Result<usize, BufferTooSmall>;
pub fn into_str(self, output: &mut str) -> Result<usize, BufferTooSmall>;
}
(or something similar to those). It should be possible to make the low-level implementation work over &mut [u8]
and have the other functions delegate to that with a little (unsafe) conversion of their input.
Thanks for the quick response. That makes sense. The &mut [u8]
version would work well for me.
Great, I probably won't have time to work on this anytime soon but would happily accept a PR for it.
Currently the only way to avoid allocating memory while encoding is to use EncodeBuilder::into(), but this requires a String, which still requires allocation when called from a (nested) function that doesn't happen to have an unused String buffer.
The Write trait is more generic and can be used to write to a stack-allocated buffer. It can also be passed other objects. This can be used, for example, for an efficient implementation of the Display trait for a data type that should be represented in Base58 - this implementation could pass the std::fmt::Formatter directly to the encoder.