oximedia_bitstream/write/bit_write.rs
1// Copyright 2017 Brian Langenberger
2// Copyright 2024-2026 COOLJAPAN OU (Team Kitasan)
3//
4// Licensed under the Apache License, Version 2.0 or the MIT license,
5// at your option. See the LICENSE-APACHE / LICENSE-MIT files for details.
6
7//! The core `BitWrite` trait and its blanket impls.
8
9use std::io;
10
11use super::{
12 BitCount, Checkable, Endianness, Integer, Numeric, Primitive, SignedBitCount, SignedInteger,
13 ToBitStream, ToBitStreamUsing, ToBitStreamWith, UnsignedInteger, VBRInteger,
14};
15
16/// A trait for anything that can write a variable number of
17/// potentially un-aligned values to an output stream
18pub trait BitWrite {
19 /// Writes a single bit to the stream.
20 /// `true` indicates 1, `false` indicates 0
21 ///
22 /// # Errors
23 ///
24 /// Passes along any I/O error from the underlying stream.
25 ///
26 /// # Examples
27 /// ```
28 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
29 ///
30 /// let mut w = BitWriter::endian(vec![], BigEndian);
31 /// assert!(w.write_bit(true).is_ok());
32 /// assert!(w.write_bit(false).is_ok());
33 /// assert!(w.write_bit(false).is_ok());
34 /// assert!(w.write_bit(false).is_ok());
35 /// assert!(w.write_bit(true).is_ok());
36 /// assert!(w.write_bit(true).is_ok());
37 /// assert!(w.write_bit(true).is_ok());
38 /// assert!(w.write_bit(false).is_ok());
39 /// assert_eq!(w.into_writer(), &[0b1000_1110]);
40 /// ```
41 ///
42 /// ```
43 /// use oximedia_bitstream::{BitWriter, BitWrite, LittleEndian};
44 ///
45 /// let mut w = BitWriter::endian(vec![], LittleEndian);
46 /// assert!(w.write_bit(false).is_ok());
47 /// assert!(w.write_bit(true).is_ok());
48 /// assert!(w.write_bit(true).is_ok());
49 /// assert!(w.write_bit(true).is_ok());
50 /// assert!(w.write_bit(false).is_ok());
51 /// assert!(w.write_bit(false).is_ok());
52 /// assert!(w.write_bit(false).is_ok());
53 /// assert!(w.write_bit(true).is_ok());
54 /// assert_eq!(w.into_writer(), &[0b1000_1110]);
55 /// ```
56 #[inline]
57 fn write_bit(&mut self, bit: bool) -> io::Result<()> {
58 self.write_unsigned::<1, u8>(u8::from(bit))
59 }
60
61 /// Writes a signed or unsigned value to the stream using the given
62 /// const number of bits.
63 ///
64 /// # Errors
65 ///
66 /// Passes along any I/O error from the underlying stream.
67 /// Returns an error if the value is too large
68 /// to fit the given number of bits.
69 /// A compile-time error occurs if the given number of bits
70 /// is larger than the output type.
71 ///
72 /// # Examples
73 /// ```
74 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
75 ///
76 /// let mut w = BitWriter::endian(vec![], BigEndian);
77 /// // writing unsigned value is ok
78 /// assert!(w.write::<4, u8>(1).is_ok());
79 /// // writing signed value is ok
80 /// assert!(w.write::<4, i8>(-1).is_ok());
81 /// // writing an array of bits is ok too
82 /// assert!(w.write::<1, [bool; 4]>([true, false, true, true]).is_ok());
83 /// // writing an array of any Integer type is ok
84 /// assert!(w.write::<2, [u8; 2]>([0b11, 0b00]).is_ok());
85 /// // trying to write a value larger than 4 bits in 4 bits is an error
86 /// assert!(w.write::<4, u8>(u8::MAX).is_err());
87 ///
88 /// assert_eq!(w.into_writer(), &[0b0001_1111, 0b1011_11_00]);
89 /// ```
90 ///
91 /// ```rust,compile_fail
92 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
93 ///
94 /// let mut w = BitWriter::endian(vec![], BigEndian);
95 /// // trying to write 9 bits from a u8 is a compile-time error
96 /// w.write::<9, u8>(1);
97 /// ```
98 #[inline]
99 fn write<const BITS: u32, I>(&mut self, value: I) -> io::Result<()>
100 where
101 I: Integer,
102 {
103 Integer::write::<BITS, Self>(value, self)
104 }
105
106 /// Writes a signed or unsigned value to the stream using the given
107 /// number of bits.
108 ///
109 /// # Errors
110 ///
111 /// Passes along any I/O error from the underlying stream.
112 /// Returns an error if the input type is too small
113 /// to hold the given number of bits.
114 /// Returns an error if the value is too large
115 /// to fit the given number of bits.
116 ///
117 /// # Examples
118 /// ```
119 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
120 ///
121 /// let mut w = BitWriter::endian(vec![], BigEndian);
122 /// // writing unsigned value is ok
123 /// assert!(w.write_var::<u8>(4, 1).is_ok());
124 /// // writing signed value is also ok
125 /// assert!(w.write_var::<i8>(4, -1).is_ok());
126 /// assert_eq!(w.into_writer(), &[0b0001_1111]);
127 /// ```
128 ///
129 /// ```
130 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
131 ///
132 /// let mut w = BitWriter::endian(vec![], BigEndian);
133 /// // writing a value larger than 4 bits in 4 bits is a runtime error
134 /// assert!(w.write_var::<u8>(4, u8::MAX).is_err());
135 /// // writing 9 bits from a u8 is also a runtime error
136 /// assert!(w.write_var::<u8>(9, 0).is_err());
137 /// ```
138 #[inline]
139 fn write_var<I>(&mut self, bits: u32, value: I) -> io::Result<()>
140 where
141 I: Integer,
142 {
143 self.write_counted(BitCount::unknown(bits), value)
144 }
145
146 /// Writes an unsigned value to the stream using the given
147 /// const number of bits.
148 ///
149 /// # Errors
150 ///
151 /// Passes along any I/O error from the underlying stream.
152 /// Returns an error if the value is too large
153 /// to fit the given number of bits.
154 /// A compile-time error occurs if the given number of bits
155 /// is larger than the output type.
156 ///
157 /// # Examples
158 /// ```
159 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
160 ///
161 /// let mut writer = BitWriter::endian(vec![], BigEndian);
162 /// writer.write_unsigned::<1, u8>(0b1).unwrap();
163 /// writer.write_unsigned::<2, u8>(0b01).unwrap();
164 /// writer.write_unsigned::<5, u8>(0b10111).unwrap();
165 /// assert_eq!(writer.into_writer(), [0b1_01_10111]);
166 /// ```
167 ///
168 /// ```
169 /// use oximedia_bitstream::{LittleEndian, BitWriter, BitWrite};
170 ///
171 /// let mut writer = BitWriter::endian(vec![], LittleEndian);
172 /// writer.write_unsigned::<1, u8>(0b1).unwrap();
173 /// writer.write_unsigned::<2, u8>(0b11).unwrap();
174 /// writer.write_unsigned::<5, u8>(0b10110).unwrap();
175 /// assert_eq!(writer.into_writer(), [0b10110_11_1]);
176 /// ```
177 ///
178 /// ```rust,compile_fail
179 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
180 ///
181 /// let mut writer = BitWriter::endian(vec![], BigEndian);
182 /// // trying to write 9 bits from a u8 is a compile-time error
183 /// writer.write_unsigned::<9, u8>(1);
184 /// ```
185 ///
186 /// ```
187 /// use std::io::{Write, sink};
188 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
189 ///
190 /// let mut w = BitWriter::endian(sink(), BigEndian);
191 /// assert!(w.write_unsigned::<1, u8>(2).is_err()); // can't write 2 in 1 bit
192 /// assert!(w.write_unsigned::<2, u8>(4).is_err()); // can't write 4 in 2 bits
193 /// assert!(w.write_unsigned::<3, u8>(8).is_err()); // can't write 8 in 3 bits
194 /// assert!(w.write_unsigned::<4, u8>(16).is_err()); // can't write 16 in 4 bits
195 /// ```
196 #[inline]
197 fn write_unsigned<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
198 where
199 U: UnsignedInteger,
200 {
201 self.write_unsigned_var(BITS, value)
202 }
203
204 /// Writes an unsigned value to the stream using the given
205 /// number of bits.
206 ///
207 /// # Errors
208 ///
209 /// Passes along any I/O error from the underlying stream.
210 /// Returns an error if the input type is too small
211 /// to hold the given number of bits.
212 /// Returns an error if the value is too large
213 /// to fit the given number of bits.
214 ///
215 /// # Examples
216 /// ```
217 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
218 ///
219 /// let mut writer = BitWriter::endian(vec![], BigEndian);
220 /// writer.write_unsigned_var::<u8>(1, 0b1).unwrap();
221 /// writer.write_unsigned_var::<u8>(2, 0b01).unwrap();
222 /// writer.write_unsigned_var::<u8>(5, 0b10111).unwrap();
223 /// assert_eq!(writer.into_writer(), [0b1_01_10111]);
224 /// ```
225 ///
226 /// ```
227 /// use std::io::Write;
228 /// use oximedia_bitstream::{LittleEndian, BitWriter, BitWrite};
229 ///
230 /// let mut writer = BitWriter::endian(vec![], LittleEndian);
231 /// writer.write_unsigned_var::<u8>(1, 0b1).unwrap();
232 /// writer.write_unsigned_var::<u8>(2, 0b11).unwrap();
233 /// writer.write_unsigned_var::<u8>(5, 0b10110).unwrap();
234 /// assert_eq!(writer.into_writer(), [0b10110_11_1]);
235 /// ```
236 ///
237 /// ```
238 /// use std::io::{Write, sink};
239 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
240 ///
241 /// let mut w = BitWriter::endian(sink(), BigEndian);
242 /// assert!(w.write_unsigned_var::<u8>(9, 0).is_err()); // can't write u8 in 9 bits
243 /// assert!(w.write_unsigned_var::<u16>(17, 0).is_err()); // can't write u16 in 17 bits
244 /// assert!(w.write_unsigned_var::<u32>(33, 0).is_err()); // can't write u32 in 33 bits
245 /// assert!(w.write_unsigned_var::<u64>(65, 0).is_err()); // can't write u64 in 65 bits
246 /// assert!(w.write_unsigned_var::<u8>(1, 2).is_err()); // can't write 2 in 1 bit
247 /// assert!(w.write_unsigned_var::<u8>(2, 4).is_err()); // can't write 4 in 2 bits
248 /// assert!(w.write_unsigned_var::<u8>(3, 8).is_err()); // can't write 8 in 3 bits
249 /// assert!(w.write_unsigned_var::<u8>(4, 16).is_err()); // can't write 16 in 4 bits
250 /// ```
251 fn write_unsigned_var<U>(&mut self, bits: u32, value: U) -> io::Result<()>
252 where
253 U: UnsignedInteger,
254 {
255 self.write_unsigned_counted(BitCount::unknown(bits), value)
256 }
257
258 /// Writes a twos-complement signed value to the stream
259 /// with the given const number of bits.
260 ///
261 /// # Errors
262 ///
263 /// Passes along any I/O error from the underlying stream.
264 /// Returns an error if the value is too large
265 /// to fit the given number of bits.
266 /// A compile-time error occurs if the number of bits is 0,
267 /// since one bit is always needed for the sign.
268 /// A compile-time error occurs if the given number of bits
269 /// is larger than the output type.
270 ///
271 /// # Examples
272 /// ```
273 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
274 ///
275 /// let mut writer = BitWriter::endian(vec![], BigEndian);
276 /// writer.write_signed::<4, i8>(-5).unwrap();
277 /// writer.write_signed::<4, i8>(7).unwrap();
278 /// assert_eq!(writer.into_writer(), [0b10110111]);
279 /// ```
280 ///
281 /// ```
282 /// use oximedia_bitstream::{LittleEndian, BitWriter, BitWrite};
283 ///
284 /// let mut writer = BitWriter::endian(vec![], LittleEndian);
285 /// writer.write_signed::<4, i8>(7).unwrap();
286 /// writer.write_signed::<4, i8>(-5).unwrap();
287 /// assert_eq!(writer.into_writer(), [0b10110111]);
288 /// ```
289 ///
290 /// ```
291 /// use oximedia_bitstream::{LittleEndian, BitWriter, BitWrite};
292 ///
293 /// let mut writer = BitWriter::endian(vec![], LittleEndian);
294 /// // writing a value too large for 4 bits in 4 bits is a runtime error
295 /// assert!(writer.write_signed::<4, i8>(i8::MAX).is_err());
296 /// ```
297 ///
298 /// ```rust,compile_fail
299 /// use oximedia_bitstream::{LittleEndian, BitWriter, BitWrite};
300 ///
301 /// let mut writer = BitWriter::endian(vec![], LittleEndian);
302 /// // writing 9 bits from an i8 is a compile-time error
303 /// assert!(writer.write_signed::<9, i8>(1).is_err());
304 /// ```
305 fn write_signed<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
306 where
307 S: SignedInteger,
308 {
309 self.write_signed_var(BITS, value)
310 }
311
312 /// Writes a twos-complement signed value to the stream
313 /// with the given number of bits.
314 ///
315 /// # Errors
316 ///
317 /// Passes along any I/O error from the underlying stream.
318 /// Returns an error if the input type is too small
319 /// to hold the given number of bits.
320 /// Returns an error if the number of bits is 0,
321 /// since one bit is always needed for the sign.
322 /// Returns an error if the value is too large
323 /// to fit the given number of bits.
324 ///
325 /// # Examples
326 /// ```
327 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
328 ///
329 /// let mut writer = BitWriter::endian(vec![], BigEndian);
330 /// writer.write_signed_var(4, -5).unwrap();
331 /// writer.write_signed_var(4, 7).unwrap();
332 /// assert_eq!(writer.into_writer(), [0b10110111]);
333 /// ```
334 ///
335 /// ```
336 /// use oximedia_bitstream::{LittleEndian, BitWriter, BitWrite};
337 ///
338 /// let mut writer = BitWriter::endian(vec![], LittleEndian);
339 /// writer.write_signed_var(4, 7).unwrap();
340 /// writer.write_signed_var(4, -5).unwrap();
341 /// assert_eq!(writer.into_writer(), [0b10110111]);
342 /// ```
343 #[inline(always)]
344 fn write_signed_var<S>(&mut self, bits: u32, value: S) -> io::Result<()>
345 where
346 S: SignedInteger,
347 {
348 self.write_signed_counted(BitCount::unknown(bits), value)
349 }
350
351 /// Writes the given bit count to the stream
352 /// with the necessary maximum number of bits.
353 ///
354 /// For example, if the maximum bit count is 15 - or `0b1111` -
355 /// writes the bit count to the stream as a 4-bit unsigned value
356 /// which can be used in subsequent writes.
357 ///
358 /// Note that `MAX` must be greater than 0.
359 /// Unlike the bit reader, the bit count need not be an exact
360 /// power of two when writing. Any bits higher than the
361 /// bit count can reach are simply left 0.
362 ///
363 /// # Errors
364 ///
365 /// Passes along an I/O error from the underlying stream.
366 ///
367 /// ```
368 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
369 ///
370 /// let mut w = BitWriter::endian(vec![], BigEndian);
371 /// let count = 4;
372 /// w.write::<3, u32>(count).unwrap();
373 /// // may need to verify count is not larger than u8 at runtime
374 /// w.write_var::<u8>(count, 0b1111).unwrap();
375 /// w.byte_align().unwrap();
376 /// assert_eq!(w.into_writer(), &[0b100_11110]);
377 /// ```
378 ///
379 /// ```
380 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite, BitCount};
381 ///
382 /// let mut w = BitWriter::endian(vec![], BigEndian);
383 /// // a bit count of 4, with a maximum of 7 (0b111)
384 /// let count: BitCount<0b111> = BitCount::new::<4>();
385 /// w.write_count(count).unwrap();
386 /// // maximum size of count is known to be 7 bits at compile-time
387 /// // so no need to check that 7 bits is larger than a u8 at runtime
388 /// w.write_counted::<0b111, u8>(count, 0b1111).unwrap();
389 /// w.byte_align().unwrap();
390 /// assert_eq!(w.into_writer(), &[0b100_11110]);
391 /// ```
392 ///
393 /// ```
394 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite, BitCount};
395 ///
396 /// let mut w = BitWriter::endian(vec![], BigEndian);
397 /// // a bit count of 4, with a maximum of 6 (0b110)
398 /// let count: BitCount<0b110> = BitCount::new::<4>();
399 /// w.write_count(count).unwrap();
400 /// w.write_counted::<0b110, u8>(count, 0b1111).unwrap();
401 /// w.byte_align().unwrap();
402 /// // bit count is written in 3 bits
403 /// // while actual value is written in 4 bits
404 /// assert_eq!(w.into_writer(), &[0b100_11110]);
405 /// ```
406 fn write_count<const MAX: u32>(&mut self, BitCount { bits }: BitCount<MAX>) -> io::Result<()> {
407 const {
408 assert!(MAX > 0, "MAX value must be > 0");
409 }
410
411 self.write_unsigned_var(
412 if MAX == u32::MAX {
413 32
414 } else if (MAX + 1).is_power_of_two() {
415 (MAX + 1).ilog2()
416 } else {
417 (MAX + 1).ilog2() + 1
418 },
419 bits,
420 )
421 }
422
423 /// Writes a signed or unsigned value to the stream with
424 /// the given number of bits.
425 ///
426 /// # Errors
427 ///
428 /// Passes along any I/O error from the underlying stream.
429 /// Returns an error if the value is too large
430 /// to fit the given number of bits.
431 ///
432 /// # Examples
433 /// ```
434 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian, BitCount};
435 ///
436 /// let mut w = BitWriter::endian(vec![], BigEndian);
437 /// // writing 4 bits with a maximum of 8 will fit into a u8
438 /// // so we only need check the value fits into 4 bits
439 /// assert!(w.write_counted::<4, u8>(BitCount::new::<4>(), 0b1111).is_ok());
440 /// assert!(w.write_counted::<4, u8>(BitCount::new::<4>(), 0b1111 + 1).is_err());
441 /// // writing 4 bits with a maximum of 64 might not fit into a u8
442 /// // so need to verify this at runtime
443 /// assert!(w.write_counted::<64, u8>(BitCount::new::<4>(), 0b0000).is_ok());
444 /// assert_eq!(w.into_writer(), &[0b1111_0000]);
445 /// ```
446 fn write_counted<const MAX: u32, I>(&mut self, bits: BitCount<MAX>, value: I) -> io::Result<()>
447 where
448 I: Integer + Sized,
449 {
450 I::write_var::<MAX, _>(value, self, bits)
451 }
452
453 /// Writes a signed value to the stream with
454 /// the given number of bits.
455 ///
456 /// # Errors
457 ///
458 /// Passes along any I/O error from the underlying stream.
459 /// Returns an error if the value is too large
460 /// to fit the given number of bits.
461 ///
462 /// # Examples
463 /// ```
464 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian, BitCount};
465 ///
466 /// let mut w = BitWriter::endian(vec![], BigEndian);
467 /// // writing 4 bits with a maximum of 8 will fit into a u8
468 /// // so we only need check the value fits into 4 bits
469 /// assert!(w.write_unsigned_counted::<4, u8>(BitCount::new::<4>(), 0b1111).is_ok());
470 /// assert!(w.write_unsigned_counted::<4, u8>(BitCount::new::<4>(), 0b1111 + 1).is_err());
471 /// // writing 4 bits with a maximum of 64 might not fit into a u8
472 /// // so need to verify this at runtime
473 /// assert!(w.write_unsigned_counted::<64, u8>(BitCount::new::<4>(), 0b0000).is_ok());
474 /// assert_eq!(w.into_writer(), &[0b1111_0000]);
475 /// ```
476 fn write_unsigned_counted<const BITS: u32, U>(
477 &mut self,
478 bits: BitCount<BITS>,
479 value: U,
480 ) -> io::Result<()>
481 where
482 U: UnsignedInteger;
483
484 /// Writes an unsigned value to the stream with
485 /// the given number of bits.
486 ///
487 /// # Errors
488 ///
489 /// Passes along any I/O error from the underlying stream.
490 /// Returns an error if the value is too large
491 /// to fit the given number of bits.
492 ///
493 /// # Examples
494 /// ```
495 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian, BitCount};
496 ///
497 /// let mut w = BitWriter::endian(vec![], BigEndian);
498 /// // writing 4 bits with a maximum of 8 will fit into an i8
499 /// // so we only need check the value fits into 4 bits
500 /// assert!(w.write_signed_counted::<4, i8>(BitCount::new::<4>(), 0b0111).is_ok());
501 /// assert!(w.write_signed_counted::<4, i8>(BitCount::new::<4>(), 0b0111 + 1).is_err());
502 /// // writing 4 bits with a maximum of 64 might not fit into a i8
503 /// // so need to verify this at runtime
504 /// assert!(w.write_signed_counted::<64, i8>(BitCount::new::<4>(), 0b0000).is_ok());
505 /// assert_eq!(w.into_writer(), &[0b0111_0000]);
506 /// ```
507 fn write_signed_counted<const MAX: u32, S>(
508 &mut self,
509 bits: impl TryInto<SignedBitCount<MAX>>,
510 value: S,
511 ) -> io::Result<()>
512 where
513 S: SignedInteger;
514
515 /// Writes the given constant value to the stream with
516 /// the given number of bits.
517 ///
518 /// Due to current limitations of constant parameters,
519 /// this is limited to `u32` values.
520 ///
521 /// # Errors
522 ///
523 /// Passes along any I/O error from the underlying stream.
524 /// A compile-time error occurs if the number of bits is larger
525 /// than 32 or if the value is too large too fit the
526 /// requested number of bits.
527 ///
528 /// # Examples
529 ///
530 /// ```
531 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
532 ///
533 /// let mut w = BitWriter::endian(vec![], BigEndian);
534 /// assert!(w.write_const::<4, 0b1000>().is_ok());
535 /// assert!(w.write_const::<4, 0b1011>().is_ok());
536 /// assert_eq!(w.into_writer(), &[0b1000_1011]);
537 /// ```
538 ///
539 /// ```rust,compile_fail
540 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
541 ///
542 /// let mut w = BitWriter::endian(vec![], BigEndian);
543 /// // trying to write a 5 bit value in 4 bits is a compile-time error
544 /// w.write_const::<4, 0b11111>();
545 /// ```
546 ///
547 /// ```rust,compile_fail
548 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
549 ///
550 /// let mut w = BitWriter::endian(vec![], BigEndian);
551 /// // trying to write a 33 bit value is also a compile-time error
552 /// w.write_const::<33, 1>();
553 /// ```
554 #[inline]
555 fn write_const<const BITS: u32, const VALUE: u32>(&mut self) -> io::Result<()> {
556 const {
557 assert!(
558 BITS == 0 || VALUE <= (u32::ALL >> (u32::BITS_SIZE - BITS)),
559 "excessive value for bits written"
560 );
561 }
562
563 self.write::<BITS, u32>(VALUE)
564 }
565
566 /// Writes whole value to the stream whose size in bits
567 /// is equal to its type's size.
568 ///
569 /// # Errors
570 ///
571 /// Passes along any I/O error from the underlying stream.
572 ///
573 /// # Examples
574 /// ```
575 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
576 ///
577 /// let mut w = BitWriter::endian(vec![], BigEndian);
578 /// assert!(w.write_from::<u32>(0x12_34_56_78).is_ok());
579 /// assert_eq!(w.into_writer(), &[0x12, 0x34, 0x56, 0x78]);
580 /// ```
581 ///
582 /// ```
583 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
584 ///
585 /// let mut w = BitWriter::endian(vec![], BigEndian);
586 /// assert!(w.write_from::<[u8; 4]>([0x12, 0x34, 0x56, 0x78]).is_ok());
587 /// assert_eq!(w.into_writer(), &[0x12, 0x34, 0x56, 0x78]);
588 /// ```
589 fn write_from<V>(&mut self, value: V) -> io::Result<()>
590 where
591 V: Primitive;
592
593 /// Writes whole value to the stream whose size in bits
594 /// is equal to its type's size in an endianness that may
595 /// be different from the stream's endianness.
596 ///
597 /// # Errors
598 ///
599 /// Passes along any I/O error from the underlying stream.
600 ///
601 /// # Examples
602 /// ```
603 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian, LittleEndian};
604 ///
605 /// let mut w = BitWriter::endian(vec![], BigEndian);
606 /// assert!(w.write_as_from::<LittleEndian, u32>(0x12_34_56_78).is_ok());
607 /// assert_eq!(w.into_writer(), &[0x78, 0x56, 0x34, 0x12]);
608 /// ```
609 fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
610 where
611 F: Endianness,
612 V: Primitive;
613
614 /// Pads the stream by writing 0 over the given number of bits.
615 ///
616 /// # Errors
617 ///
618 /// Passes along any I/O error from the underlying stream.
619 ///
620 /// # Example
621 ///
622 /// ```
623 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
624 ///
625 /// let mut w = BitWriter::endian(vec![], BigEndian);
626 /// assert!(w.write_bit(true).is_ok());
627 /// assert!(w.pad(7).is_ok());
628 /// assert_eq!(w.into_writer(), &[0b1_0000000]);
629 /// ```
630 fn pad(&mut self, mut bits: u32) -> io::Result<()> {
631 loop {
632 match bits {
633 0 => break Ok(()),
634 bits @ 1..64 => break self.write_var(bits, 0u64),
635 _ => {
636 self.write::<64, u64>(0)?;
637 bits -= 64;
638 }
639 }
640 }
641 }
642
643 /// Writes the entirety of a byte buffer to the stream.
644 ///
645 /// # Errors
646 ///
647 /// Passes along any I/O error from the underlying stream.
648 ///
649 /// # Example
650 ///
651 /// ```
652 /// use std::io::Write;
653 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
654 /// let mut writer = BitWriter::endian(Vec::new(), BigEndian);
655 /// writer.write_var(8, 0x66u8).unwrap();
656 /// writer.write_var(8, 0x6Fu8).unwrap();
657 /// writer.write_var(8, 0x6Fu8).unwrap();
658 /// writer.write_bytes(b"bar").unwrap();
659 /// assert_eq!(writer.into_writer(), b"foobar");
660 /// ```
661 #[inline]
662 fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
663 buf.iter().try_for_each(|b| self.write_unsigned::<8, _>(*b))
664 }
665
666 /// Writes `value` number of non `STOP_BIT` bits to the stream
667 /// and then writes a `STOP_BIT`. This field is variably-sized.
668 /// `STOP_BIT` must be 0 or 1.
669 ///
670 /// # Errors
671 ///
672 /// Passes along any I/O error from the underyling stream.
673 ///
674 /// # Examples
675 /// ```
676 /// use std::io::Write;
677 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
678 /// let mut writer = BitWriter::endian(Vec::new(), BigEndian);
679 /// writer.write_unary::<0>(0).unwrap();
680 /// writer.write_unary::<0>(3).unwrap();
681 /// writer.write_unary::<0>(10).unwrap();
682 /// assert_eq!(writer.into_writer(), [0b01110111, 0b11111110]);
683 /// ```
684 ///
685 /// ```
686 /// use std::io::Write;
687 /// use oximedia_bitstream::{LittleEndian, BitWriter, BitWrite};
688 /// let mut writer = BitWriter::endian(Vec::new(), LittleEndian);
689 /// writer.write_unary::<0>(0).unwrap();
690 /// writer.write_unary::<0>(3).unwrap();
691 /// writer.write_unary::<0>(10).unwrap();
692 /// assert_eq!(writer.into_writer(), [0b11101110, 0b01111111]);
693 /// ```
694 ///
695 /// ```
696 /// use std::io::Write;
697 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
698 /// let mut writer = BitWriter::endian(Vec::new(), BigEndian);
699 /// writer.write_unary::<1>(0).unwrap();
700 /// writer.write_unary::<1>(3).unwrap();
701 /// writer.write_unary::<1>(10).unwrap();
702 /// assert_eq!(writer.into_writer(), [0b10001000, 0b00000001]);
703 /// ```
704 ///
705 /// ```
706 /// use std::io::Write;
707 /// use oximedia_bitstream::{LittleEndian, BitWriter, BitWrite};
708 /// let mut writer = BitWriter::endian(Vec::new(), LittleEndian);
709 /// writer.write_unary::<1>(0).unwrap();
710 /// writer.write_unary::<1>(3).unwrap();
711 /// writer.write_unary::<1>(10).unwrap();
712 /// assert_eq!(writer.into_writer(), [0b00010001, 0b10000000]);
713 /// ```
714 fn write_unary<const STOP_BIT: u8>(&mut self, mut value: u32) -> io::Result<()> {
715 const {
716 assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1");
717 }
718
719 const MAX: BitCount<32> = BitCount::new::<32>();
720
721 match STOP_BIT {
722 0 => {
723 while value > 0 {
724 let to_write = MAX.min(value);
725 self.write_checked(to_write.all::<u32>())?;
726 value -= u32::from(to_write);
727 }
728 self.write_bit(false)
729 }
730 1 => {
731 while value > 0 {
732 let to_write = MAX.min(value);
733 self.write_checked(to_write.none::<u32>())?;
734 value -= u32::from(to_write);
735 }
736 self.write_bit(true)
737 }
738 _ => unreachable!(),
739 }
740 }
741
742 /// Writes checked value that is known to fit a given number of bits
743 fn write_checked<C: Checkable>(&mut self, value: C) -> io::Result<()> {
744 // a naive default implementation
745 value.write(self)
746 }
747
748 /// Builds and writes complex type
749 fn build<T: ToBitStream>(&mut self, build: &T) -> Result<(), T::Error> {
750 build.to_writer(self)
751 }
752
753 /// Builds and writes complex type with context
754 fn build_with<'a, T: ToBitStreamWith<'a>>(
755 &mut self,
756 build: &T,
757 context: &T::Context,
758 ) -> Result<(), T::Error> {
759 build.to_writer(self, context)
760 }
761
762 /// Builds and writes complex type with owned context
763 fn build_using<T: ToBitStreamUsing>(
764 &mut self,
765 build: &T,
766 context: T::Context,
767 ) -> Result<(), T::Error> {
768 build.to_writer(self, context)
769 }
770
771 /// Returns true if the stream is aligned at a whole byte.
772 ///
773 /// # Example
774 /// ```
775 /// use std::io::{Write, sink};
776 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
777 /// let mut writer = BitWriter::endian(sink(), BigEndian);
778 /// assert_eq!(writer.byte_aligned(), true);
779 /// writer.write_var(1, 0u8).unwrap();
780 /// assert_eq!(writer.byte_aligned(), false);
781 /// writer.write_var(7, 0u8).unwrap();
782 /// assert_eq!(writer.byte_aligned(), true);
783 /// ```
784 fn byte_aligned(&self) -> bool;
785
786 /// Pads the stream with 0 bits until it is aligned at a whole byte.
787 /// Does nothing if the stream is already aligned.
788 ///
789 /// # Errors
790 ///
791 /// Passes along any I/O error from the underyling stream.
792 ///
793 /// # Example
794 /// ```
795 /// use std::io::Write;
796 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
797 /// let mut writer = BitWriter::endian(Vec::new(), BigEndian);
798 /// writer.write_var(1, 0u8).unwrap();
799 /// writer.byte_align().unwrap();
800 /// writer.write_var(8, 0xFFu8).unwrap();
801 /// assert_eq!(writer.into_writer(), [0x00, 0xFF]);
802 /// ```
803 fn byte_align(&mut self) -> io::Result<()> {
804 while !BitWrite::byte_aligned(self) {
805 self.write_bit(false)?;
806 }
807 Ok(())
808 }
809
810 /// Given a symbol, writes its representation to the output stream as bits.
811 /// Generates no output if the symbol isn't defined in the Huffman tree.
812 ///
813 /// # Errors
814 ///
815 /// Passes along any I/O error from the underlying stream.
816 ///
817 /// # Example
818 /// ```
819 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
820 /// use oximedia_bitstream::define_huffman_tree;
821 ///
822 /// define_huffman_tree!(TreeName : char = ['a', ['b', ['c', 'd']]]);
823 /// // 'a' is 0
824 /// // 'b' is 1 -> 0
825 /// // 'c' is 1 -> 1 -> 0
826 /// // 'd' is 1 -> 1 -> 1
827 ///
828 /// let mut writer = BitWriter::endian(vec![], BigEndian);
829 /// writer.write_huffman::<TreeName>('b').unwrap();
830 /// writer.write_huffman::<TreeName>('c').unwrap();
831 /// writer.write_huffman::<TreeName>('d').unwrap();
832 /// assert_eq!(writer.into_writer(), [0b10_110_111]);
833 /// ```
834 fn write_huffman<T>(&mut self, value: T::Symbol) -> io::Result<()>
835 where
836 T: crate::huffman::ToBits,
837 {
838 T::to_bits(value, |b| self.write_bit(b))
839 }
840
841 /// Writes a number using a variable using a variable width integer.
842 /// This optimises the case when the number is small.
843 ///
844 /// Given a 4-bit VBR field, any 3-bit value (0 through 7) is encoded directly, with the high bit set to zero.
845 /// Values larger than N-1 bits emit their bits in a series of N-1 bit chunks, where all but the last set the high bit.
846 ///
847 /// # Errors
848 ///
849 /// Passes along any I/O error from the underlying stream.
850 ///
851 /// # Example
852 /// ```
853 /// use std::io::Write;
854 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
855 /// let mut writer = BitWriter::endian(Vec::new(), BigEndian);
856 /// writer.write_unsigned_vbr::<4,_>(7u32);
857 /// writer.write_unsigned_vbr::<4,_>(100u32);
858 /// assert_eq!(writer.into_writer(), [0b0111_1100, 0b1100_0001]);
859 /// ```
860 fn write_unsigned_vbr<const FIELD_SIZE: u32, U: UnsignedInteger>(
861 &mut self,
862 value: U,
863 ) -> io::Result<()> {
864 const { assert!(FIELD_SIZE >= 2 && FIELD_SIZE < U::BITS_SIZE) };
865 let payload_bits = FIELD_SIZE - 1;
866 let continuation_bit = U::ONE.shl(payload_bits);
867 let payload_mask = continuation_bit.sub(U::ONE);
868 let mut value = value;
869
870 loop {
871 let payload = value & payload_mask;
872 value >>= payload_bits;
873 if value != U::ZERO {
874 self.write_unsigned::<FIELD_SIZE, U>(payload | continuation_bit)?;
875 } else {
876 self.write_unsigned::<FIELD_SIZE, U>(payload)?;
877 break;
878 }
879 }
880 Ok(())
881 }
882
883 /// Writes a number using a variable using a variable width integer.
884 /// This optimises the case when the number is small.
885 ///
886 /// The integer is mapped to an unsigned value using zigzag encoding.
887 /// For an integer X:
888 /// - if X >= 0 -> 2X
889 /// - else -> -2X + 1
890 ///
891 /// # Errors
892 ///
893 /// Passes along any I/O error from the underlying stream.
894 ///
895 /// # Example
896 /// ```
897 /// use std::io::Write;
898 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
899 /// let mut writer = BitWriter::endian(Vec::new(), BigEndian);
900 /// writer.write_signed_vbr::<4,_>(3);
901 /// writer.write_signed_vbr::<4,_>(-50);
902 /// assert_eq!(writer.into_writer(), [0b0110_1011, 0b1100_0001]);
903 /// ```
904 #[inline]
905 fn write_signed_vbr<const FIELD_SIZE: u32, I: SignedInteger>(
906 &mut self,
907 value: I,
908 ) -> io::Result<()> {
909 let zig_zag = value.shl(1).bitxor(value.shr(I::BITS_SIZE - 1));
910 self.write_unsigned_vbr::<FIELD_SIZE, _>(zig_zag.as_non_negative())
911 }
912
913 /// Writes a signed or unsigned variable width integer to the stream
914 ///
915 /// # Errors
916 ///
917 /// Passes along any I/O error from the underlying stream.
918 ///
919 /// # Example
920 /// ```
921 /// use std::io::Write;
922 /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
923 /// let mut writer = BitWriter::endian(Vec::new(), BigEndian);
924 /// writer.write_vbr::<4,_>(6u32);
925 /// writer.write_vbr::<4,_>(-50i32);
926 /// assert_eq!(writer.into_writer(), [0b0110_1011, 0b1100_0001]);
927 /// ```
928 #[inline]
929 fn write_vbr<const FIELD_SIZE: u32, I: VBRInteger>(&mut self, value: I) -> io::Result<()> {
930 I::write_vbr::<FIELD_SIZE, _>(value, self)
931 }
932
933 /// Creates a "by reference" adaptor for this `BitWrite`
934 ///
935 /// The returned adapter also implements `BitWrite`
936 /// and will borrow the current reader.
937 ///
938 /// # Example
939 /// ```
940 /// use oximedia_bitstream::{BitWriter, BitWrite, BigEndian};
941 ///
942 /// fn build<W: BitWrite>(w: W) {
943 /// // perform some building
944 /// }
945 ///
946 /// let mut writer = BitWriter::endian(vec![], BigEndian);
947 /// // performing building by reference
948 /// build(writer.by_ref());
949 /// // original owned writer still available
950 /// writer.write::<8, u8>(0).unwrap();
951 /// assert_eq!(writer.into_writer(), &[0]);
952 /// ```
953 #[inline]
954 fn by_ref(&mut self) -> &mut Self {
955 self
956 }
957}
958
959impl<W: BitWrite + ?Sized> BitWrite for &mut W {
960 #[inline]
961 fn write_bit(&mut self, bit: bool) -> io::Result<()> {
962 (**self).write_bit(bit)
963 }
964
965 #[inline]
966 fn write<const BITS: u32, I>(&mut self, value: I) -> io::Result<()>
967 where
968 I: Integer,
969 {
970 (**self).write::<BITS, I>(value)
971 }
972
973 #[inline]
974 fn write_const<const BITS: u32, const VALUE: u32>(&mut self) -> io::Result<()> {
975 (**self).write_const::<BITS, VALUE>()
976 }
977
978 #[inline]
979 fn write_var<I>(&mut self, bits: u32, value: I) -> io::Result<()>
980 where
981 I: Integer,
982 {
983 (**self).write_var(bits, value)
984 }
985
986 #[inline]
987 fn write_unsigned<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
988 where
989 U: UnsignedInteger,
990 {
991 (**self).write_unsigned::<BITS, U>(value)
992 }
993
994 #[inline]
995 fn write_unsigned_var<U>(&mut self, bits: u32, value: U) -> io::Result<()>
996 where
997 U: UnsignedInteger,
998 {
999 (**self).write_unsigned_var(bits, value)
1000 }
1001
1002 #[inline]
1003 fn write_signed<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
1004 where
1005 S: SignedInteger,
1006 {
1007 (**self).write_signed::<BITS, S>(value)
1008 }
1009
1010 #[inline(always)]
1011 fn write_signed_var<S>(&mut self, bits: u32, value: S) -> io::Result<()>
1012 where
1013 S: SignedInteger,
1014 {
1015 (**self).write_signed_var(bits, value)
1016 }
1017
1018 #[inline]
1019 fn write_count<const MAX: u32>(&mut self, count: BitCount<MAX>) -> io::Result<()> {
1020 (**self).write_count::<MAX>(count)
1021 }
1022
1023 #[inline]
1024 fn write_counted<const MAX: u32, I>(&mut self, bits: BitCount<MAX>, value: I) -> io::Result<()>
1025 where
1026 I: Integer + Sized,
1027 {
1028 (**self).write_counted::<MAX, I>(bits, value)
1029 }
1030
1031 #[inline]
1032 fn write_unsigned_counted<const BITS: u32, U>(
1033 &mut self,
1034 bits: BitCount<BITS>,
1035 value: U,
1036 ) -> io::Result<()>
1037 where
1038 U: UnsignedInteger,
1039 {
1040 (**self).write_unsigned_counted::<BITS, U>(bits, value)
1041 }
1042
1043 #[inline]
1044 fn write_signed_counted<const MAX: u32, S>(
1045 &mut self,
1046 bits: impl TryInto<SignedBitCount<MAX>>,
1047 value: S,
1048 ) -> io::Result<()>
1049 where
1050 S: SignedInteger,
1051 {
1052 (**self).write_signed_counted::<MAX, S>(bits, value)
1053 }
1054
1055 #[inline]
1056 fn write_from<V>(&mut self, value: V) -> io::Result<()>
1057 where
1058 V: Primitive,
1059 {
1060 (**self).write_from::<V>(value)
1061 }
1062
1063 #[inline]
1064 fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
1065 where
1066 F: Endianness,
1067 V: Primitive,
1068 {
1069 (**self).write_as_from::<F, V>(value)
1070 }
1071
1072 #[inline]
1073 fn pad(&mut self, bits: u32) -> io::Result<()> {
1074 (**self).pad(bits)
1075 }
1076
1077 #[inline]
1078 fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
1079 (**self).write_bytes(buf)
1080 }
1081
1082 #[inline]
1083 fn write_unary<const STOP_BIT: u8>(&mut self, value: u32) -> io::Result<()> {
1084 (**self).write_unary::<STOP_BIT>(value)
1085 }
1086
1087 #[inline]
1088 fn write_checked<C: Checkable>(&mut self, value: C) -> io::Result<()> {
1089 (**self).write_checked(value)
1090 }
1091
1092 #[inline]
1093 fn build<T: ToBitStream>(&mut self, build: &T) -> Result<(), T::Error> {
1094 (**self).build(build)
1095 }
1096
1097 #[inline]
1098 fn build_with<'a, T: ToBitStreamWith<'a>>(
1099 &mut self,
1100 build: &T,
1101 context: &T::Context,
1102 ) -> Result<(), T::Error> {
1103 (**self).build_with(build, context)
1104 }
1105
1106 #[inline]
1107 fn byte_aligned(&self) -> bool {
1108 (**self).byte_aligned()
1109 }
1110
1111 #[inline]
1112 fn byte_align(&mut self) -> io::Result<()> {
1113 (**self).byte_align()
1114 }
1115
1116 #[inline]
1117 fn write_huffman<T>(&mut self, value: T::Symbol) -> io::Result<()>
1118 where
1119 T: crate::huffman::ToBits,
1120 {
1121 (**self).write_huffman::<T>(value)
1122 }
1123}