mirror of
https://gitee.com/openharmony/third_party_rust_rust-base64
synced 2024-12-11 15:05:35 +00:00
Add a finish() that writes padding, etc
This commit is contained in:
parent
effb6ed812
commit
9dfa4acf3f
@ -8,9 +8,15 @@ use {encode_config_slice, Config};
|
||||
pub struct Base64Encoder<'a> {
|
||||
config: Config,
|
||||
w: &'a mut Write,
|
||||
/// Holds a partial chunk, if any, after the last `write()`, so that we may then fill the chunk
|
||||
/// with the next `write()`, encode it, then proceed with the rest of the input normally.
|
||||
extra: [u8; 3],
|
||||
/// How much of `extra` is occupied.
|
||||
extra_len: usize,
|
||||
/// Buffer to encode into
|
||||
output: [u8; 1024],
|
||||
/// True iff padding / partial last chunk has been written.
|
||||
output_finished: bool,
|
||||
}
|
||||
|
||||
impl<'a> fmt::Debug for Base64Encoder<'a> {
|
||||
@ -36,12 +42,40 @@ impl<'a> Base64Encoder<'a> {
|
||||
extra: [0u8; 3], // extra data left over from previous write
|
||||
extra_len: 0, // how much extra data
|
||||
output: [0u8; 1024], // output buffer
|
||||
output_finished: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Flush all buffered data, including any padding or trailing incomplete triples.
|
||||
///
|
||||
/// Once this is called, no further writes can be performed.
|
||||
pub fn finish(&mut self) -> Result<()> {
|
||||
if self.output_finished {
|
||||
// TODO disallow subsequent writes?
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
self.output_finished = true;
|
||||
|
||||
if self.extra_len > 0 {
|
||||
let sz = encode_config_slice(
|
||||
&self.extra[..self.extra_len],
|
||||
self.config,
|
||||
&mut self.output[..],
|
||||
);
|
||||
let _ = self.w.write(&self.output[..sz])?;
|
||||
}
|
||||
|
||||
self.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Write for Base64Encoder<'a> {
|
||||
fn write(&mut self, input: &[u8]) -> Result<usize> {
|
||||
if self.output_finished {
|
||||
panic!("Cannot write more after writing the trailing padding/partial chunk");
|
||||
}
|
||||
|
||||
// TODO handle line breaks
|
||||
let mut input = input;
|
||||
let mut input_read_cnt = 0;
|
||||
@ -98,21 +132,20 @@ impl<'a> Write for Base64Encoder<'a> {
|
||||
return Ok(input_read_cnt);
|
||||
}
|
||||
|
||||
/// Because this is usually treated as OK to call multiple times, it will *not* flush any
|
||||
/// incomplete chunks of input or write padding.
|
||||
fn flush(&mut self) -> Result<()> {
|
||||
if self.extra_len > 0 {
|
||||
// TODO should not write padding on each flush() -- should be able to flush() > 1x
|
||||
let sz = encode_config_slice(
|
||||
&self.extra[..self.extra_len],
|
||||
self.config,
|
||||
&mut self.output[..],
|
||||
);
|
||||
let _ = self.w.write(&self.output[..sz])?;
|
||||
}
|
||||
|
||||
self.w.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for Base64Encoder<'a> {
|
||||
fn drop(&mut self) {
|
||||
// TODO error handling?
|
||||
let _ = self.finish();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate rand;
|
||||
@ -157,7 +190,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_one_two() {
|
||||
fn encode_one_then_two_bytes() {
|
||||
let mut c = Cursor::new(Vec::new());
|
||||
{
|
||||
let mut enc = Base64Encoder::new(&mut c, URL_SAFE);
|
||||
@ -171,7 +204,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_one_five() {
|
||||
fn encode_one_then_five_bytes() {
|
||||
let mut c = Cursor::new(Vec::new());
|
||||
{
|
||||
let mut enc = Base64Encoder::new(&mut c, URL_SAFE);
|
||||
@ -188,7 +221,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_1_2_3() {
|
||||
fn encode_1_2_3_bytes() {
|
||||
let mut c = Cursor::new(Vec::new());
|
||||
{
|
||||
let mut enc = Base64Encoder::new(&mut c, URL_SAFE);
|
||||
@ -239,6 +272,26 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finish_writes_extra_byte() {
|
||||
let mut c = Cursor::new(Vec::new());
|
||||
{
|
||||
let mut enc = Base64Encoder::new(&mut c, URL_SAFE);
|
||||
|
||||
assert_eq!(6, enc.write(b"abcdef").unwrap());
|
||||
|
||||
// will be in extra
|
||||
assert_eq!(1, enc.write(b"g").unwrap());
|
||||
|
||||
// 1 trailing byte = 2 encoded chars
|
||||
let _ = enc.finish().unwrap();
|
||||
}
|
||||
assert_eq!(
|
||||
&c.get_ref()[..],
|
||||
encode_config("abcdefg", URL_SAFE).as_bytes()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_random_config_matches_normal_encode() {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
Loading…
Reference in New Issue
Block a user