Skip to content

Commit

Permalink
Merge pull request #152 from rvolgers/owned_reader
Browse files Browse the repository at this point in the history
Make DecoderReader own its inner reader
  • Loading branch information
marshallpierce committed Feb 9, 2021
2 parents 59225b7 + bde33d8 commit a21202e
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 9 deletions.
28 changes: 19 additions & 9 deletions src/read/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ const DECODED_CHUNK_SIZE: usize = 3;
/// assert_eq!(b"asdf", &result[..]);
///
/// ```
pub struct DecoderReader<'a, R: 'a + io::Read> {
pub struct DecoderReader<R: io::Read> {
config: Config,
/// Where b64 data is read from
r: &'a mut R,
inner: R,

// Holds b64 data read from the delegate reader.
b64_buffer: [u8; BUF_SIZE],
Expand All @@ -54,7 +54,7 @@ pub struct DecoderReader<'a, R: 'a + io::Read> {
total_b64_decoded: usize,
}

impl<'a, R: io::Read> fmt::Debug for DecoderReader<'a, R> {
impl<R: io::Read> fmt::Debug for DecoderReader<R> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("DecoderReader")
.field("config", &self.config)
Expand All @@ -68,12 +68,12 @@ impl<'a, R: io::Read> fmt::Debug for DecoderReader<'a, R> {
}
}

impl<'a, R: io::Read> DecoderReader<'a, R> {
/// Create a new decoder that will read from the provided reader `r`.
pub fn new(r: &'a mut R, config: Config) -> Self {
impl<R: io::Read> DecoderReader<R> {
/// Create a new decoder that will read from the provided reader.
pub fn new(reader: R, config: Config) -> Self {
DecoderReader {
config,
r,
inner: reader,
b64_buffer: [0; BUF_SIZE],
b64_offset: 0,
b64_len: 0,
Expand Down Expand Up @@ -114,7 +114,7 @@ impl<'a, R: io::Read> DecoderReader<'a, R> {
debug_assert!(self.b64_offset + self.b64_len < BUF_SIZE);

let read = self
.r
.inner
.read(&mut self.b64_buffer[self.b64_offset + self.b64_len..])?;
self.b64_len += read;

Expand Down Expand Up @@ -156,9 +156,19 @@ impl<'a, R: io::Read> DecoderReader<'a, R> {

Ok(decoded)
}

/// Unwraps this `DecoderReader`, returning the base reader which it reads base64 encoded
/// input from.
///
/// Because `DecoderReader` performs internal buffering, the state of the inner reader is
/// unspecified. This function is mainly provided because the inner reader type may provide
/// additional functionality beyond the `Read` implementation which may still be useful.
pub fn into_inner(self) -> R {
self.inner
}
}

impl<'a, R: Read> Read for DecoderReader<'a, R> {
impl<R: Read> Read for DecoderReader<R> {
/// Decode input from the wrapped reader.
///
/// Under non-error circumstances, this returns `Ok` with the value being the number of bytes
Expand Down
19 changes: 19 additions & 0 deletions src/write/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,25 @@ impl<W: Write> EncoderWriter<W> {
debug_assert_eq!(0, self.output_occupied_len);
Ok(())
}

/// 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.
pub fn into_inner(mut self) -> W {
self.delegate
.take()
.expect("Encoder has already had finish() called")
}
}

impl<W: Write> Write for EncoderWriter<W> {
Expand Down

0 comments on commit a21202e

Please sign in to comment.