From ee2989758f95b2dcc58c9b484d638ee32abdebd1 Mon Sep 17 00:00:00 2001 From: Alyssa Haroldsen Date: Fri, 9 Jun 2023 20:45:05 -0700 Subject: [PATCH] Turn the no_std feature into default-enabled std This also: - fixes the `no_std` not being enabled due to a swapped `cfg_attr`. - tests this builds with a `#![no_std]` binary. - A lot of the cfg's have been removed due to being unneeded. - adds a new dependency - updates the version to 2.0 - adds a ci command to to use cargo-no-std to check no-std Some notes on changes from #68: Everything in `core` is a subset of things in `std`. `core` is available in `std` environments, so if you're building a `no_std`-compatible library, it's best to import things that don't _require_ `std` from `core. core2 is also meant to be used as a `no_std` polyfill with its `std` feature. That is, you can reference `core2::io`, and if the `std` feature is enabled, it actually references `std::io`. --- .github/workflows/ci.yml | 55 +++++++++++----- Cargo.toml | 16 +++-- examples/flate.rs | 38 +++++------ libflate_lz77/Cargo.toml | 11 ++-- libflate_lz77/src/default.rs | 8 +-- libflate_lz77/src/lib.rs | 18 ++--- src/bit.rs | 7 +- src/checksum.rs | 3 - src/deflate/decode.rs | 23 +++---- src/deflate/encode.rs | 18 +---- src/deflate/mod.rs | 6 -- src/deflate/symbol.rs | 17 ++--- src/deflate/test_data.rs | 3 +- src/finish.rs | 13 ---- src/gzip.rs | 66 +++++-------------- src/huffman.rs | 20 +++--- src/lib.rs | 13 +--- src/lz77.rs | 1 + src/non_blocking/deflate/decode.rs | 18 +---- src/non_blocking/deflate/mod.rs | 3 - src/non_blocking/gzip.rs | 15 ----- src/non_blocking/transaction.rs | 8 --- src/non_blocking/zlib.rs | 26 ++------ src/util.rs | 101 +++++++++++++++-------------- src/zlib.rs | 33 ++-------- 25 files changed, 187 insertions(+), 353 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f02b012..a426e19 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,7 @@ jobs: strategy: matrix: toolchain: [stable, beta, nightly] + features: [--no-default-features, --all-features] steps: - name: Checkout sources uses: actions/checkout@v1 @@ -26,7 +27,41 @@ jobs: uses: actions-rs/cargo@v1 with: command: check - args: --all-features --all + args: ${{ matrix.features }} --workspace + + no-std: + name: no_std Check + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v1 + + - name: Install nightly toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + override: true + + - name: Install cargo no-std-check + uses: actions-rs/cargo@v1 + with: + command: install + args: cargo-no-std-check + + # https://github.com/mystor/cargo-no-std-check/issues/2 + # `--no-default-features` doesn't work with `--workspace` correctly. + - name: Run cargo no-std-check on libflate crate + uses: actions-rs/cargo@v1 + with: + command: no-std-check + args: --no-default-features + + - name: Run cargo no-std-check on libflate_lz77 crate + uses: actions-rs/cargo@v1 + with: + command: no-std-check + args: --no-default-features --manifest-path libflate_lz77/Cargo.toml test: name: Test Suite @@ -34,6 +69,7 @@ jobs: strategy: matrix: toolchain: [stable, beta, nightly] + features: [--no-default-features, --all-features] steps: - name: Checkout sources uses: actions/checkout@v1 @@ -49,7 +85,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --all-features --all + args: ${{ matrix.features }} --workspace lints: name: Lints @@ -57,6 +93,7 @@ jobs: strategy: matrix: toolchain: [stable, beta, nightly] + features: [--no-default-features, --all-features] steps: - name: Checkout sources uses: actions/checkout@v1 @@ -75,21 +112,9 @@ jobs: command: fmt args: --all -- --check - - name: Run cargo clippy - if: matrix.toolchain == 'beta' - uses: actions-rs/cargo@v1 - with: - command: clippy - # As `return_self_not_must_use` became `pedantic` in the 1.60.0-nightly channel, - # we allow the warning to avoid unnecessary code fixes. - # See: https://github.com/rust-lang/rust-clippy/issues/8197 - # - # TODO: Remove this branch once stable-1.59.0 is released. - args: --all-features --all -- -D warnings --allow clippy::return_self_not_must_use - - name: Run cargo clippy if: matrix.toolchain != 'beta' uses: actions-rs/cargo@v1 with: command: clippy - args: --all-features --all -- -D warnings + args: ${{ matrix.features }} --workspace -- -D warnings diff --git a/Cargo.toml b/Cargo.toml index bec8ed7..ee8451b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "libflate" -version = "1.4.0" +version = "2.0.0" authors = ["Takeru Ohta "] description = "A Rust implementation of DEFLATE algorithm and related formats (ZLIB, GZIP)" homepage = "https://github.com/sile/libflate" repository = "https://github.com/sile/libflate" readme = "README.md" keywords = ["deflate", "gzip", "zlib"] -categories = ["compression"] +categories = ["compression", "no-std"] license = "MIT" edition = "2018" @@ -15,13 +15,15 @@ edition = "2018" coveralls = {repository = "sile/libflate"} [dependencies] -adler32 = "1" -crc32fast = "1.1.1" -libflate_lz77 = { path = "libflate_lz77", version = "1.1", default_features = false } -core2 = { version = "0.4", default_features = false, features = ["alloc"], optional = true } +adler32 = { version = "1", default-features = false } +crc32fast = { version = "1.1.1", default-features = false } +dary_heap = "0.3.5" +libflate_lz77 = { path = "libflate_lz77", version = "2.0.0", default-features = false } +core2 = { version = "0.4", default-features = false, features = ["alloc"] } [features] -no_std = ["libflate_lz77/no_std", "core2"] +default = ["std"] +std = ["libflate_lz77/std", "core2/std"] [dev-dependencies] clap = "2" diff --git a/examples/flate.rs b/examples/flate.rs index 93c4d01..5162da4 100644 --- a/examples/flate.rs +++ b/examples/flate.rs @@ -1,32 +1,24 @@ +#![cfg_attr(not(feature = "std"), no_std)] + 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")] +#[cfg(not(feature = "std"))] fn main() {} -#[cfg(not(feature = "no_std"))] +#[cfg(feature = "std")] fn main() { + use clap::App; + use clap::Arg; + use clap::SubCommand; + use libflate::gzip; + use libflate::zlib; + use std::fs; + use std::io; + use std::io::Read; + use std::io::Write; + use std::process; + let matches = App::new("deflate") .arg( Arg::with_name("INPUT") diff --git a/libflate_lz77/Cargo.toml b/libflate_lz77/Cargo.toml index 393dfe3..caa8523 100644 --- a/libflate_lz77/Cargo.toml +++ b/libflate_lz77/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libflate_lz77" -version = "1.2.0" +version = "2.0.0" authors = ["Takeru Ohta "] edition = "2018" description = "LZ77 encoder for libflate crate" @@ -16,11 +16,12 @@ 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 } +core2 = { version = "0.4", default-features = false, features = ["alloc"] } +hashbrown = { version = "0.13" } [dev-dependencies] -libflate = { path = "../", version = "1" } +libflate = { path = "../", version = "2.0", default-features = false } [features] -no_std = ["core2", "hashbrown"] +default = ["std"] +std = ["core2/std", "libflate/std"] diff --git a/libflate_lz77/src/default.rs b/libflate_lz77/src/default.rs index 0ba8e14..c565116 100644 --- a/libflate_lz77/src/default.rs +++ b/libflate_lz77/src/default.rs @@ -1,11 +1,9 @@ -#[cfg(feature = "no_std")] use alloc::vec::Vec; -#[cfg(feature = "no_std")] use core::cmp; -#[cfg(feature = "no_std")] +#[cfg(not(feature = "std"))] use hashbrown::HashMap; -#[cfg(not(feature = "no_std"))] -use std::{cmp, collections::HashMap}; +#[cfg(feature = "std")] +use std::collections::HashMap; use super::Code; use super::Lz77Encode; diff --git a/libflate_lz77/src/lib.rs b/libflate_lz77/src/lib.rs index fc97b9f..e6a4883 100644 --- a/libflate_lz77/src/lib.rs +++ b/libflate_lz77/src/lib.rs @@ -2,19 +2,15 @@ //! //! 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_attr(not(feature = "std"), 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 core::cmp; use core2::io; use rle_decode_fast::rle_decode; -#[cfg(not(feature = "no_std"))] -use std::io; mod default; @@ -180,13 +176,13 @@ impl Lz77Decoder { if self.buffer.len() < backward_distance as usize { return Err(io::Error::new( io::ErrorKind::InvalidData, - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "std")] format!( "Too long backword reference: buffer.len={}, distance={}", self.buffer.len(), backward_distance ), - #[cfg(feature = "no_std")] + #[cfg(not(feature = "std"))] "Too long backword reference", )); } @@ -240,7 +236,7 @@ impl Lz77Decoder { 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); + let copy_size = 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; self.truncate_old_buffer(); @@ -251,12 +247,8 @@ impl 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] fn encoder_and_decoder_works() { diff --git a/src/bit.rs b/src/bit.rs index 816eeac..f50d6df 100644 --- a/src/bit.rs +++ b/src/bit.rs @@ -1,7 +1,4 @@ -#[cfg(feature = "no_std")] use core2::io; -#[cfg(not(feature = "no_std"))] -use std::io; #[derive(Debug)] pub struct BitWriter { @@ -179,10 +176,8 @@ pub(crate) struct BitReaderState { #[cfg(test)] mod tests { use super::*; - #[cfg(feature = "no_std")] + use alloc::vec::Vec; use core2::io; - #[cfg(not(feature = "no_std"))] - use std::io; #[test] fn writer_works() { diff --git a/src/checksum.rs b/src/checksum.rs index 5424d70..7f644a0 100644 --- a/src/checksum.rs +++ b/src/checksum.rs @@ -1,8 +1,5 @@ use adler32::RollingAdler32; -#[cfg(feature = "no_std")] use core::fmt; -#[cfg(not(feature = "no_std"))] -use std::fmt; pub struct Adler32(RollingAdler32); impl Adler32 { diff --git a/src/deflate/decode.rs b/src/deflate/decode.rs index 492e2e4..24e176b 100644 --- a/src/deflate/decode.rs +++ b/src/deflate/decode.rs @@ -1,10 +1,7 @@ use super::symbol; use crate::bit; use crate::lz77; -#[cfg(feature = "no_std")] use core2::io::{self, Read}; -#[cfg(not(feature = "no_std"))] -use std::io::{self, Read}; /// DEFLATE decoder. #[derive(Debug)] @@ -23,10 +20,9 @@ where /// /// # Examples /// ``` - /// #[cfg(feature = "no_std")] + /// # extern crate alloc; + /// # use alloc::vec::Vec; /// use core2::io::{Cursor, Read}; - /// #[cfg(not(feature = "no_std"))] - /// use std::io::{Cursor, Read}; /// use libflate::deflate::Decoder; /// /// let encoded_data = [243, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73, 81, 4, 0]; @@ -58,10 +54,7 @@ where /// /// # Examples /// ``` - /// #[cfg(feature = "no_std")] /// use core2::io::Cursor; - /// #[cfg(not(feature = "no_std"))] - /// use std::io::Cursor; /// use libflate::deflate::Decoder; /// /// let encoded_data = [243, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73, 81, 4, 0]; @@ -105,9 +98,9 @@ where if used != len.into() { Err(io::Error::new( io::ErrorKind::UnexpectedEof, - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "std")] format!("The reader has incorrect length: expected {len}, read {used}"), - #[cfg(feature = "no_std")] + #[cfg(not(feature = "std"))] "The reader has incorrect length", )) } else { @@ -173,10 +166,10 @@ where #[cfg(test)] mod tests { - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "std")] use super::*; use crate::deflate::symbol::{DynamicHuffmanCodec, HuffmanCodec}; - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "std")] use std::io; #[test] @@ -197,7 +190,7 @@ mod tests { } #[test] - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "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, @@ -219,7 +212,7 @@ mod tests { } #[test] - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "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 259a183..4e708a4 100644 --- a/src/deflate/encode.rs +++ b/src/deflate/encode.rs @@ -3,12 +3,9 @@ use super::BlockType; use crate::bit; use crate::finish::{Complete, Finish}; use crate::lz77; -#[cfg(feature = "no_std")] +use alloc::vec::Vec; 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; @@ -146,10 +143,7 @@ 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()); @@ -174,10 +168,7 @@ 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(); @@ -199,10 +190,7 @@ 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()); @@ -441,10 +429,7 @@ 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] fn test_issues_52() { @@ -485,6 +470,7 @@ mod tests { encoder.flush().expect("Flush failed"); } let finished = encoder.finish().unwrap(); + #[cfg(feature = "std")] println!("{:?}", finished.0); let mut output = Vec::new(); diff --git a/src/deflate/mod.rs b/src/deflate/mod.rs index 88e976d..161a478 100644 --- a/src/deflate/mod.rs +++ b/src/deflate/mod.rs @@ -4,10 +4,7 @@ //! //! # Examples //! ``` -//! #[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 @@ -45,10 +42,7 @@ 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] fn encode_and_decode_works() { diff --git a/src/deflate/symbol.rs b/src/deflate/symbol.rs index 3fc8258..4db7bd5 100644 --- a/src/deflate/symbol.rs +++ b/src/deflate/symbol.rs @@ -2,12 +2,9 @@ use crate::bit; use crate::huffman; use crate::huffman::Builder; use crate::lz77; -#[cfg(feature = "no_std")] +use alloc::{boxed::Box, vec::Vec}; 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), @@ -217,9 +214,9 @@ impl Decoder { 0..=255 => Symbol::Code(lz77::Code::Literal(decoded as u8)), 256 => Symbol::EndOfBlock, 286 | 287 => { - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "std")] let message = format!("The value {decoded} must not occur in compressed data"); - #[cfg(feature = "no_std")] + #[cfg(not(feature = "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 @@ -396,11 +393,11 @@ 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"))] + #[cfg(feature = "std")] let message = format!( "The value of HDIST is too big: max={MAX_DISTANCE_CODE_COUNT}, actual={distance_code_count}" ); - #[cfg(feature = "no_std")] + #[cfg(not(feature = "std"))] let message = "The value of HDIST is too big: max={MAX_DISTANCE_CODE_COUNT}"; return Err(io::Error::new(io::ErrorKind::InvalidData, message)); } @@ -434,13 +431,13 @@ 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"))] + #[cfg(feature = "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")] + #[cfg(not(feature = "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/deflate/test_data.rs b/src/deflate/test_data.rs index c3ea757..0f97dc4 100644 --- a/src/deflate/test_data.rs +++ b/src/deflate/test_data.rs @@ -1,5 +1,4 @@ -// Seperate module for large regression test data, to keep the test code readable. -// +//! Seperate module for large regression test data, to keep the test code readable. pub const ISSUE_52_INPUT: [u8; 16_052] = [ 80, 80, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 54, 56, 50, 49, 53, 56, 48, 48, 48, 48, diff --git a/src/finish.rs b/src/finish.rs index ac1a54d..effbb6d 100644 --- a/src/finish.rs +++ b/src/finish.rs @@ -1,14 +1,7 @@ //! `Finish` and related types. -#[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. @@ -112,10 +105,7 @@ impl AutoFinish { /// # Examples /// /// ``` - /// #[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; /// @@ -177,10 +167,7 @@ impl AutoFinishUnchecked { /// # Examples /// /// ``` - /// #[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; /// diff --git a/src/gzip.rs b/src/gzip.rs index 52d4e1a..2eca78c 100644 --- a/src/gzip.rs +++ b/src/gzip.rs @@ -4,10 +4,7 @@ //! //! # Examples //! ``` -//! #[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 @@ -26,12 +23,10 @@ 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}; +#[cfg(feature = "std")] +use std::time; const GZIP_ID: [u8; 2] = [31, 139]; const COMPRESSION_METHOD_DEFLATE: u8 = 8; @@ -149,12 +144,12 @@ impl HeaderBuilder { /// ``` pub fn new() -> Self { // wasm-unknown-unknown does not implement the time module - #[cfg(all(not(target_arch = "wasm32"), not(feature = "no_std")))] + #[cfg(all(not(target_arch = "wasm32"), feature = "std"))] let modification_time = time::UNIX_EPOCH .elapsed() .map(|d| d.as_secs() as u32) .unwrap_or(0); - #[cfg(any(target_arch = "wasm32", feature = "no_std"))] + #[cfg(any(target_arch = "wasm32", not(feature = "std")))] let modification_time = 0; let header = Header { @@ -245,11 +240,11 @@ impl HeaderBuilder { /// /// # Examples /// ``` - /// #[cfg(feature = "no_std")] + /// #[cfg(not(feature = "std"))] /// extern crate alloc; - /// #[cfg(feature = "no_std")] + /// #[cfg(not(feature = "std"))] /// use alloc::ffi::CString; - /// #[cfg(not(feature = "no_std"))] + /// #[cfg(feature = "std")] /// use std::ffi::CString; /// use libflate::gzip::HeaderBuilder; /// @@ -265,11 +260,11 @@ impl HeaderBuilder { /// /// # Examples /// ``` - /// #[cfg(feature = "no_std")] + /// #[cfg(not(feature = "std"))] /// extern crate alloc; - /// #[cfg(feature = "no_std")] + /// #[cfg(not(feature = "std"))] /// use alloc::ffi::CString; - /// #[cfg(not(feature = "no_std"))] + /// #[cfg(feature = "std")] /// use std::ffi::CString; /// use libflate::gzip::HeaderBuilder; /// @@ -772,10 +767,7 @@ 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(); @@ -797,10 +789,7 @@ 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(); @@ -839,10 +828,7 @@ 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(); @@ -857,20 +843,17 @@ 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; /// /// let plain = b"Hello World!"; /// let mut buf = Vec::new(); /// let mut encoder = AutoFinishUnchecked::new(Encoder::new(&mut buf).unwrap()); - /// #[cfg(feature = "no_std")] + /// #[cfg(not(feature = "std"))] /// encoder.write_all(plain.as_ref()).unwrap(); - /// #[cfg(not(feature = "no_std"))] - /// io::copy(&mut &plain[..], &mut encoder).unwrap(); + /// #[cfg(feature = "std")] + /// std::io::copy(&mut &plain[..], &mut encoder).unwrap(); /// ``` pub fn finish(self) -> Finish { let trailer = Trailer { @@ -942,10 +925,7 @@ where /// /// # Examples /// ``` - /// #[cfg(feature = "no_std")] /// use core2::io::Read; - /// #[cfg(not(feature = "no_std"))] - /// use std::io::Read; /// use libflate::gzip::Decoder; /// /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255, @@ -994,10 +974,7 @@ where /// /// # Examples /// ``` - /// #[cfg(feature = "no_std")] /// use core2::io::Cursor; - /// #[cfg(not(feature = "no_std"))] - /// use std::io::Cursor; /// use libflate::gzip::Decoder; /// /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255, @@ -1086,10 +1063,7 @@ where /// /// # Examples /// ``` - /// #[cfg(feature = "no_std")] /// use core2::io::Read; - /// #[cfg(not(feature = "no_std"))] - /// use std::io::Read; /// use libflate::gzip::MultiDecoder; /// /// let mut encoded_data = Vec::new(); @@ -1147,10 +1121,7 @@ where /// /// # Examples /// ``` - /// #[cfg(feature = "no_std")] /// use core2::io::Cursor; - /// #[cfg(not(feature = "no_std"))] - /// use std::io::Cursor; /// use libflate::gzip::MultiDecoder; /// /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255, @@ -1199,10 +1170,8 @@ where mod tests { use super::*; use crate::finish::AutoFinish; - #[cfg(feature = "no_std")] + use alloc::{vec, vec::Vec}; 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(); @@ -1246,10 +1215,7 @@ mod tests { #[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()) .take(2) @@ -1307,8 +1273,10 @@ mod tests { } #[test] - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "std")] fn encode_with_extra_field() { + use std::io; + let mut buf = Vec::new(); let extra_field = ExtraField { subfields: vec![ExtraSubField { diff --git a/src/huffman.rs b/src/huffman.rs index b95f813..d234dec 100644 --- a/src/huffman.rs +++ b/src/huffman.rs @@ -1,13 +1,8 @@ //! Length-limited Huffman Codes. use crate::bit; -#[cfg(feature = "no_std")] -use alloc::vec::Vec; -#[cfg(feature = "no_std")] +use alloc::{vec, vec::Vec}; use core::cmp; -#[cfg(feature = "no_std")] use core2::io; -#[cfg(not(feature = "no_std"))] -use std::{cmp, io}; const MAX_BITWIDTH: u8 = 15; @@ -112,12 +107,12 @@ 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"))] + #[cfg(feature = "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")] + #[cfg(not(feature = "std"))] let message = "Bit region conflict"; return Err(io::Error::new(io::ErrorKind::InvalidData, message)); } @@ -128,7 +123,7 @@ impl Builder for DecoderBuilder { fn finish(self) -> Self::Instance { Decoder { table: self.table, - safely_peek_bitwidth: std::cmp::min( + safely_peek_bitwidth: cmp::min( self.max_bitwidth, self.safely_peek_bitwidth.unwrap_or(1), ), @@ -261,8 +256,8 @@ impl Encoder { #[allow(dead_code)] mod ordinary_huffman_codes { - use std::cmp; - use std::collections::BinaryHeap; + use core::cmp; + use dary_heap::BinaryHeap; pub fn calc_optimal_max_bitwidth(frequencies: &[usize]) -> u8 { let mut heap = BinaryHeap::new(); @@ -280,7 +275,8 @@ mod ordinary_huffman_codes { } } mod length_limited_huffman_codes { - use std::mem; + use alloc::{vec, vec::Vec}; + use core::mem; #[derive(Debug, Clone)] struct Node { diff --git a/src/lib.rs b/src/lib.rs index 4d38e74..3b6c477 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,22 +2,11 @@ #![forbid(unsafe_code)] #![warn(missing_docs)] -#![cfg_attr(no_std, feature = "no_std")] +#![cfg_attr(not(feature = "std"), 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)*) => { - ::std::io::Error::new(::std::io::ErrorKind::InvalidData, format!($fmt, $($arg)*)) - } -} - -#[cfg(feature = "no_std")] macro_rules! invalid_data_error { ($fmt:expr) => { invalid_data_error!($fmt, "") diff --git a/src/lz77.rs b/src/lz77.rs index 835075a..f26d996 100644 --- a/src/lz77.rs +++ b/src/lz77.rs @@ -7,6 +7,7 @@ pub use libflate_lz77::*; mod tests { use super::*; use crate::deflate::symbol::Symbol; + use alloc::{vec, vec::Vec}; #[test] // See: https://github.com/sile/libflate/issues/21 diff --git a/src/non_blocking/deflate/decode.rs b/src/non_blocking/deflate/decode.rs index 9b2c023..519b370 100644 --- a/src/non_blocking/deflate/decode.rs +++ b/src/non_blocking/deflate/decode.rs @@ -1,16 +1,8 @@ use crate::deflate::symbol::{self, HuffmanCodec}; use crate::lz77; use crate::non_blocking::transaction::TransactionalBitReader; -#[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)] pub struct Decoder { @@ -26,10 +18,7 @@ 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; /// /// let encoded_data = [243, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73, 81, 4, 0]; @@ -62,10 +51,7 @@ 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; /// /// let encoded_data = [243, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73, 81, 4, 0]; @@ -255,10 +241,8 @@ mod tests { use super::*; use crate::deflate::{EncodeOptions, Encoder}; use crate::util::{nb_read_to_end, WouldBlockReader}; - #[cfg(feature = "no_std")] + use alloc::{format, string::String, vec::Vec}; use core2::io::{Read, Write}; - #[cfg(not(feature = "no_std"))] - use std::io::{Read, Write}; #[test] fn it_works() { diff --git a/src/non_blocking/deflate/mod.rs b/src/non_blocking/deflate/mod.rs index 3099a9b..eb6c124 100644 --- a/src/non_blocking/deflate/mod.rs +++ b/src/non_blocking/deflate/mod.rs @@ -4,10 +4,7 @@ //! //! # Examples //! ``` -//! #[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; //! diff --git a/src/non_blocking/gzip.rs b/src/non_blocking/gzip.rs index c06ed46..acf61b9 100644 --- a/src/non_blocking/gzip.rs +++ b/src/non_blocking/gzip.rs @@ -4,10 +4,7 @@ //! //! # Examples //! ``` -//! #[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; //! @@ -26,10 +23,7 @@ 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. #[derive(Debug)] @@ -46,10 +40,7 @@ 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; /// /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255, @@ -112,10 +103,7 @@ 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; /// /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255, @@ -169,10 +157,7 @@ mod tests { use super::*; use crate::gzip::Encoder; use crate::util::{nb_read_to_end, WouldBlockReader}; - #[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)); diff --git a/src/non_blocking/transaction.rs b/src/non_blocking/transaction.rs index d3f23ca..4cefe05 100644 --- a/src/non_blocking/transaction.rs +++ b/src/non_blocking/transaction.rs @@ -1,15 +1,7 @@ use crate::bit; -#[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 26c356a..ea20207 100644 --- a/src/non_blocking/zlib.rs +++ b/src/non_blocking/zlib.rs @@ -4,10 +4,7 @@ //! //! # Examples //! ``` -//! #[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; //! @@ -26,10 +23,7 @@ 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. #[derive(Debug)] @@ -46,10 +40,7 @@ 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; /// /// let encoded_data = [120, 156, 243, 72, 205, 201, 201, 87, 8, 207, 47, @@ -111,10 +102,7 @@ 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; /// /// let encoded_data = [120, 156, 243, 72, 205, 201, 201, 87, 8, 207, 47, @@ -169,22 +157,20 @@ mod tests { use super::*; use crate::util::{nb_read_to_end, WouldBlockReader}; use crate::zlib::{EncodeOptions, Encoder}; - #[cfg(feature = "no_std")] + use alloc::vec::Vec; 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"))] + #[cfg(feature = "std")] fn default_encode(buf: &[u8]) -> io::Result> { let mut encoder = Encoder::new(Vec::new()).unwrap(); encoder.write_all(buf.as_ref()).unwrap(); encoder.finish().into_result() } - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "std")] macro_rules! assert_encode_decode { ($input:expr) => {{ let encoded = default_encode(&$input[..]).unwrap(); @@ -204,7 +190,7 @@ mod tests { } #[test] - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "std")] fn default_encode_works() { let plain = b"Hello World! Hello ZLIB!!"; let mut encoder = Encoder::new(Vec::new()).unwrap(); @@ -214,7 +200,7 @@ mod tests { } #[test] - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "std")] fn best_speed_encode_works() { let plain = b"Hello World! Hello ZLIB!!"; let mut encoder = @@ -242,7 +228,7 @@ mod tests { } #[test] - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "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 d9f39f4..c1b56e8 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,64 +1,65 @@ -#[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)] -pub struct WouldBlockReader { - inner: R, - do_block: bool, -} #[cfg(test)] -impl WouldBlockReader { - pub fn new(inner: R) -> Self { - WouldBlockReader { - inner, - do_block: false, +pub(crate) mod testonly { + use alloc::vec::Vec; + use core2::io::{self, Read}; + + pub struct WouldBlockReader { + inner: R, + do_block: bool, + } + + impl WouldBlockReader { + pub fn new(inner: R) -> Self { + WouldBlockReader { + inner, + do_block: false, + } } } -} -#[cfg(test)] -impl Read for WouldBlockReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.do_block = !self.do_block; - if self.do_block { - Err(io::Error::new(io::ErrorKind::WouldBlock, "Would block")) - } else if buf.is_empty() { - Ok(0) - } else { - let mut byte = [0; 1]; - if self.inner.read(&mut byte[..])? == 1 { - buf[0] = byte[0]; - Ok(1) - } else { + + impl Read for WouldBlockReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.do_block = !self.do_block; + if self.do_block { + Err(io::Error::new(io::ErrorKind::WouldBlock, "Would block")) + } else if buf.is_empty() { Ok(0) + } else { + let mut byte = [0; 1]; + if self.inner.read(&mut byte[..])? == 1 { + buf[0] = byte[0]; + Ok(1) + } else { + Ok(0) + } } } } -} -#[cfg(test)] -pub fn nb_read_to_end(mut reader: R) -> io::Result> { - let mut buf = vec![0; 1024]; - let mut offset = 0; - loop { - match reader.read(&mut buf[offset..]) { - Err(e) => { - if e.kind() != io::ErrorKind::WouldBlock { - return Err(e); + pub fn nb_read_to_end(mut reader: R) -> io::Result> { + let mut buf = vec![0; 1024]; + let mut offset = 0; + loop { + match reader.read(&mut buf[offset..]) { + Err(e) => { + if e.kind() != io::ErrorKind::WouldBlock { + return Err(e); + } } - } - Ok(0) => { - buf.truncate(offset); - break; - } - Ok(size) => { - offset += size; - if offset == buf.len() { - buf.resize(offset * 2, 0); + Ok(0) => { + buf.truncate(offset); + break; + } + Ok(size) => { + offset += size; + if offset == buf.len() { + buf.resize(offset * 2, 0); + } } } } + Ok(buf) } - Ok(buf) } +#[cfg(test)] +pub(crate) use testonly::*; diff --git a/src/zlib.rs b/src/zlib.rs index d7b03e0..914c78e 100644 --- a/src/zlib.rs +++ b/src/zlib.rs @@ -4,9 +4,6 @@ //! //! # Examples //! ``` -//! #[cfg(not(feature = "no_std"))] -//! use std::io::{Read, Write}; -//! #[cfg(feature = "no_std")] //! use core2::io::{Read, Write}; //! use libflate::zlib::{Encoder, Decoder}; //! @@ -26,10 +23,7 @@ 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; @@ -230,7 +224,7 @@ impl Header { { let mut buf = [0; 2]; reader.read_exact(&mut buf)?; - let (cmf, flg) = (buf[0], buf[1]); + let [cmf, flg] = buf; let check = (u16::from(cmf) << 8) + u16::from(flg); if check % 31 != 0 { return Err(invalid_data_error!( @@ -303,9 +297,6 @@ where /// /// # Examples /// ``` - /// #[cfg(not(feature = "no_std"))] - /// use std::io::Read; - /// #[cfg(feature = "no_std")] /// use core2::io::Read; /// use libflate::zlib::Decoder; /// @@ -359,9 +350,6 @@ where /// /// # Examples /// ``` - /// #[cfg(not(feature = "no_std"))] - /// use std::io::Cursor; - /// #[cfg(feature = "no_std")] /// use core2::io::Cursor; /// use libflate::zlib::Decoder; /// @@ -547,9 +535,9 @@ where /// /// # Examples /// ``` - /// #[cfg(not(feature = "no_std"))] + /// #[cfg(feature = "std")] /// use std::io::Write; - /// #[cfg(feature = "no_std")] + /// #[cfg(not(feature = "std"))] /// use core2::io::Write; /// use libflate::zlib::Encoder; /// @@ -575,9 +563,6 @@ where /// /// # Examples /// ``` - /// #[cfg(not(feature = "no_std"))] - /// use std::io::Write; - /// #[cfg(feature = "no_std")] /// use core2::io::Write; /// use libflate::zlib::{Encoder, EncodeOptions}; /// @@ -616,9 +601,6 @@ where /// /// # Examples /// ``` - /// #[cfg(not(feature = "no_std"))] - /// use std::io::Write; - /// #[cfg(feature = "no_std")] /// use core2::io::Write; /// use libflate::zlib::Encoder; /// @@ -636,10 +618,7 @@ 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::Write; /// use libflate::finish::AutoFinishUnchecked; /// use libflate::zlib::Encoder; /// @@ -705,10 +684,8 @@ where mod tests { use super::*; use crate::finish::AutoFinish; - #[cfg(feature = "no_std")] + use alloc::{borrow::ToOwned, string::ToString, vec, vec::Vec}; 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(); @@ -925,7 +902,7 @@ mod tests { } #[test] - #[cfg(not(feature = "no_std"))] + #[cfg(feature = "std")] /// See: https://github.com/sile/libflate/issues/61 fn issue_61() { let data = default_encode(b"Hello World").unwrap();