lzss/lib.rs
1#![cfg_attr(not(any(test, feature = "std")), no_std)]
2#![cfg_attr(feature = "safe", forbid(unsafe_code))]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![warn(missing_docs)]
5#![warn(clippy::pedantic)]
6#![allow(clippy::cast_possible_truncation)]
7#![allow(clippy::cast_lossless)]
8#![allow(clippy::cast_sign_loss)]
9#![allow(clippy::inline_always)]
10#![allow(clippy::match_same_arms)]
11#![allow(clippy::missing_errors_doc)]
12#![allow(clippy::missing_panics_doc)]
13#![allow(clippy::module_name_repetitions)]
14#![allow(clippy::manual_assert)]
15
16//! # Lempel–Ziv–Storer–Szymanski de-/compression
17//!
18//! `lzss` is a lossless data compression algorithm in pure Rust.
19//! This crate is built for embedded systems:
20//!
21//! * Small code size
22//! * Uses little RAM and CPU
23//! * `no_std` feature
24//! * All parameters can be compile-time only
25//!
26//! # Generic vs. dynamic
27//!
28//! This crate comes in two flavors: generic ([`Lzss`](crate::Lzss)) and dynamic ([`LzssDyn`](crate::LzssDyn)).
29//!
30//! The dynamic one has one compress function and all parameters are passed to
31//! it at runtime, making it very adaptive.
32//!
33//! The generic one has compile-time parameters will produce a function for each
34//! different sets of parameters. This function will be more optimized by the
35//! compiler than the dynamic one, the downside is that multiple functions are
36//! generated when multiple parameter sets are used.
37//!
38//! (The same applies for decompress and other functions, only used function will
39//! be in the generated program.)
40//!
41//! # Lack of a header
42//!
43//! This algorithm has by design no header at all. Please be aware that it is not
44//! possible to check if the contents is correct, or even the length matches.
45//! It is recommended to add a header based on the requirements.
46//!
47//! # Origin
48//! This code is based on the [LZSS encoder-decoder by Haruhiko Okumura, public domain](https://oku.edu.mie-u.ac.jp/~okumura/compression/lzss.c).
49//!
50//! In order to create an encoder-decoder which is compatible to the program above
51//! the following is required: `C = 0x20` in this library and `P = (1+EI+EJ) / 9` in Okumuras program.
52//!
53//! # Features
54//! * `alloc` - Allows de-/compression with buffer on the heap and the [`VecWriter`](crate::VecWriter).
55//! * `safe` - Only use safe code (see Safety below).
56//! * `std` - Enables `alloc` and additional [`IOSimpleReader`](crate::IOSimpleReader), [`IOSimpleWriter`](crate::IOSimpleWriter),
57//! and the [`Error`](::std::error::Error) instance for [`LzssError`](crate::LzssError) and [`LzssDynError`](crate::LzssDynError).
58//!
59//! `std` and `safe` are enabled by default.
60//!
61//! ## Usage
62//! With defaults (`std` and `safe`):
63//! ```toml
64//! [dependencies]
65//! lzss = "0.9"
66//! ```
67//!
68//! With `no_std` (and without `safe`):
69//! ```toml
70//! [dependencies]
71//! lzss = { version = "0.9", default-features = false }
72//! ```
73//!
74//! # Example
75//! ```rust
76//! # use lzss::{Lzss, SliceReader, SliceWriter};
77//! type MyLzss = Lzss<10, 4, 0x20, { 1 << 10 }, { 2 << 10 }>;
78//! let input = b"Example Data";
79//! let mut output = [0; 30];
80//! let result = MyLzss::compress(
81//! SliceReader::new(input),
82//! SliceWriter::new(&mut output),
83//! );
84//! assert_eq!(result, Ok(14)); // there was no overflow and the output is 14 bytes long
85//! ```
86//!
87//! # Safety
88//!
89//! With the `safe` feature the code is not using any unsafe code (`forbid(unsafe_code)`), but at
90//! the cost of performance and size - though on modern systems that is not to mention.
91//!
92//! But on smaller systems (like microcontrollers, where `no_std` is needed) it may be noticeable.
93//! Which is the reason wht it can be switched on/off.
94
95#[cfg(feature = "alloc")]
96#[macro_use]
97extern crate alloc;
98
99pub use crate::dynamic::{LzssDyn, LzssDynError};
100pub use crate::error::LzssError;
101pub use crate::generic::Lzss;
102#[cfg(any(test, feature = "std"))]
103pub use crate::io_simple::{IOSimpleReader, IOSimpleWriter};
104pub use crate::read_write::{Read, Write};
105pub use crate::slice::{SliceReader, SliceWriteError, SliceWriter, SliceWriterExact};
106#[cfg(any(test, feature = "alloc"))]
107pub use crate::vec::VecWriter;
108pub use crate::void::{
109 ResultLzssErrorVoidExt, ResultLzssErrorVoidReadExt, ResultLzssErrorVoidWriteExt,
110};
111
112mod bits;
113mod dynamic;
114mod error;
115mod generic;
116#[cfg(any(test, feature = "std"))]
117mod io_simple;
118mod macros;
119mod read_write;
120#[cfg_attr(feature = "safe", path = "slice_safe.rs")]
121mod slice;
122#[cfg(any(test, feature = "alloc"))]
123mod vec;
124mod void;