1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! LZHAM (Lossless ZIP Huffman Arithmetic Modeling) — **header parser only**.
//!
//! LZHAM is Rich Geldreich's LZMA-class codec, published at
//! <https://github.com/richgel999/lzham_codec> under the MIT licence. The
//! raw codec (`lzham_lib_decompress`) consumes an arithmetic-coded
//! bitstream produced by a multi-state Markov-chain model with dynamic
//! Huffman / polar / quasi-arithmetic sub-tables, none of which is
//! documented outside the reference C++ source. Dictionary size and
//! table-update-rate are caller-supplied parameters, not bytes in the
//! stream.
//!
//! ## What this build supports
//!
//! - The **`LZH0` container framing** emitted by `lzhamtest` (Rich's
//! reference compress/decompress CLI). The decoder validates the magic,
//! reads the `dict_size_log2` byte, reads the little-endian `u64`
//! uncompressed size, and then — because the inner LZHAM bitstream is
//! undocumented and untestable from this side — returns
//! [`Error::Unsupported`] for the payload.
//! - The encoder permanently returns [`Error::Unsupported`].
//!
//! Implementing the inner codec faithfully would require porting ~3000
//! lines of C++ (the symbol codec, the LZ state machine with 24 transition
//! states, the table-update scheduler) into safe Rust and validating
//! against fixtures generated by the reference toolchain. That scope is
//! larger than a single batch's worth of work, so we ship the framing
//! layer cleanly and document the gap.
//!
//! ## `LZH0` framing
//!
//! | Offset | Size | Field |
//! |--------|------|--------------------------------------------------|
//! | 0 | 4 | Magic: `b"LZH0"` |
//! | 4 | 1 | `dict_size_log2` (`15..=29` per `lzham.h`) |
//! | 5 | 8 | Uncompressed size, little-endian `u64` |
//! | 13 | … | LZHAM compressed payload (this build: Unsupported) |
//!
//! No checksum is stored in the file; the reference CLI recomputes
//! Adler-32 on the decompressed bytes and prints it for the user. This
//! parser does not enforce a checksum it cannot see.
//!
//! ## References
//!
//! - Reference codec: <https://github.com/richgel999/lzham_codec>
//! - Public API header: <https://github.com/richgel999/lzham_codec/blob/master/include/lzham.h>
//! - `lzhamtest` CLI (source of the `LZH0` framing):
//! <https://github.com/richgel999/lzham_codec/blob/master/lzhamtest/lzhamtest.cpp>
use crateError;
use crate;
pub use Decoder;
/// Zero-sized marker type implementing [`Algorithm`] for LZHAM.
;
// ─── shared format constants ─────────────────────────────────────────────
/// `LZH0` container magic emitted by `lzhamtest`.
pub const MAGIC: = *b"LZH0";
/// Minimum and maximum `dict_size_log2` values accepted by the LZHAM
/// reference codec. `LZHAM_MIN_DICT_SIZE_LOG2` = 15 (32 KiB),
/// `LZHAM_MAX_DICT_SIZE_LOG2_X64` = 29 (512 MiB); these come from
/// `include/lzham.h`. We accept the full range on the parse side.
pub const MIN_DICT_LOG2: u8 = 15;
pub const MAX_DICT_LOG2: u8 = 29;
/// Total fixed-prefix length of the `LZH0` container header.
pub const HEADER_LEN: usize = 4 + 1 + 8;
// ─── encoder ─────────────────────────────────────────────────────────────
/// Encoder stub. LZHAM encoding is out of scope for this build; every
/// method here returns [`Error::Unsupported`].
;