Skip to main content

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}