Zstd compression in pure OCaml
1(** Bitstream reader for Zstandard decompression.
2
3 This module wraps the Bitstream library, translating exceptions
4 to Zstd_error for consistent error handling. *)
5
6(** Helper to wrap Bitstream operations and translate exceptions *)
7let[@inline] wrap_truncated f =
8 try f ()
9 with Bitstream.End_of_stream ->
10 raise (Constants.Zstd_error Constants.Truncated_input)
11
12let[@inline] wrap_all f =
13 try f ()
14 with
15 | Bitstream.End_of_stream ->
16 raise (Constants.Zstd_error Constants.Truncated_input)
17 | Bitstream.Invalid_state _ ->
18 raise (Constants.Zstd_error Constants.Corruption)
19 | Bitstream.Corrupted_stream _ ->
20 raise (Constants.Zstd_error Constants.Corruption)
21
22(** Forward bitstream reader - reads from start to end *)
23module Forward = struct
24 type t = Bitstream.Forward_reader.t
25
26 let create src ~pos ~len =
27 Bitstream.Forward_reader.create src ~pos ~len
28
29 let of_bytes src =
30 Bitstream.Forward_reader.of_bytes src
31
32 let[@inline] remaining t =
33 Bitstream.Forward_reader.remaining t
34
35 let[@inline] is_byte_aligned t =
36 Bitstream.Forward_reader.is_byte_aligned t
37
38 let[@inline] read_bits t n =
39 wrap_truncated (fun () -> Bitstream.Forward_reader.read_bits t n)
40
41 let[@inline] read_byte t =
42 wrap_all (fun () -> Bitstream.Forward_reader.read_byte t)
43
44 let rewind_bits t n =
45 wrap_truncated (fun () -> Bitstream.Forward_reader.rewind_bits t n)
46
47 let align t =
48 Bitstream.Forward_reader.align t
49
50 let byte_position t =
51 wrap_all (fun () -> Bitstream.Forward_reader.byte_position t)
52
53 let get_bytes t n =
54 wrap_all (fun () -> Bitstream.Forward_reader.get_bytes t n)
55
56 let advance t n =
57 wrap_all (fun () -> Bitstream.Forward_reader.advance t n)
58
59 let sub t n =
60 wrap_all (fun () -> Bitstream.Forward_reader.sub t n)
61
62 let remaining_bytes t =
63 wrap_all (fun () -> Bitstream.Forward_reader.remaining_bytes t)
64end
65
66(** Backward bitstream reader - reads from end to start.
67 Used for FSE and Huffman coded streams. *)
68module Backward = struct
69 type t = Bitstream.Backward_reader.t
70
71 let create src ~pos ~len =
72 wrap_all (fun () -> Bitstream.Backward_reader.of_bytes src ~pos ~len)
73
74 let of_bytes src ~pos ~len =
75 create src ~pos ~len
76
77 let[@inline] remaining t =
78 Bitstream.Backward_reader.remaining t
79
80 let[@inline] read_bits t n =
81 Bitstream.Backward_reader.read_bits t n
82
83 let[@inline] is_empty t =
84 Bitstream.Backward_reader.is_empty t
85end
86
87(** Read little-endian integers from bytes *)
88let[@inline] get_u16_le src pos =
89 Bytes.get_uint16_le src pos