diff --git a/Cargo.toml b/Cargo.toml index 67832fd..99e11f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,6 @@ codecov = {repository = "sile/libflate"} [dependencies] adler32 = "1" -byteorder = "1" crc32fast = "1" rle-decode-fast = "1.0.0" take_mut = "0.2.2" diff --git a/src/bit.rs b/src/bit.rs index 52f2563..e4c656b 100644 --- a/src/bit.rs +++ b/src/bit.rs @@ -1,6 +1,3 @@ -use byteorder::LittleEndian; -use byteorder::ReadBytesExt; -use byteorder::WriteBytesExt; use std::io; #[derive(Debug)] @@ -34,7 +31,7 @@ where } pub fn flush(&mut self) -> io::Result<()> { while self.end > 0 { - self.inner.write_u8(self.buf as u8)?; + self.inner.write_all(&[self.buf as u8])?; self.buf >>= 8; self.end = self.end.saturating_sub(8); } @@ -44,7 +41,7 @@ where #[inline(always)] fn flush_if_needed(&mut self) -> io::Result<()> { if self.end >= 16 { - self.inner.write_u16::(self.buf as u16)?; + self.inner.write_all(&(self.buf as u16).to_le_bytes())?; self.end -= 16; self.buf >>= 16; } @@ -135,7 +132,9 @@ where self.offset -= 8; self.last_read >>= 8; - let next = u32::from(self.inner.read_u8()?); + let mut buf = [0; 1]; + self.inner.read_exact(&mut buf)?; + let next = u32::from(buf[0]); self.last_read |= next << (32 - 8); Ok(()) } diff --git a/src/deflate/decode.rs b/src/deflate/decode.rs index 652b2c9..da038e2 100644 --- a/src/deflate/decode.rs +++ b/src/deflate/decode.rs @@ -1,5 +1,3 @@ -use byteorder::LittleEndian; -use byteorder::ReadBytesExt; use rle_decode_fast::rle_decode; use std::cmp; use std::io; @@ -73,8 +71,11 @@ where fn read_non_compressed_block(&mut self) -> io::Result<()> { self.bit_reader.reset(); - let len = self.bit_reader.as_inner_mut().read_u16::()?; - let nlen = self.bit_reader.as_inner_mut().read_u16::()?; + let mut buf = [0; 2]; + self.bit_reader.as_inner_mut().read_exact(&mut buf)?; + let len = u16::from_le_bytes(buf); + self.bit_reader.as_inner_mut().read_exact(&mut buf)?; + let nlen = u16::from_le_bytes(buf); if !len != nlen { Err(invalid_data_error!( "LEN={} is not the one's complement of NLEN={}", diff --git a/src/deflate/encode.rs b/src/deflate/encode.rs index 9e3ceee..de7819f 100644 --- a/src/deflate/encode.rs +++ b/src/deflate/encode.rs @@ -1,5 +1,3 @@ -use byteorder::LittleEndian; -use byteorder::WriteBytesExt; use std::cmp; use std::io; @@ -357,10 +355,10 @@ impl RawBuf { writer.flush()?; writer .as_inner_mut() - .write_u16::(size as u16)?; + .write_all(&(size as u16).to_le_bytes())?; writer .as_inner_mut() - .write_u16::(!size as u16)?; + .write_all(&(!size as u16).to_le_bytes())?; writer.as_inner_mut().write_all(&self.buf[..size])?; self.buf.drain(0..size); Ok(()) diff --git a/src/gzip.rs b/src/gzip.rs index 67ddc32..ae4017e 100644 --- a/src/gzip.rs +++ b/src/gzip.rs @@ -19,12 +19,7 @@ //! //! assert_eq!(decoded_data, b"Hello World!"); //! ``` -use byteorder::LittleEndian; -use byteorder::ReadBytesExt; -use byteorder::WriteBytesExt; -use std::ffi::CString; -use std::io; -use std::time; +use std::{ffi::CString, io, time}; use checksum; use deflate; @@ -107,17 +102,19 @@ impl Trailer { where R: io::Read, { - Ok(Trailer { - crc32: reader.read_u32::()?, - input_size: reader.read_u32::()?, - }) + let mut buf = [0; 4]; + reader.read_exact(&mut buf)?; + let crc32 = u32::from_le_bytes(buf); + reader.read_exact(&mut buf)?; + let input_size = u32::from_le_bytes(buf); + Ok(Trailer { crc32, input_size }) } fn write_to(&self, mut writer: W) -> io::Result<()> where W: io::Write, { - writer.write_u32::(self.crc32)?; - writer.write_u32::(self.input_size)?; + writer.write_all(&self.crc32.to_le_bytes())?; + writer.write_all(&self.input_size.to_le_bytes())?; Ok(()) } } @@ -361,11 +358,9 @@ impl Header { W: io::Write, { writer.write_all(&GZIP_ID)?; - writer.write_u8(COMPRESSION_METHOD_DEFLATE)?; - writer.write_u8(self.flags())?; - writer.write_u32::(self.modification_time)?; - writer.write_u8(self.compression_level.to_u8())?; - writer.write_u8(self.os.to_u8())?; + writer.write_all(&[COMPRESSION_METHOD_DEFLATE, self.flags()])?; + writer.write_all(&self.modification_time.to_le_bytes())?; + writer.write_all(&[self.compression_level.to_u8(), self.os.to_u8()])?; if let Some(ref x) = self.extra_field { x.write_to(&mut writer)?; } @@ -376,7 +371,7 @@ impl Header { writer.write_all(x.as_bytes_with_nul())?; } if self.is_verified { - writer.write_u16::(self.crc16())?; + writer.write_all(&self.crc16().to_le_bytes())?; } Ok(()) } @@ -385,8 +380,9 @@ impl Header { R: io::Read, { let mut this = HeaderBuilder::new().finish(); - let mut id = [0; 2]; - reader.read_exact(&mut id)?; + let mut buf = [0; 2 + 1 + 1 + 4 + 1 + 1]; + reader.read_exact(&mut buf)?; + let id = &buf[0..2]; if id != GZIP_ID { return Err(invalid_data_error!( "Unexpected GZIP ID: value={:?}, \ @@ -395,7 +391,7 @@ impl Header { GZIP_ID )); } - let compression_method = reader.read_u8()?; + let compression_method = buf[2]; if compression_method != COMPRESSION_METHOD_DEFLATE { return Err(invalid_data_error!( "Compression methods other than DEFLATE(8) are \ @@ -403,10 +399,11 @@ impl Header { compression_method )); } - let flags = reader.read_u8()?; - this.modification_time = reader.read_u32::()?; - this.compression_level = CompressionLevel::from_u8(reader.read_u8()?); - this.os = Os::from_u8(reader.read_u8()?); + let flags = buf[3]; + this.modification_time = + u32::from_le_bytes([buf[4], buf[5], buf[6], buf[7]]); + this.compression_level = CompressionLevel::from_u8(buf[8]); + this.os = Os::from_u8(buf[9]); if flags & F_EXTRA != 0 { this.extra_field = Some(ExtraField::read_from(&mut reader)?); } @@ -420,7 +417,9 @@ impl Header { // so that random data from fuzzer can reach actually interesting code. // Compilation flag 'fuzzing' is automatically set by all 3 Rust fuzzers. if flags & F_HCRC != 0 && cfg!(not(fuzzing)) { - let crc = reader.read_u16::()?; + let mut buf = [0; 2]; + reader.read_exact(&mut buf)?; + let crc = u16::from_le_bytes(buf); let expected = this.crc16(); if crc != expected { return Err(invalid_data_error!( @@ -442,11 +441,12 @@ where { let mut buf = Vec::new(); loop { - let b = reader.read_u8()?; - if b == 0 { + let mut cbuf = [0; 1]; + reader.read_exact(&mut cbuf)?; + if cbuf[0] == 0 { return Ok(unsafe { CString::from_vec_unchecked(buf) }); } - buf.push(b); + buf.push(cbuf[0]); } } @@ -462,7 +462,9 @@ impl ExtraField { R: io::Read, { let mut subfields = Vec::new(); - let data_size = reader.read_u16::()? as usize; + let mut buf = [0; 2]; + reader.read_exact(&mut buf)?; + let data_size = u16::from_le_bytes(buf) as usize; let mut reader = reader.take(data_size as u64); while reader.limit() > 0 { subfields.push(ExtraSubField::read_from(&mut reader)?); @@ -477,7 +479,7 @@ impl ExtraField { if len > 0xFFFF { return Err(invalid_data_error!("extra field too long: {}", len)); } - writer.write_u16::(len as u16)?; + writer.write_all(&(len as u16).to_le_bytes())?; for f in &self.subfields { f.write_to(&mut writer)?; } @@ -505,7 +507,9 @@ impl ExtraSubField { }; reader.read_exact(&mut field.id)?; - let data_size = reader.read_u16::()? as usize; + let mut buf = [0; 2]; + reader.read_exact(&mut buf)?; + let data_size = u16::from_le_bytes(buf) as usize; field.data.resize(data_size, 0); reader.read_exact(&mut field.data)?; @@ -516,7 +520,7 @@ impl ExtraSubField { W: io::Write, { writer.write_all(&self.id)?; - writer.write_u16::(self.data.len() as u16)?; + writer.write_all(&(self.data.len() as u16).to_le_bytes())?; writer.write_all(&self.data)?; Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index a414e02..3a5f84c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ //! A Rust implementation of DEFLATE algorithm and related formats (ZLIB, GZIP). #![warn(missing_docs)] extern crate adler32; -extern crate byteorder; extern crate crc32fast; extern crate rle_decode_fast; extern crate take_mut; diff --git a/src/non_blocking/deflate/decode.rs b/src/non_blocking/deflate/decode.rs index 424a801..7ce0ba5 100644 --- a/src/non_blocking/deflate/decode.rs +++ b/src/non_blocking/deflate/decode.rs @@ -1,5 +1,3 @@ -use byteorder::LittleEndian; -use byteorder::ReadBytesExt; use rle_decode_fast::rle_decode; use std::cmp; use std::io; @@ -99,8 +97,11 @@ impl Read for Decoder { DecoderState::ReadNonCompressedBlockLen => { let len = self.bit_reader.transaction(|r| { r.reset(); - let len = r.as_inner_mut().read_u16::()?; - let nlen = r.as_inner_mut().read_u16::()?; + let mut buf = [0; 2]; + r.as_inner_mut().read_exact(&mut buf)?; + let len = u16::from_le_bytes(buf); + r.as_inner_mut().read_exact(&mut buf)?; + let nlen = u16::from_le_bytes(buf); if !len != nlen { Err(invalid_data_error!( "LEN={} is not the one's complement of NLEN={}", diff --git a/src/non_blocking/zlib.rs b/src/non_blocking/zlib.rs index c6dfa8f..5e695f8 100644 --- a/src/non_blocking/zlib.rs +++ b/src/non_blocking/zlib.rs @@ -20,8 +20,6 @@ //! //! assert_eq!(decoded_data, b"Hello World!"); //! ``` -use byteorder::BigEndian; -use byteorder::ReadBytesExt; use std::io::{self, Read}; use checksum; @@ -128,10 +126,12 @@ impl Read for Decoder { } else { let read_size = self.reader.read(buf)?; if read_size == 0 { - let adler32 = self - .reader - .bit_reader_mut() - .transaction(|r| r.as_inner_mut().read_u32::())?; + let adler32 = self.reader.bit_reader_mut().transaction(|r| { + let mut buf = [0; 4]; + r.as_inner_mut() + .read_exact(&mut buf) + .and(Ok(u32::from_be_bytes(buf))) + })?; self.eos = true; // checksum verification is skipped during fuzzing // so that random data from fuzzer can reach actually interesting code diff --git a/src/zlib.rs b/src/zlib.rs index c1d7abe..f556117 100644 --- a/src/zlib.rs +++ b/src/zlib.rs @@ -19,9 +19,6 @@ //! //! assert_eq!(decoded_data, b"Hello World!"); //! ``` -use byteorder::BigEndian; -use byteorder::ReadBytesExt; -use byteorder::WriteBytesExt; use std::io; use checksum; @@ -203,8 +200,9 @@ impl Header { where R: io::Read, { - let cmf = reader.read_u8()?; - let flg = reader.read_u8()?; + let mut buf = [0; 2]; + reader.read_exact(&mut buf)?; + let (cmf, flg) = (buf[0], buf[1]); let check = (u16::from(cmf) << 8) + u16::from(flg); if check % 31 != 0 { return Err(invalid_data_error!( @@ -230,7 +228,9 @@ impl Header { let dict_flag = (flg & 0b100_000) != 0; if dict_flag { - let dictionary_id = reader.read_u32::()?; + let mut buf = [0; 4]; + reader.read_exact(&mut buf)?; + let dictionary_id = u32::from_be_bytes(buf); return Err(invalid_data_error!( "Preset dictionaries are not supported: \ dictionary_id=0x{:X}", @@ -253,8 +253,7 @@ impl Header { if check % 31 != 0 { flg += (31 - check % 31) as u8; } - writer.write_u8(cmf)?; - writer.write_u8(flg)?; + writer.write_all(&[cmf, flg])?; Ok(()) } } @@ -354,7 +353,10 @@ where let read_size = self.reader.read(buf)?; if read_size == 0 { self.eos = true; - let adler32 = self.reader.as_inner_mut().read_u32::()?; + let mut buf = [0; 4]; + self.reader.as_inner_mut().read_exact(&mut buf)?; + let adler32 = u32::from_be_bytes(buf); + // checksum verification is skipped during fuzzing // so that random data from fuzzer can reach actually interesting code // Compilation flag 'fuzzing' is automatically set by all 3 Rust fuzzers. @@ -582,7 +584,7 @@ where pub fn finish(self) -> Finish { let mut inner = finish_try!(self.writer.finish()); match inner - .write_u32::(self.adler32.value()) + .write_all(&self.adler32.value().to_be_bytes()) .and_then(|_| inner.flush()) { Ok(_) => Finish::new(inner, None),