Skip to content

Commit

Permalink
Don't call read_to_end to read a block of data
Browse files Browse the repository at this point in the history
Delegate to calling `read` at most one time instead. This requires initializing
all buffers ahead of time to maintain the safe code invariant, but the writer
abstractions can continue to use uninitialized memory (as miniz is known to not
read it, just write it).

Closes rust-lang#16
  • Loading branch information
alexcrichton committed Mar 2, 2015
1 parent b7e97dd commit 2077908
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 52 deletions.
10 changes: 6 additions & 4 deletions src/deflate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use std::io::prelude::*;
use std::io;
use std::iter::repeat;

use raw;

Expand Down Expand Up @@ -46,7 +47,7 @@ impl<W: Write> EncoderWriter<W> {
pub fn new(w: W, level: ::Compression) -> EncoderWriter<W> {
EncoderWriter {
inner: raw::EncoderWriter::new(w, level, true,
Vec::with_capacity(128 * 1024))
Vec::with_capacity(32 * 1024)),
}
}

Expand All @@ -71,7 +72,7 @@ impl<R: Read> EncoderReader<R> {
pub fn new(r: R, level: ::Compression) -> EncoderReader<R> {
EncoderReader {
inner: raw::EncoderReader::new(r, level, true,
Vec::with_capacity(128 * 1024))
repeat(0).take(32 * 1024).collect()),
}
}

Expand All @@ -89,7 +90,7 @@ impl<R: Read> DecoderReader<R> {
/// Creates a new decoder which will decompress data read from the given
/// stream.
pub fn new(r: R) -> DecoderReader<R> {
DecoderReader::new_with_buf(r, Vec::with_capacity(128 * 1024))
DecoderReader::new_with_buf(r, repeat(0).take(32 * 1024).collect())
}

/// Same as `new`, but the intermediate buffer for data is specified.
Expand All @@ -114,7 +115,8 @@ impl<W: Write> DecoderWriter<W> {
/// be flushed.
pub fn new(w: W) -> DecoderWriter<W> {
DecoderWriter {
inner: raw::DecoderWriter::new(w, true, Vec::with_capacity(128 * 1024))
inner: raw::DecoderWriter::new(w, true,
Vec::with_capacity(32 * 1024)),
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/gz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl Builder {
pub fn write<W: Write>(self, w: W, lvl: Compression) -> EncoderWriter<W> {
EncoderWriter {
inner: raw::EncoderWriter::new(w, lvl, true,
Vec::with_capacity(128 * 1024)),
Vec::with_capacity(32 * 1024)),
crc: Crc::new(),
header: self.into_header(lvl),
}
Expand All @@ -128,7 +128,7 @@ impl Builder {
let crc = CrcReader::new(r);
EncoderReader {
inner: raw::EncoderReader::new(crc, lvl, true,
Vec::with_capacity(128 * 1024)),
repeat(0).take(32 * 1024).collect()),
header: self.into_header(lvl),
pos: 0,
eof: false,
Expand Down Expand Up @@ -374,7 +374,7 @@ impl<R: Read> DecoderReader<R> {
}

let flate = raw::DecoderReader::new(crc_reader.into_inner(), true,
Vec::with_capacity(128 * 1024));
repeat(0).take(32 * 1024).collect());
return Ok(DecoderReader {
inner: CrcReader::new(flate),
header: Header {
Expand Down
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
//! These provide convenience methods for creating a decoder/encoder out of an
//! already existing stream to chain construction.
#![feature(io, core, collections, std_misc, env)]
#![feature(io, core, collections, std_misc)]
#![deny(missing_docs)]
#![feature(unsafe_destructor)]
// #![cfg_attr(test, deny(warnings))]
Expand All @@ -44,7 +44,6 @@ mod deflate;
mod gz;
mod raw;
mod zlib;
mod util;

/// Types which operate over `Reader` streams, both encoders and decoders for
/// various formats.
Expand Down
34 changes: 16 additions & 18 deletions src/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@ pub struct EncoderWriter<W> {
pub struct EncoderReader<R> {
pub inner: R,
stream: Stream,
buf: Vec<u8>,
buf: Box<[u8]>,
pos: usize,
cap: usize,
}

pub struct DecoderReader<R> {
pub inner: R,
stream: Stream,
pub pos: usize,
pub buf: Vec<u8>,
pub cap: usize,
pub buf: Box<[u8]>,
}

pub struct DecoderWriter<W> {
Expand Down Expand Up @@ -93,15 +95,16 @@ impl<R: Read> EncoderReader<R> {
EncoderReader {
inner: w,
stream: Stream::new(Deflate, raw, level),
buf: buf,
buf: buf.into_boxed_slice(),
cap: 0,
pos: 0,
}
}
}

impl<R: Read> Read for EncoderReader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.stream.read(buf, &mut self.buf, &mut self.pos,
self.stream.read(buf, &mut self.buf, &mut self.pos, &mut self.cap,
&mut self.inner, ffi::mz_deflate)
}
}
Expand All @@ -112,14 +115,15 @@ impl<R: Read> DecoderReader<R> {
inner: r,
stream: Stream::new(Inflate, raw, Compression::None),
pos: 0,
buf: buf,
buf: buf.into_boxed_slice(),
cap: 0,
}
}
}

impl<R: Read> Read for DecoderReader<R> {
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
self.stream.read(into, &mut self.buf, &mut self.pos,
self.stream.read(into, &mut self.buf, &mut self.pos, &mut self.cap,
&mut self.inner, ffi::mz_inflate)
}
}
Expand Down Expand Up @@ -189,26 +193,20 @@ impl Stream {
Stream(state, kind)
}

fn read<R: Read>(&mut self, into: &mut [u8], buf: &mut Vec<u8>,
pos: &mut usize, reader: &mut R,
fn read<R: Read>(&mut self, into: &mut [u8], buf: &mut [u8],
pos: &mut usize, cap: &mut usize, reader: &mut R,
f: unsafe extern fn(*mut ffi::mz_stream,
libc::c_int) -> libc::c_int)
-> io::Result<usize> {
loop {
let mut eof = false;
if *pos == buf.len() {
buf.truncate(0);
if *pos == *cap {
*cap = try!(reader.take(buf.len() as u64).read(buf));
*pos = 0;
// FIXME(rust-lang/rust#22640) this should be `.take()`
let mut r = ::util::Take {
limit: buf.capacity() as u64,
inner: &mut *reader,
};
try!(r.read_to_end(buf));
eof = buf.len() == 0;
eof = *cap == 0;
}

let next_in = &buf[*pos..];
let next_in = &buf[*pos..*cap];

self.next_in = next_in.as_ptr();
self.avail_in = next_in.len() as libc::c_uint;
Expand Down
21 changes: 0 additions & 21 deletions src/util.rs

This file was deleted.

10 changes: 6 additions & 4 deletions src/zlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use std::io::prelude::*;
use std::io;
use std::iter::repeat;

use raw;

Expand Down Expand Up @@ -46,7 +47,7 @@ impl<W: Write> EncoderWriter<W> {
pub fn new(w: W, level: ::Compression) -> EncoderWriter<W> {
EncoderWriter {
inner: raw::EncoderWriter::new(w, level, false,
Vec::with_capacity(128 * 1024))
Vec::with_capacity(32 * 1024)),
}
}

Expand All @@ -71,7 +72,7 @@ impl<R: Read> EncoderReader<R> {
pub fn new(r: R, level: ::Compression) -> EncoderReader<R> {
EncoderReader {
inner: raw::EncoderReader::new(r, level, false,
Vec::with_capacity(128 * 1024))
repeat(0).take(32 * 1024).collect())
}
}

Expand All @@ -89,7 +90,7 @@ impl<R: Read> DecoderReader<R> {
/// Creates a new decoder which will decompress data read from the given
/// stream.
pub fn new(r: R) -> DecoderReader<R> {
DecoderReader::new_with_buf(r, Vec::with_capacity(128 * 1024))
DecoderReader::new_with_buf(r, repeat(0).take(32 * 1024).collect())
}

/// Same as `new`, but the intermediate buffer for data is specified.
Expand All @@ -114,7 +115,8 @@ impl<W: Write> DecoderWriter<W> {
/// be flushed.
pub fn new(w: W) -> DecoderWriter<W> {
DecoderWriter {
inner: raw::DecoderWriter::new(w, false, Vec::with_capacity(128 * 1024))
inner: raw::DecoderWriter::new(w, false,
Vec::with_capacity(32 * 1024)),
}
}

Expand Down

0 comments on commit 2077908

Please sign in to comment.