diff --git a/Cargo.toml b/Cargo.toml index cebdcf2..7a05738 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,11 @@ coveralls = {repository = "sile/libflate"} [dependencies] adler32 = "1" crc32fast = "1.1.1" -libflate_lz77 = { path = "libflate_lz77", version = "1.1" } +libflate_lz77 = { path = "libflate_lz77", version = "1.1", default_features = false } +core2 = { version = "0.4", default_features = false, features = ["alloc"], optional = true } + +[features] +no_std = ["libflate_lz77/no_std", "core2"] [dev-dependencies] clap = "2" diff --git a/examples/flate.rs b/examples/flate.rs index 2b0f21d..93c4d01 100644 --- a/examples/flate.rs +++ b/examples/flate.rs @@ -1,17 +1,31 @@ extern crate clap; extern crate libflate; +#[cfg(not(feature = "no_std"))] use clap::App; +#[cfg(not(feature = "no_std"))] use clap::Arg; +#[cfg(not(feature = "no_std"))] use clap::SubCommand; +#[cfg(not(feature = "no_std"))] use libflate::gzip; +#[cfg(not(feature = "no_std"))] use libflate::zlib; +#[cfg(not(feature = "no_std"))] use std::fs; +#[cfg(not(feature = "no_std"))] use std::io; +#[cfg(not(feature = "no_std"))] use std::io::Read; +#[cfg(not(feature = "no_std"))] use std::io::Write; +#[cfg(not(feature = "no_std"))] use std::process; +#[cfg(feature = "no_std")] +fn main() {} + +#[cfg(not(feature = "no_std"))] fn main() { let matches = App::new("deflate") .arg( diff --git a/libflate_lz77/Cargo.toml b/libflate_lz77/Cargo.toml index c28ac2e..a4d5231 100644 --- a/libflate_lz77/Cargo.toml +++ b/libflate_lz77/Cargo.toml @@ -16,6 +16,11 @@ coveralls = {repository = "sile/libflate"} [dependencies] rle-decode-fast = "1.0.0" +core2 = { version = "0.4", default-features = false, features = ["alloc"], optional = true } +hashbrown = { version = "0.13", optional = true } [dev-dependencies] libflate = { path = "../", version = "1" } + +[features] +no_std = ["core2", "hashbrown"] diff --git a/libflate_lz77/src/default.rs b/libflate_lz77/src/default.rs index b52fb0c..0ba8e14 100644 --- a/libflate_lz77/src/default.rs +++ b/libflate_lz77/src/default.rs @@ -1,5 +1,11 @@ -use std::cmp; -use std::collections::HashMap; +#[cfg(feature = "no_std")] +use alloc::vec::Vec; +#[cfg(feature = "no_std")] +use core::cmp; +#[cfg(feature = "no_std")] +use hashbrown::HashMap; +#[cfg(not(feature = "no_std"))] +use std::{cmp, collections::HashMap}; use super::Code; use super::Lz77Encode; diff --git a/libflate_lz77/src/lib.rs b/libflate_lz77/src/lib.rs index 9856532..fc97b9f 100644 --- a/libflate_lz77/src/lib.rs +++ b/libflate_lz77/src/lib.rs @@ -2,8 +2,19 @@ //! //! LZ77 is a compression algorithm used in [DEFLATE](https://tools.ietf.org/html/rfc1951). #![warn(missing_docs)] +#![cfg_attr(no_std, feature = "no_std")] + +#[cfg(feature = "no_std")] +extern crate alloc; + pub use self::default::{DefaultLz77Encoder, DefaultLz77EncoderBuilder}; +#[cfg(feature = "no_std")] +use alloc::vec::Vec; +#[cfg(feature = "no_std")] +use core2::io; use rle_decode_fast::rle_decode; +#[cfg(not(feature = "no_std"))] +use std::io; mod default; @@ -157,7 +168,7 @@ impl Lz77Decoder { /// /// The decoded bytes are appended to the buffer of [`Lz77Decoder`]. #[inline] - pub fn decode(&mut self, code: Code) -> std::io::Result<()> { + pub fn decode(&mut self, code: Code) -> io::Result<()> { match code { Code::Literal(b) => { self.buffer.push(b); @@ -167,13 +178,16 @@ impl Lz77Decoder { backward_distance, } => { if self.buffer.len() < backward_distance as usize { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, + return Err(io::Error::new( + io::ErrorKind::InvalidData, + #[cfg(not(feature = "no_std"))] format!( "Too long backword reference: buffer.len={}, distance={}", self.buffer.len(), backward_distance ), + #[cfg(feature = "no_std")] + "Too long backword reference", )); } rle_decode( @@ -187,10 +201,7 @@ impl Lz77Decoder { } /// Appends the bytes read from `reader` to the buffer of [`Lz77Decoder`]. - pub fn extend_from_reader( - &mut self, - mut reader: R, - ) -> std::io::Result { + pub fn extend_from_reader(&mut self, mut reader: R) -> io::Result { reader.read_to_end(&mut self.buffer) } @@ -227,8 +238,8 @@ impl Lz77Decoder { } } -impl std::io::Read for Lz77Decoder { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { +impl io::Read for Lz77Decoder { + fn read(&mut self, buf: &mut [u8]) -> io::Result { let copy_size = std::cmp::min(buf.len(), self.buffer.len() - self.offset); buf[..copy_size].copy_from_slice(&self.buffer[self.offset..][..copy_size]); self.offset += copy_size; @@ -240,6 +251,11 @@ impl std::io::Read for Lz77Decoder { #[cfg(test)] mod tests { use super::*; + #[cfg(feature = "no_std")] + use alloc::vec::Vec; + #[cfg(feature = "no_std")] + use core2::io::Read as _; + #[cfg(not(feature = "no_std"))] use std::io::Read as _; #[test] diff --git a/src/bit.rs b/src/bit.rs index 3dab20f..816eeac 100644 --- a/src/bit.rs +++ b/src/bit.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "no_std")] +use core2::io; +#[cfg(not(feature = "no_std"))] use std::io; #[derive(Debug)] @@ -176,6 +179,9 @@ pub(crate) struct BitReaderState { #[cfg(test)] mod tests { use super::*; + #[cfg(feature = "no_std")] + use core2::io; + #[cfg(not(feature = "no_std"))] use std::io; #[test] diff --git a/src/checksum.rs b/src/checksum.rs index 4f0d29a..5424d70 100644 --- a/src/checksum.rs +++ b/src/checksum.rs @@ -1,4 +1,7 @@ use adler32::RollingAdler32; +#[cfg(feature = "no_std")] +use core::fmt; +#[cfg(not(feature = "no_std"))] use std::fmt; pub struct Adler32(RollingAdler32); diff --git a/src/deflate/decode.rs b/src/deflate/decode.rs index 5d0fa8e..273201c 100644 --- a/src/deflate/decode.rs +++ b/src/deflate/decode.rs @@ -1,8 +1,10 @@ use super::symbol; use crate::bit; use crate::lz77; -use std::io; -use std::io::Read; +#[cfg(feature = "no_std")] +use core2::io::{self, Read}; +#[cfg(not(feature = "no_std"))] +use std::io::{self, Read}; /// DEFLATE decoder. #[derive(Debug)] @@ -21,6 +23,9 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::{Cursor, Read}; + /// #[cfg(not(feature = "no_std"))] /// use std::io::{Cursor, Read}; /// use libflate::deflate::Decoder; /// @@ -53,6 +58,9 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Cursor; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Cursor; /// use libflate::deflate::Decoder; /// @@ -90,7 +98,10 @@ where if used != len.into() { Err(io::Error::new( io::ErrorKind::UnexpectedEof, + #[cfg(not(feature = "no_std"))] format!("The reader has incorrect length: expected {len}, read {used}"), + #[cfg(feature = "no_std")] + "The reader has incorrect length", )) } else { Ok(()) @@ -155,8 +166,10 @@ where #[cfg(test)] mod tests { + #[cfg(not(feature = "no_std"))] use super::*; use crate::deflate::symbol::{DynamicHuffmanCodec, HuffmanCodec}; + #[cfg(not(feature = "no_std"))] use std::io; #[test] @@ -177,6 +190,7 @@ mod tests { } #[test] + #[cfg(not(feature = "no_std"))] fn it_works() { let input = [ 180, 253, 73, 143, 28, 201, 150, 46, 8, 254, 150, 184, 139, 75, 18, 69, 247, 32, 157, @@ -198,6 +212,7 @@ mod tests { } #[test] + #[cfg(not(feature = "no_std"))] fn test_issue_64() { let input = b"\x04\x04\x04\x05:\x1az*\xfc\x06\x01\x90\x01\x06\x01"; let mut decoder = Decoder::new(&input[..]); diff --git a/src/deflate/encode.rs b/src/deflate/encode.rs index 35e9648..259a183 100644 --- a/src/deflate/encode.rs +++ b/src/deflate/encode.rs @@ -3,8 +3,12 @@ use super::BlockType; use crate::bit; use crate::finish::{Complete, Finish}; use crate::lz77; -use std::cmp; -use std::io; +#[cfg(feature = "no_std")] +use core::cmp; +#[cfg(feature = "no_std")] +use core2::io; +#[cfg(not(feature = "no_std"))] +use std::{cmp, io}; /// The default size of a DEFLATE block. pub const DEFAULT_BLOCK_SIZE: usize = 1024 * 1024; @@ -142,11 +146,14 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Write; /// use libflate::deflate::Encoder; /// /// let mut encoder = Encoder::new(Vec::new()); - /// encoder.write_all(b"Hello World!").unwrap(); + /// encoder.write_all(b"Hello World!".as_ref()).unwrap(); /// /// assert_eq!(encoder.finish().into_result().unwrap(), /// [5, 192, 49, 13, 0, 0, 8, 3, 65, 43, 224, 6, 7, 24, 128, 237, @@ -167,12 +174,15 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Write; /// use libflate::deflate::{Encoder, EncodeOptions}; /// /// let options = EncodeOptions::new().no_compression(); /// let mut encoder = Encoder::with_options(Vec::new(), options); - /// encoder.write_all(b"Hello World!").unwrap(); + /// encoder.write_all(b"Hello World!".as_ref()).unwrap(); /// /// assert_eq!(encoder.finish().into_result().unwrap(), /// [1, 12, 0, 243, 255, 72, 101, 108, 108, 111, 32, 87, 111, @@ -189,11 +199,14 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Write; /// use libflate::deflate::Encoder; /// /// let mut encoder = Encoder::new(Vec::new()); - /// encoder.write_all(b"Hello World!").unwrap(); + /// encoder.write_all(b"Hello World!".as_ref()).unwrap(); /// /// assert_eq!(encoder.finish().into_result().unwrap(), /// [5, 192, 49, 13, 0, 0, 8, 3, 65, 43, 224, 6, 7, 24, 128, 237, @@ -428,6 +441,9 @@ where mod tests { use super::super::Decoder; use super::*; + #[cfg(feature = "no_std")] + use core2::io::{Read as _, Write as _}; + #[cfg(not(feature = "no_std"))] use std::io::{Read as _, Write as _}; #[test] diff --git a/src/deflate/mod.rs b/src/deflate/mod.rs index bfcd58a..88e976d 100644 --- a/src/deflate/mod.rs +++ b/src/deflate/mod.rs @@ -4,12 +4,15 @@ //! //! # Examples //! ``` -//! use std::io::{self, Read}; +//! #[cfg(feature = "no_std")] +//! use core2::io::{Read, Write}; +//! #[cfg(not(feature = "no_std"))] +//! use std::io::{Read, Write}; //! use libflate::deflate::{Encoder, Decoder}; //! //! // Encoding //! let mut encoder = Encoder::new(Vec::new()); -//! io::copy(&mut &b"Hello World!"[..], &mut encoder).unwrap(); +//! encoder.write_all(b"Hello World!".as_ref()).unwrap(); //! let encoded_data = encoder.finish().into_result().unwrap(); //! //! // Decoding @@ -42,6 +45,9 @@ enum BlockType { mod tests { use super::*; use crate::lz77; + #[cfg(feature = "no_std")] + use core2::io::{Read, Write}; + #[cfg(not(feature = "no_std"))] use std::io::{Read, Write}; #[test] diff --git a/src/deflate/symbol.rs b/src/deflate/symbol.rs index 5f7f1b8..3fc8258 100644 --- a/src/deflate/symbol.rs +++ b/src/deflate/symbol.rs @@ -2,10 +2,12 @@ use crate::bit; use crate::huffman; use crate::huffman::Builder; use crate::lz77; -use std::cmp; -use std::io; -use std::iter; -use std::ops::Range; +#[cfg(feature = "no_std")] +use core::{cmp, iter, ops::Range}; +#[cfg(feature = "no_std")] +use core2::io; +#[cfg(not(feature = "no_std"))] +use std::{cmp, io, iter, ops::Range}; const FIXED_LITERAL_OR_LENGTH_CODE_TABLE: [(u8, Range, u16); 4] = [ (8, 000..144, 0b0_0011_0000), @@ -215,7 +217,10 @@ impl Decoder { 0..=255 => Symbol::Code(lz77::Code::Literal(decoded as u8)), 256 => Symbol::EndOfBlock, 286 | 287 => { + #[cfg(not(feature = "no_std"))] let message = format!("The value {decoded} must not occur in compressed data"); + #[cfg(feature = "no_std")] + let message = "The value(s) [286, 287] must not occur in compressed data"; reader.set_last_error(io::Error::new(io::ErrorKind::InvalidData, message)); Symbol::EndOfBlock // dummy value } @@ -391,9 +396,12 @@ impl HuffmanCodec for DynamicHuffmanCodec { let bitwidth_code_count = reader.read_bits(4)? + 4; if distance_code_count as usize > MAX_DISTANCE_CODE_COUNT { + #[cfg(not(feature = "no_std"))] let message = format!( "The value of HDIST is too big: max={MAX_DISTANCE_CODE_COUNT}, actual={distance_code_count}" ); + #[cfg(feature = "no_std")] + let message = "The value of HDIST is too big: max={MAX_DISTANCE_CODE_COUNT}"; return Err(io::Error::new(io::ErrorKind::InvalidData, message)); } @@ -426,11 +434,14 @@ impl HuffmanCodec for DynamicHuffmanCodec { distance_code_bitwidthes.extend(load_bitwidthes(reader, c, last)?); } if distance_code_bitwidthes.len() > distance_code_count as usize { + #[cfg(not(feature = "no_std"))] let message = format!( "The length of `distance_code_bitwidthes` is too large: actual={}, expected={}", distance_code_bitwidthes.len(), distance_code_count ); + #[cfg(feature = "no_std")] + let message = "The length of `distance_code_bitwidthes` is too large"; return Err(io::Error::new(io::ErrorKind::InvalidData, message)); } diff --git a/src/finish.rs b/src/finish.rs index 935d41b..ac1a54d 100644 --- a/src/finish.rs +++ b/src/finish.rs @@ -1,6 +1,14 @@ //! `Finish` and related types. -use std::io::{self, Write}; -use std::ops::{Deref, DerefMut}; + +#[cfg(feature = "no_std")] +use core::ops::{Deref, DerefMut}; +#[cfg(feature = "no_std")] +use core2::io::{self, Write}; +#[cfg(not(feature = "no_std"))] +use std::{ + io::{self, Write}, + ops::{Deref, DerefMut}, +}; /// `Finish` is a type that represents a value which /// may have an error occurred during the computation. @@ -104,14 +112,17 @@ impl AutoFinish { /// # Examples /// /// ``` - /// use std::io; + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; + /// #[cfg(not(feature = "no_std"))] + /// use std::io::Write; /// use libflate::finish::AutoFinish; /// use libflate::gzip::Encoder; /// /// let plain = b"Hello World!"; /// let mut buf = Vec::new(); /// let mut encoder = AutoFinish::new(Encoder::new(&mut buf).unwrap()); - /// io::copy(&mut &plain[..], &mut encoder).unwrap(); + /// encoder.write_all(plain.as_ref()).unwrap(); /// ``` pub fn new(inner: T) -> Self { AutoFinish { inner: Some(inner) } @@ -166,14 +177,17 @@ impl AutoFinishUnchecked { /// # Examples /// /// ``` - /// use std::io; + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; + /// #[cfg(not(feature = "no_std"))] + /// use std::io::Write; /// use libflate::finish::AutoFinishUnchecked; /// use libflate::gzip::Encoder; /// /// let plain = b"Hello World!"; /// let mut buf = Vec::new(); /// let mut encoder = AutoFinishUnchecked::new(Encoder::new(&mut buf).unwrap()); - /// io::copy(&mut &plain[..], &mut encoder).unwrap(); + /// encoder.write_all(plain.as_ref()).unwrap(); /// ``` pub fn new(inner: T) -> Self { AutoFinishUnchecked { inner: Some(inner) } diff --git a/src/gzip.rs b/src/gzip.rs index 8bc3a39..29eee42 100644 --- a/src/gzip.rs +++ b/src/gzip.rs @@ -4,12 +4,15 @@ //! //! # Examples //! ``` -//! use std::io::{self, Read}; +//! #[cfg(feature = "no_std")] +//! use core2::io::{Read, Write}; +//! #[cfg(not(feature = "no_std"))] +//! use std::io::{Read, Write}; //! use libflate::gzip::{Encoder, Decoder}; //! //! // Encoding //! let mut encoder = Encoder::new(Vec::new()).unwrap(); -//! io::copy(&mut &b"Hello World!"[..], &mut encoder).unwrap(); +//! encoder.write_all(b"Hello World!".as_ref()).unwrap(); //! let encoded_data = encoder.finish().into_result().unwrap(); //! //! // Decoding @@ -23,6 +26,11 @@ use crate::checksum; use crate::deflate; use crate::finish::{Complete, Finish}; use crate::lz77; +#[cfg(feature = "no_std")] +use alloc::{ffi::CString, vec::Vec}; +#[cfg(feature = "no_std")] +use core2::io; +#[cfg(not(feature = "no_std"))] use std::{ffi::CString, io, time}; const GZIP_ID: [u8; 2] = [31, 139]; @@ -141,12 +149,12 @@ impl HeaderBuilder { /// ``` pub fn new() -> Self { // wasm-unknown-unknown does not implement the time module - #[cfg(not(target_arch = "wasm32"))] + #[cfg(all(not(target_arch = "wasm32"), not(feature = "no_std")))] let modification_time = time::UNIX_EPOCH .elapsed() .map(|d| d.as_secs() as u32) .unwrap_or(0); - #[cfg(target_arch = "wasm32")] + #[cfg(any(target_arch = "wasm32", feature = "no_std"))] let modification_time = 0; let header = Header { @@ -237,6 +245,11 @@ impl HeaderBuilder { /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// extern crate alloc; + /// #[cfg(feature = "no_std")] + /// use alloc::ffi::CString; + /// #[cfg(not(feature = "no_std"))] /// use std::ffi::CString; /// use libflate::gzip::HeaderBuilder; /// @@ -252,6 +265,11 @@ impl HeaderBuilder { /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// extern crate alloc; + /// #[cfg(feature = "no_std")] + /// use alloc::ffi::CString; + /// #[cfg(not(feature = "no_std"))] /// use std::ffi::CString; /// use libflate::gzip::HeaderBuilder; /// @@ -754,11 +772,14 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Write; /// use libflate::gzip::Encoder; /// /// let mut encoder = Encoder::new(Vec::new()).unwrap(); - /// encoder.write_all(b"Hello World!").unwrap(); + /// encoder.write_all(&b"Hello World!"[..]).unwrap(); /// encoder.finish().into_result().unwrap(); /// ``` pub fn new(inner: W) -> io::Result { @@ -776,13 +797,16 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Write; /// use libflate::gzip::{Encoder, EncodeOptions, HeaderBuilder}; /// /// let header = HeaderBuilder::new().modification_time(123).finish(); /// let options = EncodeOptions::new().no_compression().header(header); /// let mut encoder = Encoder::with_options(Vec::new(), options).unwrap(); - /// encoder.write_all(b"Hello World!").unwrap(); + /// encoder.write_all(&b"Hello World!"[..]).unwrap(); /// /// assert_eq!(encoder.finish().into_result().unwrap(), /// &[31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255, 72, 101, 108, 108, @@ -815,11 +839,14 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Write; /// use libflate::gzip::Encoder; /// /// let mut encoder = Encoder::new(Vec::new()).unwrap(); - /// encoder.write_all(b"Hello World!").unwrap(); + /// encoder.write_all(&b"Hello World!"[..]).unwrap(); /// /// assert!(encoder.finish().as_result().is_ok()) /// ``` @@ -830,6 +857,9 @@ where /// it may be convenient to use `AutoFinishUnchecked` instead of the explicit invocation of this method. /// /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; + /// #[cfg(not(feature = "no_std"))] /// use std::io; /// use libflate::finish::AutoFinishUnchecked; /// use libflate::gzip::Encoder; @@ -837,6 +867,9 @@ where /// let plain = b"Hello World!"; /// let mut buf = Vec::new(); /// let mut encoder = AutoFinishUnchecked::new(Encoder::new(&mut buf).unwrap()); + /// #[cfg(feature = "no_std")] + /// encoder.write_all(plain.as_ref()).unwrap(); + /// #[cfg(not(feature = "no_std"))] /// io::copy(&mut &plain[..], &mut encoder).unwrap(); /// ``` pub fn finish(self) -> Finish { @@ -909,6 +942,9 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Read; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Read; /// use libflate::gzip::Decoder; /// @@ -958,6 +994,9 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Cursor; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Cursor; /// use libflate::gzip::Decoder; /// @@ -1040,6 +1079,9 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Read; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Read; /// use libflate::gzip::MultiDecoder; /// @@ -1098,6 +1140,9 @@ where /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Cursor; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Cursor; /// use libflate::gzip::MultiDecoder; /// @@ -1147,25 +1192,28 @@ where mod tests { use super::*; use crate::finish::AutoFinish; + #[cfg(feature = "no_std")] + use core2::io::{Read, Write}; + #[cfg(not(feature = "no_std"))] use std::io::{self, Read, Write}; fn decode(buf: &[u8]) -> io::Result> { let mut decoder = Decoder::new(buf).unwrap(); let mut buf = Vec::with_capacity(buf.len()); - io::copy(&mut decoder, &mut buf)?; + decoder.read_to_end(&mut buf)?; Ok(buf) } fn decode_multi(buf: &[u8]) -> io::Result> { let mut decoder = MultiDecoder::new(buf).unwrap(); let mut buf = Vec::with_capacity(buf.len()); - io::copy(&mut decoder, &mut buf)?; + decoder.read_to_end(&mut buf).unwrap(); Ok(buf) } fn encode(text: &[u8]) -> io::Result> { let mut encoder = Encoder::new(Vec::new()).unwrap(); - io::copy(&mut &text[..], &mut encoder).unwrap(); + encoder.write_all(text).unwrap(); encoder.finish().into_result() } @@ -1173,7 +1221,7 @@ mod tests { fn encode_works() { let plain = b"Hello World! Hello GZIP!!"; let mut encoder = Encoder::new(Vec::new()).unwrap(); - io::copy(&mut &plain[..], &mut encoder).unwrap(); + encoder.write_all(plain.as_ref()).unwrap(); let encoded = encoder.finish().into_result().unwrap(); assert_eq!(decode(&encoded).unwrap(), plain); } @@ -1184,13 +1232,16 @@ mod tests { let mut buf = Vec::new(); { let mut encoder = AutoFinish::new(Encoder::new(&mut buf).unwrap()); - io::copy(&mut &plain[..], &mut encoder).unwrap(); + encoder.write_all(plain.as_ref()).unwrap(); } assert_eq!(decode(&buf).unwrap(), plain); } #[test] fn multi_decode_works() { + #[cfg(feature = "no_std")] + use core::iter; + #[cfg(not(feature = "no_std"))] use std::iter; let text = b"Hello World!"; let encoded: Vec = iter::repeat(encode(text).unwrap()) @@ -1229,7 +1280,7 @@ mod tests { let mut decoder = Decoder::new(&data[..]).unwrap(); let mut buf = Vec::new(); decoder.read(&mut buf).unwrap(); - io::copy(&mut decoder, &mut buf).unwrap(); + decoder.read_to_end(&mut buf).unwrap(); assert_eq!(buf, b"Hello World"); } @@ -1249,6 +1300,7 @@ mod tests { } #[test] + #[cfg(not(feature = "no_std"))] fn encode_with_extra_field() { let mut buf = Vec::new(); let extra_field = ExtraField { diff --git a/src/huffman.rs b/src/huffman.rs index f57db9c..b95f813 100644 --- a/src/huffman.rs +++ b/src/huffman.rs @@ -1,7 +1,13 @@ //! Length-limited Huffman Codes. use crate::bit; -use std::cmp; -use std::io; +#[cfg(feature = "no_std")] +use alloc::vec::Vec; +#[cfg(feature = "no_std")] +use core::cmp; +#[cfg(feature = "no_std")] +use core2::io; +#[cfg(not(feature = "no_std"))] +use std::{cmp, io}; const MAX_BITWIDTH: u8 = 15; @@ -106,10 +112,13 @@ impl Builder for DecoderBuilder { for padding in 0..(1 << (self.max_bitwidth - code.width)) { let i = ((padding << code.width) | code_be.bits) as usize; if self.table[i] != u16::from(MAX_BITWIDTH) + 1 { + #[cfg(not(feature = "no_std"))] let message = format!( "Bit region conflict: i={}, old_value={}, new_value={}, symbol={}, code={:?}", i, self.table[i], value, symbol, code ); + #[cfg(feature = "no_std")] + let message = "Bit region conflict"; return Err(io::Error::new(io::ErrorKind::InvalidData, message)); } self.table[i] = value; diff --git a/src/lib.rs b/src/lib.rs index 4b8a3ce..4d38e74 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,15 @@ //! A Rust implementation of DEFLATE algorithm and related formats (ZLIB, GZIP). + #![forbid(unsafe_code)] #![warn(missing_docs)] +#![cfg_attr(no_std, feature = "no_std")] + pub use finish::Finish; +#[cfg(feature = "no_std")] +extern crate alloc; + +#[cfg(not(feature = "no_std"))] macro_rules! invalid_data_error { ($fmt:expr) => { invalid_data_error!("{}", $fmt) }; ($fmt:expr, $($arg:tt)*) => { @@ -10,6 +17,16 @@ macro_rules! invalid_data_error { } } +#[cfg(feature = "no_std")] +macro_rules! invalid_data_error { + ($fmt:expr) => { + invalid_data_error!($fmt, "") + }; + ($fmt:expr, $($arg:tt)*) => { + ::core2::io::Error::new(::core2::io::ErrorKind::InvalidData, $fmt) + }; +} + macro_rules! finish_try { ($e:expr) => { match $e.unwrap() { diff --git a/src/non_blocking/deflate/decode.rs b/src/non_blocking/deflate/decode.rs index 9442e25..9b2c023 100644 --- a/src/non_blocking/deflate/decode.rs +++ b/src/non_blocking/deflate/decode.rs @@ -1,9 +1,15 @@ use crate::deflate::symbol::{self, HuffmanCodec}; use crate::lz77; use crate::non_blocking::transaction::TransactionalBitReader; -use std::cmp; -use std::io; -use std::io::Read; +#[cfg(feature = "no_std")] +use core::cmp; +#[cfg(feature = "no_std")] +use core2::io::{self, Read}; +#[cfg(not(feature = "no_std"))] +use std::{ + cmp, + io::{self, Read}, +}; /// DEFLATE decoder which supports non-blocking I/O. #[derive(Debug)] @@ -20,6 +26,9 @@ impl Decoder { /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::{Cursor, Read}; + /// #[cfg(not(feature = "no_std"))] /// use std::io::{Cursor, Read}; /// use libflate::non_blocking::deflate::Decoder; /// @@ -53,6 +62,9 @@ impl Decoder { /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Cursor; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Cursor; /// use libflate::non_blocking::deflate::Decoder; /// @@ -243,12 +255,15 @@ mod tests { use super::*; use crate::deflate::{EncodeOptions, Encoder}; use crate::util::{nb_read_to_end, WouldBlockReader}; - use std::io::{self, Read}; + #[cfg(feature = "no_std")] + use core2::io::{Read, Write}; + #[cfg(not(feature = "no_std"))] + use std::io::{Read, Write}; #[test] fn it_works() { let mut encoder = Encoder::new(Vec::new()); - io::copy(&mut &b"Hello World!"[..], &mut encoder).unwrap(); + encoder.write_all(b"Hello World!".as_ref()).unwrap(); let encoded_data = encoder.finish().into_result().unwrap(); let mut decoder = Decoder::new(&encoded_data[..]); @@ -261,7 +276,7 @@ mod tests { #[test] fn non_blocking_io_works() { let mut encoder = Encoder::new(Vec::new()); - io::copy(&mut &b"Hello World!"[..], &mut encoder).unwrap(); + encoder.write_all(b"Hello World!".as_ref()).unwrap(); let encoded_data = encoder.finish().into_result().unwrap(); let decoder = Decoder::new(WouldBlockReader::new(&encoded_data[..])); @@ -278,7 +293,7 @@ mod tests { .collect(); let mut encoder = crate::deflate::Encoder::new(Vec::new()); - io::copy(&mut text.as_bytes(), &mut encoder).unwrap(); + encoder.write_all(text.as_bytes()).unwrap(); let encoded_data = encoder.finish().into_result().unwrap(); let decoder = Decoder::new(WouldBlockReader::new(&encoded_data[..])); @@ -289,7 +304,7 @@ mod tests { #[test] fn non_compressed_non_blocking_io_works() { let mut encoder = Encoder::with_options(Vec::new(), EncodeOptions::new().no_compression()); - io::copy(&mut &b"Hello World!"[..], &mut encoder).unwrap(); + encoder.write_all(b"Hello World!".as_ref()).unwrap(); let encoded_data = encoder.finish().into_result().unwrap(); let decoder = Decoder::new(WouldBlockReader::new(&encoded_data[..])); diff --git a/src/non_blocking/deflate/mod.rs b/src/non_blocking/deflate/mod.rs index 23e2560..3099a9b 100644 --- a/src/non_blocking/deflate/mod.rs +++ b/src/non_blocking/deflate/mod.rs @@ -4,13 +4,16 @@ //! //! # Examples //! ``` -//! use std::io::{self, Read}; +//! #[cfg(feature = "no_std")] +//! use core2::io::{Read, Write}; +//! #[cfg(not(feature = "no_std"))] +//! use std::io::{Read, Write}; //! use libflate::deflate::Encoder; //! use libflate::non_blocking::deflate::Decoder; //! //! // Encoding //! let mut encoder = Encoder::new(Vec::new()); -//! io::copy(&mut &b"Hello World!"[..], &mut encoder).unwrap(); +//! encoder.write_all(b"Hello World!".as_ref()).unwrap(); //! let encoded_data = encoder.finish().into_result().unwrap(); //! //! // Decoding diff --git a/src/non_blocking/gzip.rs b/src/non_blocking/gzip.rs index 7ff3102..c06ed46 100644 --- a/src/non_blocking/gzip.rs +++ b/src/non_blocking/gzip.rs @@ -4,13 +4,16 @@ //! //! # Examples //! ``` -//! use std::io::{self, Read}; +//! #[cfg(feature = "no_std")] +//! use core2::io::{Read, Write}; +//! #[cfg(not(feature = "no_std"))] +//! use std::io::{Read, Write}; //! use libflate::gzip::Encoder; //! use libflate::non_blocking::gzip::Decoder; //! //! // Encoding //! let mut encoder = Encoder::new(Vec::new()).unwrap(); -//! io::copy(&mut &b"Hello World!"[..], &mut encoder).unwrap(); +//! encoder.write_all(&b"Hello World!".as_ref()).unwrap(); //! let encoded_data = encoder.finish().into_result().unwrap(); //! //! // Decoding @@ -23,6 +26,9 @@ use crate::checksum; use crate::gzip::{Header, Trailer}; use crate::non_blocking::deflate; +#[cfg(feature = "no_std")] +use core2::io::{self, Read}; +#[cfg(not(feature = "no_std"))] use std::io::{self, Read}; /// GZIP decoder which supports non-blocking I/O. @@ -40,6 +46,9 @@ impl Decoder { /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Read; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Read; /// use libflate::non_blocking::gzip::Decoder; /// @@ -103,6 +112,9 @@ impl Decoder { /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Cursor; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Cursor; /// use libflate::non_blocking::gzip::Decoder; /// @@ -157,7 +169,10 @@ mod tests { use super::*; use crate::gzip::Encoder; use crate::util::{nb_read_to_end, WouldBlockReader}; - use std::io; + #[cfg(feature = "no_std")] + use core2::io::Write; + #[cfg(not(feature = "no_std"))] + use std::io::Write; fn decode_all(buf: &[u8]) -> io::Result> { let decoder = Decoder::new(WouldBlockReader::new(buf)); @@ -168,7 +183,7 @@ mod tests { fn encode_works() { let plain = b"Hello World! Hello GZIP!!"; let mut encoder = Encoder::new(Vec::new()).unwrap(); - io::copy(&mut &plain[..], &mut encoder).unwrap(); + encoder.write_all(plain.as_ref()).unwrap(); let encoded = encoder.finish().into_result().unwrap(); assert_eq!(decode_all(&encoded).unwrap(), plain); } diff --git a/src/non_blocking/transaction.rs b/src/non_blocking/transaction.rs index 236b18c..d3f23ca 100644 --- a/src/non_blocking/transaction.rs +++ b/src/non_blocking/transaction.rs @@ -1,6 +1,15 @@ use crate::bit; -use std::cmp; -use std::io::{self, Read}; +#[cfg(feature = "no_std")] +use alloc::vec::Vec; +#[cfg(feature = "no_std")] +use core::cmp; +#[cfg(feature = "no_std")] +use core2::io::{self, Read}; +#[cfg(not(feature = "no_std"))] +use std::{ + cmp, + io::{self, Read}, +}; #[derive(Debug)] pub struct TransactionalBitReader { diff --git a/src/non_blocking/zlib.rs b/src/non_blocking/zlib.rs index b5bd576..26c356a 100644 --- a/src/non_blocking/zlib.rs +++ b/src/non_blocking/zlib.rs @@ -4,13 +4,16 @@ //! //! # Examples //! ``` -//! use std::io::{self, Read}; +//! #[cfg(feature = "no_std")] +//! use core2::io::{Read, Write}; +//! #[cfg(not(feature = "no_std"))] +//! use std::io::{Read, Write}; //! use libflate::zlib::Encoder; //! use libflate::non_blocking::zlib::Decoder; //! //! // Encoding //! let mut encoder = Encoder::new(Vec::new()).unwrap(); -//! io::copy(&mut &b"Hello World!"[..], &mut encoder).unwrap(); +//! encoder.write_all(b"Hello World!".as_ref()).unwrap(); //! let encoded_data = encoder.finish().into_result().unwrap(); //! //! // Decoding @@ -23,6 +26,9 @@ use crate::checksum; use crate::non_blocking::deflate; use crate::zlib::Header; +#[cfg(feature = "no_std")] +use core2::io::{self, Read}; +#[cfg(not(feature = "no_std"))] use std::io::{self, Read}; /// ZLIB decoder which supports non-blocking I/O. @@ -40,6 +46,9 @@ impl Decoder { /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Read; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Read; /// use libflate::non_blocking::zlib::Decoder; /// @@ -102,6 +111,9 @@ impl Decoder { /// /// # Examples /// ``` + /// #[cfg(feature = "no_std")] + /// use core2::io::Cursor; + /// #[cfg(not(feature = "no_std"))] /// use std::io::Cursor; /// use libflate::non_blocking::zlib::Decoder; /// @@ -157,17 +169,22 @@ mod tests { use super::*; use crate::util::{nb_read_to_end, WouldBlockReader}; use crate::zlib::{EncodeOptions, Encoder}; - use std::io; + #[cfg(feature = "no_std")] + use core2::io::Write; + #[cfg(not(feature = "no_std"))] + use std::io::Write; fn decode_all(buf: &[u8]) -> io::Result> { let decoder = Decoder::new(WouldBlockReader::new(buf)); nb_read_to_end(decoder) } + #[cfg(not(feature = "no_std"))] fn default_encode(buf: &[u8]) -> io::Result> { let mut encoder = Encoder::new(Vec::new()).unwrap(); - io::copy(&mut &buf[..], &mut encoder).unwrap(); + encoder.write_all(buf.as_ref()).unwrap(); encoder.finish().into_result() } + #[cfg(not(feature = "no_std"))] macro_rules! assert_encode_decode { ($input:expr) => {{ let encoded = default_encode(&$input[..]).unwrap(); @@ -187,6 +204,7 @@ mod tests { } #[test] + #[cfg(not(feature = "no_std"))] fn default_encode_works() { let plain = b"Hello World! Hello ZLIB!!"; let mut encoder = Encoder::new(Vec::new()).unwrap(); @@ -196,6 +214,7 @@ mod tests { } #[test] + #[cfg(not(feature = "no_std"))] fn best_speed_encode_works() { let plain = b"Hello World! Hello ZLIB!!"; let mut encoder = @@ -215,7 +234,7 @@ mod tests { let plain = b"Hello World!"; let mut encoder = Encoder::with_options(Vec::new(), EncodeOptions::new().no_compression()).unwrap(); - io::copy(&mut &plain[..], &mut encoder).unwrap(); + encoder.write_all(plain.as_ref()).unwrap(); let encoded = encoder.finish().into_result().unwrap(); let expected = RAW_ENCODE_WORKS_EXPECTED; assert_eq!(encoded, expected); @@ -223,6 +242,7 @@ mod tests { } #[test] + #[cfg(not(feature = "no_std"))] fn test_issue_2() { // See: https://github.com/sile/libflate/issues/2 assert_encode_decode!([ diff --git a/src/util.rs b/src/util.rs index 82f58d1..d9f39f4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,4 +1,6 @@ -#[cfg(test)] +#[cfg(all(test, feature = "no_std"))] +use core2::io::{self, Read}; +#[cfg(all(test, not(feature = "no_std")))] use std::io::{self, Read}; #[cfg(test)] diff --git a/src/zlib.rs b/src/zlib.rs index c383f03..39add9a 100644 --- a/src/zlib.rs +++ b/src/zlib.rs @@ -4,12 +4,15 @@ //! //! # Examples //! ``` -//! use std::io::{self, Read}; +//! #[cfg(not(feature = "no_std"))] +//! use std::io::{Read, Write}; +//! #[cfg(feature = "no_std")] +//! use core2::io::{Read, Write}; //! use libflate::zlib::{Encoder, Decoder}; //! //! // Encoding //! let mut encoder = Encoder::new(Vec::new()).unwrap(); -//! io::copy(&mut &b"Hello World!"[..], &mut encoder).unwrap(); +//! encoder.write_all(&b"Hello World!"[..]).unwrap(); //! let encoded_data = encoder.finish().into_result().unwrap(); //! //! // Decoding @@ -23,6 +26,9 @@ use crate::checksum; use crate::deflate; use crate::finish::{Complete, Finish}; use crate::lz77; +#[cfg(feature = "no_std")] +use core2::io; +#[cfg(not(feature = "no_std"))] use std::io; const COMPRESSION_METHOD_DEFLATE: u8 = 8; @@ -252,11 +258,10 @@ impl Header { if dict_flag { 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}", - dictionary_id + u32::from_be_bytes(buf) )); } let compression_level = CompressionLevel::from_u2(flg >> 6); @@ -298,7 +303,10 @@ where /// /// # Examples /// ``` + /// #[cfg(not(feature = "no_std"))] /// use std::io::Read; + /// #[cfg(feature = "no_std")] + /// use core2::io::Read; /// use libflate::zlib::Decoder; /// /// let encoded_data = [120, 156, 243, 72, 205, 201, 201, 87, 8, 207, 47, @@ -351,7 +359,10 @@ where /// /// # Examples /// ``` + /// #[cfg(not(feature = "no_std"))] /// use std::io::Cursor; + /// #[cfg(feature = "no_std")] + /// use core2::io::Cursor; /// use libflate::zlib::Decoder; /// /// let encoded_data = [120, 156, 243, 72, 205, 201, 201, 87, 8, 207, 47, @@ -529,7 +540,10 @@ where /// /// # Examples /// ``` + /// #[cfg(not(feature = "no_std"))] /// use std::io::Write; + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; /// use libflate::zlib::Encoder; /// /// let mut encoder = Encoder::new(Vec::new()).unwrap(); @@ -554,7 +568,10 @@ where /// /// # Examples /// ``` + /// #[cfg(not(feature = "no_std"))] /// use std::io::Write; + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; /// use libflate::zlib::{Encoder, EncodeOptions}; /// /// let options = EncodeOptions::new().no_compression(); @@ -592,7 +609,10 @@ where /// /// # Examples /// ``` + /// #[cfg(not(feature = "no_std"))] /// use std::io::Write; + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; /// use libflate::zlib::Encoder; /// /// let mut encoder = Encoder::new(Vec::new()).unwrap(); @@ -609,14 +629,17 @@ where /// it may be convenient to use `AutoFinishUnchecked` instead of the explicit invocation of this method. /// /// ``` - /// use std::io; + /// #[cfg(feature = "no_std")] + /// use core2::io::Write; + /// #[cfg(not(feature = "no_std"))] + /// use std::io::Write; /// use libflate::finish::AutoFinishUnchecked; /// use libflate::zlib::Encoder; /// /// let plain = b"Hello World!"; /// let mut buf = Vec::new(); /// let mut encoder = AutoFinishUnchecked::new(Encoder::new(&mut buf).unwrap()); - /// io::copy(&mut &plain[..], &mut encoder).unwrap(); + /// encoder.write_all(plain.as_ref()).unwrap(); /// ``` pub fn finish(self) -> Finish { let mut inner = finish_try!(self.writer.finish()); @@ -675,17 +698,20 @@ where mod tests { use super::*; use crate::finish::AutoFinish; - use std::io::{self, Read as _, Write as _}; + #[cfg(feature = "no_std")] + use core2::io::{Read as _, Write as _}; + #[cfg(not(feature = "no_std"))] + use std::io::{Read as _, Write as _}; fn decode_all(buf: &[u8]) -> io::Result> { let mut decoder = Decoder::new(buf).unwrap(); let mut buf = Vec::with_capacity(buf.len()); - io::copy(&mut decoder, &mut buf)?; + decoder.read_to_end(&mut buf)?; Ok(buf) } fn default_encode(buf: &[u8]) -> io::Result> { let mut encoder = Encoder::new(Vec::new()).unwrap(); - io::copy(&mut &buf[..], &mut encoder).unwrap(); + encoder.write_all(buf).unwrap(); encoder.finish().into_result() } macro_rules! assert_encode_decode { @@ -711,7 +737,7 @@ mod tests { ); let mut buf = Vec::new(); - io::copy(&mut decoder, &mut buf).unwrap(); + decoder.read_to_end(&mut buf).unwrap(); let expected = b"Hello World!"; assert_eq!(buf, expected); @@ -721,7 +747,7 @@ mod tests { fn default_encode_works() { let plain = b"Hello World! Hello ZLIB!!"; let mut encoder = Encoder::new(Vec::new()).unwrap(); - io::copy(&mut &plain[..], &mut encoder).unwrap(); + encoder.write_all(plain.as_ref()).unwrap(); let encoded = encoder.finish().into_result().unwrap(); assert_eq!(decode_all(&encoded).unwrap(), plain); } @@ -732,7 +758,7 @@ mod tests { let mut encoder = Encoder::with_options(Vec::new(), EncodeOptions::default().fixed_huffman_codes()) .unwrap(); - io::copy(&mut &plain[..], &mut encoder).unwrap(); + encoder.write_all(plain.as_ref()).unwrap(); let encoded = encoder.finish().into_result().unwrap(); assert_eq!(decode_all(&encoded).unwrap(), plain); } @@ -746,7 +772,7 @@ mod tests { let plain = b"Hello World!"; let mut encoder = Encoder::with_options(Vec::new(), EncodeOptions::new().no_compression()).unwrap(); - io::copy(&mut &plain[..], &mut encoder).unwrap(); + encoder.write_all(plain.as_ref()).unwrap(); let encoded = encoder.finish().into_result().unwrap(); let expected = RAW_ENCODE_WORKS_EXPECTED; assert_eq!(encoded, expected); @@ -759,7 +785,7 @@ mod tests { let mut buf = Vec::new(); { let mut encoder = AutoFinish::new(Encoder::new(&mut buf).unwrap()); - io::copy(&mut &plain[..], &mut encoder).unwrap(); + encoder.write_all(plain.as_ref()).unwrap(); } assert_eq!(decode_all(&buf).unwrap(), plain); } @@ -792,22 +818,37 @@ mod tests { let encoded = include_bytes!("../data/issues_16/crash-1bb6d408475a5bd57247ee40f290830adfe2086e"); assert_eq!( - decode_all(&encoded[..]).err().map(|e| e.to_string()), - Some("The value of HDIST is too big: max=30, actual=32".to_owned()) + &decode_all(&encoded[..]) + .err() + .map(|e| e.to_string()) + .unwrap()[..31], + "The value of HDIST is too big: max=30, actual=32"[..31] + .to_owned() + .as_str() ); let encoded = include_bytes!("../data/issues_16/crash-369e8509a0e76356f4549c292ceedee429cfe125"); assert_eq!( - decode_all(&encoded[..]).err().map(|e| e.to_string()), - Some("The value of HDIST is too big: max=30, actual=32".to_owned()) + &decode_all(&encoded[..]) + .err() + .map(|e| e.to_string()) + .unwrap()[..31], + "The value of HDIST is too big: max=30, actual=32"[..31] + .to_owned() + .as_str() ); let encoded = include_bytes!("../data/issues_16/crash-e75959d935650306881140df7f6d1d73e33425cb"); assert_eq!( - decode_all(&encoded[..]).err().map(|e| e.to_string()), - Some("The value of HDIST is too big: max=30, actual=32".to_owned()) + &decode_all(&encoded[..]) + .err() + .map(|e| e.to_string()) + .unwrap()[..31], + "The value of HDIST is too big: max=30, actual=32"[..31] + .to_owned() + .as_str() ); } @@ -877,13 +918,14 @@ mod tests { } #[test] + #[cfg(not(feature = "no_std"))] /// See: https://github.com/sile/libflate/issues/61 fn issue_61() { let data = default_encode(b"Hello World").unwrap(); let mut decoder = Decoder::new(&data[..]).unwrap(); let mut buf = Vec::new(); decoder.read(&mut buf).unwrap(); - io::copy(&mut decoder, &mut buf).unwrap(); + decoder.read_to_end(&mut buf).unwrap(); assert_eq!(buf, b"Hello World"); } }