pub struct EncoderWriter<'e, E: Engine, W: Write> {
    engine: &'e E,
    delegate: Option<W>,
    extra_input: [u8; 3],
    extra_input_occupied_len: usize,
    output: [u8; 1024],
    output_occupied_len: usize,
    panicked: bool,
}
Expand description

A Write implementation that base64 encodes data before delegating to the wrapped writer.

Because base64 has special handling for the end of the input data (padding, etc), there’s a finish() method on this type that encodes any leftover input bytes and adds padding if appropriate. It’s called automatically when deallocated (see the Drop implementation), but any error that occurs when invoking the underlying writer will be suppressed. If you want to handle such errors, call finish() yourself.

Examples

use std::io::Write;
use base64::engine::general_purpose;

// use a vec as the simplest possible `Write` -- in real code this is probably a file, etc.
let mut enc = base64::write::EncoderWriter::new(Vec::new(), &general_purpose::STANDARD);

// handle errors as you normally would
enc.write_all(b"asdf").unwrap();

// could leave this out to be called by Drop, if you don't care
// about handling errors or getting the delegate writer back
let delegate = enc.finish().unwrap();

// base64 was written to the writer
assert_eq!(b"YXNkZg==", &delegate[..]);

Panics

Calling write() (or related methods) or finish() after finish() has completed without error is invalid and will panic.

Errors

Base64 encoding itself does not generate errors, but errors from the wrapped writer will be returned as per the contract of Write.

Performance

It has some minor performance loss compared to encoding slices (a couple percent). It does not do any heap allocation.

Limitations

Owing to the specification of the write and flush methods on the Write trait and their implications for a buffering implementation, these methods may not behave as expected. In particular, calling write_all on this interface may fail with io::ErrorKind::WriteZero. See the documentation of the Write trait implementation for further details.

Fields§

§engine: &'e E§delegate: Option<W>

Where encoded data is written to. It’s an Option as it’s None immediately before Drop is called so that finish() can return the underlying writer. None implies that finish() has been called successfully.

§extra_input: [u8; 3]

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_input_occupied_len: usize

How much of extra is occupied, in [0, MIN_ENCODE_CHUNK_SIZE].

§output: [u8; 1024]

Buffer to encode into. May hold leftover encoded bytes from a previous write call that the underlying writer did not write last time.

§output_occupied_len: usize

How much of output is occupied with encoded data that couldn’t be written last time

§panicked: bool

panic safety: don’t write again in destructor if writer panicked while we were writing to it

Implementations§

source§

impl<'e, E: Engine, W: Write> EncoderWriter<'e, E, W>

source

pub fn new(delegate: W, engine: &'e E) -> EncoderWriter<'e, E, W>

Create a new encoder that will write to the provided delegate writer.

source

pub fn finish(&mut self) -> Result<W>

Encode all remaining buffered data and write it, including any trailing incomplete input triples and associated padding.

Once this succeeds, no further writes or calls to this method are allowed.

This may write to the delegate writer multiple times if the delegate writer does not accept all input provided to its write each invocation.

If you don’t care about error handling, it is not necessary to call this function, as the equivalent finalization is done by the Drop impl.

Returns the writer that this was constructed around.

Errors

The first error that is not of ErrorKind::Interrupted will be returned.

source

fn write_final_leftovers(&mut self) -> Result<()>

Write any remaining buffered data to the delegate writer.

source

fn write_to_delegate(&mut self, current_output_len: usize) -> Result<()>

Write as much of the encoded output to the delegate writer as it will accept, and store the leftovers to be attempted at the next write() call. Updates self.output_occupied_len.

Errors

Errors from the delegate writer are returned. In the case of an error, self.output_occupied_len will not be updated, as errors from write are specified to mean that no write took place.

source

fn write_all_encoded_output(&mut self) -> Result<()>

Write all buffered encoded output. If this returns Ok, self.output_occupied_len is 0.

This is basically write_all for the remaining buffered data but without the undesirable abort-on-Ok(0) behavior.

Errors

Any error emitted by the delegate writer abort the write loop and is returned, unless it’s Interrupted, in which case the error is ignored and writes will continue.

source

pub fn into_inner(self) -> W

Unwraps this EncoderWriter, returning the base writer it writes base64 encoded output to.

Normally this method should not be needed, since finish() returns the inner writer if it completes successfully. That will also ensure all data has been flushed, which the into_inner() function does not do.

Calling this method after finish() has completed successfully will panic, since the writer has already been returned.

This method may be useful if the writer implements additional APIs beyond the Write trait. Note that the inner writer might be in an error state or have an incomplete base64 string written to it.

Trait Implementations§

source§

impl<'e, E: Engine, W: Write> Debug for EncoderWriter<'e, E, W>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'e, E: Engine, W: Write> Drop for EncoderWriter<'e, E, W>

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl<'e, E: Engine, W: Write> Write for EncoderWriter<'e, E, W>

source§

fn write(&mut self, input: &[u8]) -> Result<usize>

Encode input and then write to the delegate writer.

Under non-error circumstances, this returns Ok with the value being the number of bytes of input consumed. The value may be 0, which interacts poorly with write_all, which interprets Ok(0) as an error, despite it being allowed by the contract of write. See https://github.com/rust-lang/rust/issues/56889 for more on that.

If the previous call to write provided more (encoded) data than the delegate writer could accept in a single call to its write, the remaining data is buffered. As long as buffered data is present, subsequent calls to write will try to write the remaining buffered data to the delegate and return either Ok(0) – and therefore not consume any of input – or an error.

Errors

Any errors emitted by the delegate writer are returned.

source§

fn flush(&mut self) -> Result<()>

Because this is usually treated as OK to call multiple times, it will not flush any incomplete chunks of input or write padding.

Errors

The first error that is not of ErrorKind::Interrupted will be returned.

1.36.0 · source§

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize, Error>

Like write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

🔬This is a nightly-only experimental API. (can_vector)
Determines if this Writer has an efficient write_vectored implementation. Read more
1.0.0 · source§

fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>

Attempts to write an entire buffer into this writer. Read more
source§

fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>

🔬This is a nightly-only experimental API. (write_all_vectored)
Attempts to write multiple buffers into this writer. Read more
1.0.0 · source§

fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<(), Error>

Writes a formatted string into this writer, returning any error encountered. Read more
1.0.0 · source§

fn by_ref(&mut self) -> &mut Selfwhere Self: Sized,

Creates a “by reference” adapter for this instance of Write. Read more

Auto Trait Implementations§

§

impl<'e, E, W> RefUnwindSafe for EncoderWriter<'e, E, W>where E: RefUnwindSafe, W: RefUnwindSafe,

§

impl<'e, E, W> Send for EncoderWriter<'e, E, W>where W: Send,

§

impl<'e, E, W> Sync for EncoderWriter<'e, E, W>where W: Sync,

§

impl<'e, E, W> Unpin for EncoderWriter<'e, E, W>where W: Unpin,

§

impl<'e, E, W> UnwindSafe for EncoderWriter<'e, E, W>where E: RefUnwindSafe, W: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.