Skip to content

Commit a21202e

Browse files
Merge pull request #152 from rvolgers/owned_reader
Make DecoderReader own its inner reader
2 parents 59225b7 + bde33d8 commit a21202e

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

src/read/decoder.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ const DECODED_CHUNK_SIZE: usize = 3;
2929
/// assert_eq!(b"asdf", &result[..]);
3030
///
3131
/// ```
32-
pub struct DecoderReader<'a, R: 'a + io::Read> {
32+
pub struct DecoderReader<R: io::Read> {
3333
config: Config,
3434
/// Where b64 data is read from
35-
r: &'a mut R,
35+
inner: R,
3636

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

57-
impl<'a, R: io::Read> fmt::Debug for DecoderReader<'a, R> {
57+
impl<R: io::Read> fmt::Debug for DecoderReader<R> {
5858
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5959
f.debug_struct("DecoderReader")
6060
.field("config", &self.config)
@@ -68,12 +68,12 @@ impl<'a, R: io::Read> fmt::Debug for DecoderReader<'a, R> {
6868
}
6969
}
7070

71-
impl<'a, R: io::Read> DecoderReader<'a, R> {
72-
/// Create a new decoder that will read from the provided reader `r`.
73-
pub fn new(r: &'a mut R, config: Config) -> Self {
71+
impl<R: io::Read> DecoderReader<R> {
72+
/// Create a new decoder that will read from the provided reader.
73+
pub fn new(reader: R, config: Config) -> Self {
7474
DecoderReader {
7575
config,
76-
r,
76+
inner: reader,
7777
b64_buffer: [0; BUF_SIZE],
7878
b64_offset: 0,
7979
b64_len: 0,
@@ -114,7 +114,7 @@ impl<'a, R: io::Read> DecoderReader<'a, R> {
114114
debug_assert!(self.b64_offset + self.b64_len < BUF_SIZE);
115115

116116
let read = self
117-
.r
117+
.inner
118118
.read(&mut self.b64_buffer[self.b64_offset + self.b64_len..])?;
119119
self.b64_len += read;
120120

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

157157
Ok(decoded)
158158
}
159+
160+
/// Unwraps this `DecoderReader`, returning the base reader which it reads base64 encoded
161+
/// input from.
162+
///
163+
/// Because `DecoderReader` performs internal buffering, the state of the inner reader is
164+
/// unspecified. This function is mainly provided because the inner reader type may provide
165+
/// additional functionality beyond the `Read` implementation which may still be useful.
166+
pub fn into_inner(self) -> R {
167+
self.inner
168+
}
159169
}
160170

161-
impl<'a, R: Read> Read for DecoderReader<'a, R> {
171+
impl<R: Read> Read for DecoderReader<R> {
162172
/// Decode input from the wrapped reader.
163173
///
164174
/// Under non-error circumstances, this returns `Ok` with the value being the number of bytes

src/write/encoder.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,25 @@ impl<W: Write> EncoderWriter<W> {
215215
debug_assert_eq!(0, self.output_occupied_len);
216216
Ok(())
217217
}
218+
219+
/// Unwraps this `EncoderWriter`, returning the base writer it writes base64 encoded output
220+
/// to.
221+
///
222+
/// Normally this method should not be needed, since `finish()` returns the inner writer if
223+
/// it completes successfully. That will also ensure all data has been flushed, which the
224+
/// `into_inner()` function does *not* do.
225+
///
226+
/// Calling this method after `finish()` has completed successfully will panic, since the
227+
/// writer has already been returned.
228+
///
229+
/// This method may be useful if the writer implements additional APIs beyond the `Write`
230+
/// trait. Note that the inner writer might be in an error state or have an incomplete
231+
/// base64 string written to it.
232+
pub fn into_inner(mut self) -> W {
233+
self.delegate
234+
.take()
235+
.expect("Encoder has already had finish() called")
236+
}
218237
}
219238

220239
impl<W: Write> Write for EncoderWriter<W> {

0 commit comments

Comments
 (0)