Skip to content

Commit

Permalink
Merge pull request #39 from antangelo/no_std
Browse files Browse the repository at this point in the history
Add support for no_std
  • Loading branch information
KillingSpark authored Mar 24, 2023
2 parents a4d5d48 + c9e8623 commit 3449d0a
Show file tree
Hide file tree
Showing 25 changed files with 536 additions and 173 deletions.
71 changes: 71 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,77 @@ jobs:
command: clippy
args: -- -D warnings

check-no-std:
name: Check (no_std)
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install nightly toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true

- name: Run cargo check without std feature
uses: actions-rs/cargo@v1
with:
command: check
toolchain: nightly
args: --no-default-features

test-no-std:
name: Test Suite (no_std)
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install nightly toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true

- name: Run cargo test without std feature
uses: actions-rs/cargo@v1
with:
command: test
toolchain: nightly
args: --no-default-features

lints-no-std:
name: Lints
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install nightly toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true
components: rustfmt, clippy

- name: Run cargo fmt
uses: actions-rs/cargo@v1
with:
command: fmt
toolchain: nightly
args: --all -- --check

- name: Run cargo clippy
uses: actions-rs/cargo@v1
with:
command: clippy
toolchain: nightly
args: --no-default-features -- -D warnings

# fails CI because criterion needs two versions of autocfg
#cargo-deny:
# name: Cargo Deny
Expand Down
16 changes: 14 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,26 @@ exclude = ["decodecorpus_files/*", "dict_tests/*", "fuzz_decodecorpus/*"]
readme = "Readme.md"

[dependencies]
byteorder = "1.4"
byteorder = { version = "1.4", default-features = false }
twox-hash = { version = "1.6", default-features = false }
thiserror = "1"
thiserror = { package = "thiserror-core", version = "1.0.38", default-features = false }

[dev-dependencies]
criterion = "0.3"
rand = "0.8.5"

[features]
default = ["std"]
std = ["thiserror/std"]

[[bench]]
name = "reversedbitreader_bench"
harness = false

[[bin]]
name = "zstd"
required-features = ["std"]

[[bin]]
name = "zstd_stream"
required-features = ["std"]
4 changes: 2 additions & 2 deletions src/blocks/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ pub enum BlockType {
Reserved,
}

impl std::fmt::Display for BlockType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
impl core::fmt::Display for BlockType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
match self {
BlockType::Compressed => write!(f, "Compressed"),
BlockType::Raw => write!(f, "Raw"),
Expand Down
4 changes: 2 additions & 2 deletions src/blocks/literals_section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ pub enum LiteralsSectionParseError {
NotEnoughBytes { have: usize, need: u8 },
}

impl std::fmt::Display for LiteralsSectionType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
impl core::fmt::Display for LiteralsSectionType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
match self {
LiteralsSectionType::Compressed => write!(f, "Compressed"),
LiteralsSectionType::Raw => write!(f, "Raw"),
Expand Down
4 changes: 2 additions & 2 deletions src/blocks/sequence_section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ pub struct Sequence {
pub of: u32,
}

impl std::fmt::Display for Sequence {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
impl core::fmt::Display for Sequence {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "LL: {}, ML: {}, OF: {}", self.ll, self.ml, self.of)
}
}
Expand Down
42 changes: 16 additions & 26 deletions src/decoding/block_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::blocks::literals_section::LiteralsSectionParseError;
use crate::blocks::sequence_section::SequencesHeaderParseError;
use crate::decoding::scratch::DecoderScratch;
use crate::decoding::sequence_execution::execute_sequences;
use std::io::{self, Read};
use crate::io::{self, Read};

pub struct BlockDecoder {
header_buffer: [u8; 3],
Expand Down Expand Up @@ -203,12 +203,12 @@ impl BlockDecoder {
let mut section = LiteralsSection::new();
let bytes_in_literals_header = section.parse_from_header(raw)?;
let raw = &raw[bytes_in_literals_header as usize..];
if crate::VERBOSE {
println!(
"Found {} literalssection with regenerated size: {}, and compressed size: {:?}",
section.ls_type, section.regenerated_size, section.compressed_size
);
}
vprintln!(
"Found {} literalssection with regenerated size: {}, and compressed size: {:?}",
section.ls_type,
section.regenerated_size,
section.compressed_size
);

let upper_limit_for_literals = match section.compressed_size {
Some(x) => x as usize,
Expand All @@ -227,9 +227,7 @@ impl BlockDecoder {
}

let raw_literals = &raw[..upper_limit_for_literals];
if crate::VERBOSE {
println!("Slice for literals: {}", raw_literals.len());
}
vprintln!("Slice for literals: {}", raw_literals.len());

workspace.literals_buffer.clear(); //all literals of the previous block must have been used in the sequence execution anyways. just be defensive here
let bytes_used_in_literals_section = decode_literals(
Expand All @@ -247,20 +245,16 @@ impl BlockDecoder {
assert!(bytes_used_in_literals_section == upper_limit_for_literals as u32);

let raw = &raw[upper_limit_for_literals..];
if crate::VERBOSE {
println!("Slice for sequences with headers: {}", raw.len());
}
vprintln!("Slice for sequences with headers: {}", raw.len());

let mut seq_section = SequencesHeader::new();
let bytes_in_sequence_header = seq_section.parse_from_header(raw)?;
let raw = &raw[bytes_in_sequence_header as usize..];
if crate::VERBOSE {
println!(
"Found sequencessection with sequences: {} and size: {}",
seq_section.num_sequences,
raw.len()
);
}
vprintln!(
"Found sequencessection with sequences: {} and size: {}",
seq_section.num_sequences,
raw.len()
);

assert!(
u32::from(bytes_in_literals_header)
Expand All @@ -269,9 +263,7 @@ impl BlockDecoder {
+ raw.len() as u32
== header.content_size
);
if crate::VERBOSE {
println!("Slice for sequences: {}", raw.len());
}
vprintln!("Slice for sequences: {}", raw.len());

if seq_section.num_sequences != 0 {
decode_sequences(
Expand All @@ -280,9 +272,7 @@ impl BlockDecoder {
&mut workspace.fse,
&mut workspace.sequences,
)?;
if crate::VERBOSE {
println!("Executing sequences");
}
vprintln!("Executing sequences");
execute_sequences(workspace)?;
} else {
workspace.buffer.push(&workspace.literals_buffer);
Expand Down
41 changes: 23 additions & 18 deletions src/decoding/decodebuffer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::hash::Hasher;
use std::io;
use crate::io::{Error, Read, Write};
use alloc::vec::Vec;
use core::hash::Hasher;

use twox_hash::XxHash64;

Expand All @@ -23,8 +24,8 @@ pub enum DecodebufferError {
OffsetTooBig { offset: usize, buf_len: usize },
}

impl io::Read for Decodebuffer {
fn read(&mut self, target: &mut [u8]) -> io::Result<usize> {
impl Read for Decodebuffer {
fn read(&mut self, target: &mut [u8]) -> Result<usize, Error> {
let max_amount = self.can_drain_to_window_size().unwrap_or(0);
let amount = max_amount.min(target.len());

Expand Down Expand Up @@ -176,7 +177,7 @@ impl Decodebuffer {
}
}

pub fn drain_to_window_size_writer(&mut self, mut sink: impl io::Write) -> io::Result<usize> {
pub fn drain_to_window_size_writer(&mut self, mut sink: impl Write) -> Result<usize, Error> {
match self.can_drain_to_window_size() {
None => Ok(0),
Some(can_drain) => {
Expand All @@ -199,14 +200,14 @@ impl Decodebuffer {
vec
}

pub fn drain_to_writer(&mut self, mut sink: impl io::Write) -> io::Result<usize> {
pub fn drain_to_writer(&mut self, mut sink: impl Write) -> Result<usize, Error> {
let len = self.buffer.len();
self.drain_to(len, |buf| write_all_bytes(&mut sink, buf))?;

Ok(len)
}

pub fn read_all(&mut self, target: &mut [u8]) -> io::Result<usize> {
pub fn read_all(&mut self, target: &mut [u8]) -> Result<usize, Error> {
let amount = self.buffer.len().min(target.len());

let mut written = 0;
Expand All @@ -224,8 +225,8 @@ impl Decodebuffer {
fn drain_to(
&mut self,
amount: usize,
mut write_bytes: impl FnMut(&[u8]) -> (usize, io::Result<()>),
) -> io::Result<()> {
mut write_bytes: impl FnMut(&[u8]) -> (usize, Result<(), Error>),
) -> Result<(), Error> {
if amount == 0 {
return Ok(());
}
Expand Down Expand Up @@ -280,7 +281,7 @@ impl Decodebuffer {
}

/// Like Write::write_all but returns partial write length even on error
fn write_all_bytes(mut sink: impl io::Write, buf: &[u8]) -> (usize, io::Result<()>) {
fn write_all_bytes(mut sink: impl Write, buf: &[u8]) -> (usize, Result<(), Error>) {
let mut written = 0;
while written < buf.len() {
match sink.write(&buf[written..]) {
Expand All @@ -294,7 +295,11 @@ fn write_all_bytes(mut sink: impl io::Write, buf: &[u8]) -> (usize, io::Result<(
#[cfg(test)]
mod tests {
use super::Decodebuffer;
use std::io::Write;
use crate::io::{Error, ErrorKind, Write};

extern crate std;
use alloc::vec;
use alloc::vec::Vec;

#[test]
fn short_writer() {
Expand All @@ -304,7 +309,7 @@ mod tests {
}

impl Write for ShortWriter {
fn write(&mut self, buf: &[u8]) -> std::result::Result<usize, std::io::Error> {
fn write(&mut self, buf: &[u8]) -> std::result::Result<usize, Error> {
if buf.len() > self.write_len {
self.buf.extend_from_slice(&buf[..self.write_len]);
Ok(self.write_len)
Expand All @@ -314,7 +319,7 @@ mod tests {
}
}

fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
fn flush(&mut self) -> std::result::Result<(), Error> {
Ok(())
}
}
Expand Down Expand Up @@ -352,18 +357,18 @@ mod tests {
}

impl Write for WouldblockWriter {
fn write(&mut self, buf: &[u8]) -> std::result::Result<usize, std::io::Error> {
fn write(&mut self, buf: &[u8]) -> std::result::Result<usize, Error> {
if self.last_blocked < self.block_every {
self.buf.extend_from_slice(buf);
self.last_blocked += 1;
Ok(buf.len())
} else {
self.last_blocked = 0;
Err(std::io::Error::from(std::io::ErrorKind::WouldBlock))
Err(Error::from(ErrorKind::WouldBlock))
}
}

fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
fn flush(&mut self) -> std::result::Result<(), Error> {
Ok(())
}
}
Expand All @@ -390,7 +395,7 @@ mod tests {
}
}
Err(e) => {
if e.kind() == std::io::ErrorKind::WouldBlock {
if e.kind() == ErrorKind::WouldBlock {
continue;
} else {
panic!("Unexpected error {:?}", e);
Expand All @@ -410,7 +415,7 @@ mod tests {
}
}
Err(e) => {
if e.kind() == std::io::ErrorKind::WouldBlock {
if e.kind() == ErrorKind::WouldBlock {
continue;
} else {
panic!("Unexpected error {:?}", e);
Expand Down
3 changes: 2 additions & 1 deletion src/decoding/dictionary.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::convert::TryInto;
use alloc::vec::Vec;
use core::convert::TryInto;

use crate::decoding::scratch::FSEScratch;
use crate::decoding::scratch::HuffmanScratch;
Expand Down
5 changes: 2 additions & 3 deletions src/decoding/literals_section_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::super::blocks::literals_section::{LiteralsSection, LiteralsSectionTyp
use super::bit_reader_reverse::{BitReaderReversed, GetBitsError};
use super::scratch::HuffmanScratch;
use crate::huff0::{HuffmanDecoder, HuffmanDecoderError, HuffmanTableError};
use alloc::vec::Vec;

#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
Expand Down Expand Up @@ -75,9 +76,7 @@ fn decompress_literals(
LiteralsSectionType::Compressed => {
//read Huffman tree description
bytes_read += scratch.table.build_decoder(source)?;
if crate::VERBOSE {
println!("Built huffman table using {} bytes", bytes_read);
}
vprintln!("Built huffman table using {} bytes", bytes_read);
}
LiteralsSectionType::Treeless => {
if scratch.table.max_num_bits == 0 {
Expand Down
Loading

0 comments on commit 3449d0a

Please sign in to comment.