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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
// Copyright 2017 Brian Langenberger
// Copyright 2024-2026 COOLJAPAN OU (Team Kitasan)
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Bit-level I/O for OxiMedia — a `std`-only fork of
//! [`bitstream-io`](https://crates.io/crates/bitstream-io) 4.9.0.
//!
//! `oximedia-bitstream` provides traits and structs for reading and writing
//! signed and unsigned integer values to streams that may not be aligned at
//! a whole byte. Both big-endian and little-endian streams are supported.
//!
//! The crate is used internally by `oximedia-codec` for entropy coding
//! (FLAC predictor coefficients, Vorbis header parsing, AV1 OBU parsing, etc.)
//! and by `oximedia-container` for MP4 box I/O.
//!
//! # Core traits
//!
//! | Trait | Purpose |
//! |-------|---------|
//! | [`BitRead`] | Read bits from a stream, big- or little-endian |
//! | [`BitWrite`] | Write bits to a stream, big- or little-endian |
//! | [`ByteRead`] | Read whole bytes from a byte source |
//! | [`ByteWrite`] | Write whole bytes to any destination |
//! | [`FromBitStream`] | Deserialise a struct from a bit reader |
//! | [`ToBitStream`] | Serialise a struct to a bit writer |
//!
//! # Concrete types
//!
//! - [`BitReader`] — wraps any `std::io::Read` and exposes bit-level reads
//! - [`BitWriter`] — wraps any `std::io::Write` and exposes bit-level writes
//! - [`ByteReader`] — wraps any `std::io::Read` for whole-byte reads
//! - [`ByteWriter`] — wraps any `std::io::Write` for whole-byte writes
//! - [`BitRecorder`] (feature `alloc`) — records bits written for later replay
//! - [`BitsWritten`] — counts bits written without a backing writer
//!
//! Huffman coding helpers live in the [`huffman`] module via the
//! [`FromBits`](huffman::FromBits) and [`ToBits`](huffman::ToBits) traits.
//!
//! # Quick start
//!
//! ```
//! use std::io::Cursor;
//! use oximedia_bitstream::{BigEndian, BitReader, BitRead};
//!
//! let data = [0b1011_0100u8, 0b1100_1010u8];
//! let mut r = BitReader::endian(Cursor::new(&data), BigEndian);
//!
//! // Constant-bit-count read — validated at compile time (requires Rust 1.79+)
//! let high: u8 = r.read::<4, _>().unwrap();
//! assert_eq!(high, 0b1011);
//!
//! // Variable-bit-count read
//! let low: u8 = r.read_var(4).unwrap();
//! assert_eq!(low, 0b0100);
//! ```
//!
//! # Endianness
//!
//! Pass [`BigEndian`] or [`LittleEndian`] as a zero-sized type parameter
//! (or value) to [`BitReader::endian`] / [`BitWriter::endian`]. The endianness
//! is a compile-time phantom; switching endianness mid-stream requires creating
//! a new reader/writer around the same underlying stream.
//!
//! # Feature flags
//!
//! | Flag | Default | Effect |
//! |------|---------|--------|
//! | `std` | yes | Enables `alloc` |
//! | `alloc` | via `std` | Enables [`BitRecorder`] |
//!
//! # Upstream attribution
//!
//! This crate is derived from
//! [`bitstream-io`](https://crates.io/crates/bitstream-io) 4.9.0 by
//! Brian Langenberger, licensed under Apache-2.0 / MIT.
//! The OxiMedia fork removes the `core2` / `no_std` compatibility shim
//! (OxiMedia targets `std` Rust only) and adapts the crate to the
//! OxiMedia workspace conventions.
//! # Traits and helpers for bitstream handling functionality
//!
//! Bitstream readers are for reading signed and unsigned integer
//! values from a stream whose sizes may not be whole bytes.
//! Bitstream writers are for writing signed and unsigned integer
//! values to a stream, also potentially un-aligned at a whole byte.
//!
//! Both big-endian and little-endian streams are supported.
//!
//! The only requirement for wrapped reader streams is that they must
//! implement the [`io::Read`] trait, and the only requirement
//! for writer streams is that they must implement the [`io::Write`] trait.
//!
//! In addition, reader streams do not consume any more bytes
//! from the underlying reader than necessary, buffering only a
//! single partial byte as needed.
//! Writer streams also write out all whole bytes as they are accumulated.
//!
//! Readers and writers are also designed to work with integer
//! types of any possible size.
//! Many of Rust's built-in integer types are supported by default.
//! # Minimum Compiler Version
//!
//! Beginning with version 2.4, the minimum compiler version has been
//! updated to Rust 1.79.
//!
//! The issue is that reading an excessive number of
//! bits to a type which is too small to hold them,
//! or writing an excessive number of bits from too small of a type,
//! are always errors:
//! ```
//! use std::io::{Read, Cursor};
//! use oximedia_bitstream::{BigEndian, BitReader, BitRead};
//! let data = [0; 10];
//! let mut r = BitReader::endian(Cursor::new(&data), BigEndian);
//! let x: Result<u32, _> = r.read_var(64); // reading 64 bits to u32 always fails at runtime
//! assert!(x.is_err());
//! ```
//! but those errors will not be caught until the program runs,
//! which is less than ideal for the common case in which
//! the number of bits is already known at compile-time.
//!
//! But starting with Rust 1.79, we can now have read and write methods
//! which take a constant number of bits and can validate the number of bits
//! are small enough for the type being read/written at compile-time:
//! ```rust,compile_fail
//! use std::io::{Read, Cursor};
//! use oximedia_bitstream::{BigEndian, BitReader, BitRead};
//! let data = [0; 10];
//! let mut r = BitReader::endian(Cursor::new(&data), BigEndian);
//! let x: Result<u32, _> = r.read::<64, _>(); // doesn't compile at all
//! ```
//! Since catching potential bugs at compile-time is preferable
//! to encountering errors at runtime, this will hopefully be
//! an improvement in the long run.
//! # Changes From 3.X.X
//!
//! Version 4.0.0 features significant optimizations to the [`BitRecorder`]
//! and deprecates the [`BitCounter`] in favor of [`BitsWritten`],
//! which no longer requires specifying an endianness.
//!
//! In addition, the [`BitRead::read_bytes`] and [`BitWrite::write_bytes`]
//! methods are significantly optimized in the case of non-aligned
//! reads and writes.
//!
//! Finally, the [`Endianness`] traits have been sealed so as not
//! to be implemented by other packages. Given that other endianness
//! types are extremely rare in file formats and end users should not
//! have to implement this trait themselves, this should not be a
//! concern.
//!
//! # Changes From 2.X.X
//!
//! Version 3.0.0 has made many breaking changes to the [`BitRead`] and
//! [`BitWrite`] traits.
//!
//! The [`BitRead::read`] method takes a constant number of bits,
//! and the [`BitRead::read_var`] method takes a variable number of bits
//! (reversing the older [`BitRead2::read_in`] and [`BitRead2::read`]
//! calling methods to emphasize using the constant-based one,
//! which can do more validation at compile-time).
//! A new [`BitRead2`] trait uses the older calling convention
//! for compatibility with existing code and is available
//! for anything implementing [`BitRead`].
//!
//! In addition, the main reading methods return primitive types which
//! implement a new [`Integer`] trait,
//! which delegates to [`BitRead::read_unsigned`]
//! or [`BitRead::read_signed`] depending on whether the output
//! is an unsigned or signed type.
//!
//! [`BitWrite::write`] and [`BitWrite::write_var`] work
//! similarly to the reader's `read` methods, taking anything
//! that implements [`Integer`] and writing an unsigned or
//! signed value to [`BitWrite::write_unsigned`] or
//! [`BitWrite::write_signed`] as appropriate.
//!
//! And as with reading, a [`BitWrite2`] trait is offered
//! for compatibility.
//!
//! In addition, the Huffman code handling has been rewritten
//! to use a small amount of macro magic to write
//! code to read and write symbols at compile-time.
//! This is significantly faster than the older version
//! and can no longer fail to compile at runtime.
//!
//! Lastly, there's a new [`BitCount`] struct which wraps a humble
//! `u32` but encodes the maximum possible number of bits
//! at the type level.
//! This is intended for file formats which encode the number
//! of bits to be read in the format itself.
//! For example, FLAC's predictor coefficient precision
//! is a 4 bit value which indicates how large each predictor
//! coefficient is in bits
//! (each coefficient might be an `i32` type).
//! By keeping track of the maximum value at compile time
//! (4 bits' worth, in this case), we can eliminate
//! any need to check that coefficients aren't too large
//! for an `i32` at runtime.
//! This is accomplished by using [`BitRead::read_count`] to
//! read a [`BitCount`] and then reading final values with
//! that number of bits using [`BitRead::read_counted`].
//! # Migrating From Pre 1.0.0
//!
//! There are now [`BitRead`] and [`BitWrite`] traits for bitstream
//! reading and writing (analogous to the standard library's
//! `Read` and `Write` traits) which you will also need to import.
//! The upside to this approach is that library consumers
//! can now make functions and methods generic over any sort
//! of bit reader or bit writer, regardless of the underlying
//! stream byte source or endianness.
// `PhantomData` is re-used through `super::PhantomData` by the `read` and
// `write` submodules; keep the alias reachable from the crate root.
pub use PhantomData;
use io;
pub use ;
pub use BitRecorder;
pub use ;
pub use BitCounter;
// Split-out modules — the bitstream runtime surface is carved into
// focused files so that no single source exceeds the COOLJAPAN 2 000-line
// refactor guideline while preserving the original public API.
pub use ;
pub use ;
pub use ;
pub use Endianness;
pub use ;
pub use ;