Skip to main content

lz4rip_core/
lib.rs

1//! Shared types and constants for the lz4rip encode/decode crates.
2
3#![forbid(unsafe_code)]
4#![deny(warnings)]
5#![deny(missing_docs)]
6#![cfg_attr(not(feature = "std"), no_std)]
7#![cfg_attr(feature = "nightly", feature(optimize_attribute))]
8
9use core::{error::Error, fmt};
10
11mod sink;
12pub use sink::{Sink, SliceSink};
13
14mod fastcpy;
15pub use fastcpy::slice_copy;
16
17// --- LZ4 block format constants ---
18
19/// Window size for LZ4 compression (64 KB).
20pub const WINDOW_SIZE: usize = 64 * 1024;
21
22/// Last match must start at least 12 bytes before end of block.
23pub const MFLIMIT: usize = 12;
24
25/// Last 5 bytes are always literals.
26pub const LAST_LITERALS: usize = 5;
27
28/// `LAST_LITERALS` + 1: extra byte for register-width reads near end.
29pub const END_OFFSET: usize = LAST_LITERALS + 1;
30
31/// Minimum compressible block length: MFLIMIT + 1 for the token.
32pub const LZ4_MIN_LENGTH: usize = MFLIMIT + 1;
33
34/// Maximum match distance (65535).
35pub const MAX_DISTANCE: usize = (1 << 16) - 1;
36
37/// Minimum match length.
38pub const MINMATCH: usize = 4;
39
40/// An error representing invalid compressed data.
41#[derive(Debug, Clone, PartialEq, Eq)]
42#[non_exhaustive]
43pub enum DecompressError {
44    /// The provided output is too small
45    OutputTooSmall {
46        /// Minimum expected output size
47        expected: usize,
48        /// Actual size of output
49        actual: usize,
50    },
51    /// Literal is out of bounds of the input
52    LiteralOutOfBounds,
53    /// Expected another byte, but none found.
54    ExpectedAnotherByte,
55    /// Match offset is 0
56    OffsetZero,
57    /// Deduplication offset out of bounds (not in buffer).
58    OffsetOutOfBounds,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq)]
62#[non_exhaustive]
63/// Errors that can happen during compression.
64pub enum CompressError {
65    /// The provided output is too small.
66    OutputTooSmall,
67}
68
69impl fmt::Display for DecompressError {
70    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71        match self {
72            DecompressError::OutputTooSmall { expected, actual } => {
73                write!(
74                    f,
75                    "provided output is too small for the decompressed data, actual {actual}, expected \
76                     {expected}"
77                )
78            }
79            DecompressError::LiteralOutOfBounds => {
80                f.write_str("literal is out of bounds of the input")
81            }
82            DecompressError::ExpectedAnotherByte => {
83                f.write_str("expected another byte, found none")
84            }
85            DecompressError::OffsetZero => f.write_str("0 is not a valid match offset"),
86            DecompressError::OffsetOutOfBounds => {
87                f.write_str("the offset to copy is not contained in the decompressed buffer")
88            }
89        }
90    }
91}
92
93impl fmt::Display for CompressError {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        match self {
96            CompressError::OutputTooSmall => f.write_str(
97                "output is too small for the compressed data, use get_maximum_output_size to \
98                 reserve enough space",
99            ),
100        }
101    }
102}
103
104impl Error for DecompressError {}
105
106impl Error for CompressError {}