Skip to main content

oximedia_bitstream/write/
bit_write2.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//! Legacy `BitWrite2` compatibility trait.
8
9use std::io;
10
11use crate::endian::write_byte;
12
13use super::{
14    BitCount, BitWrite, BitWriter, Checkable, CheckedSigned, CheckedUnsigned, Endianness, Integer,
15    Primitive, SignedBitCount, SignedInteger, ToBitStream, ToBitStreamWith, UnsignedInteger,
16};
17
18/// A compatibility trait for older code implementing [`BitWrite`]
19///
20/// This is a trait largely compatible with older code
21/// from the 2.X.X version,
22/// which one can use with a named import as needed.
23///
24/// New code should prefer the regular [`BitWrite`] trait.
25///
26/// # Example
27/// ```
28/// use oximedia_bitstream::BitWrite2 as BitWrite;
29/// use oximedia_bitstream::{BitWriter, BigEndian};
30/// let mut byte = vec![];
31/// let mut writer = BitWriter::endian(byte, BigEndian);
32/// writer.write::<u8>(4, 0b1111).unwrap();
33/// writer.write_out::<4, u8>(0b0000).unwrap();
34/// assert_eq!(writer.into_writer(), [0b1111_0000]);
35/// ```
36pub trait BitWrite2 {
37    /// Writes a single bit to the stream.
38    /// `true` indicates 1, `false` indicates 0
39    ///
40    /// # Errors
41    ///
42    /// Passes along any I/O error from the underlying stream.
43    fn write_bit(&mut self, bit: bool) -> io::Result<()> {
44        self.write_unsigned_out::<1, u8>(u8::from(bit))
45    }
46
47    /// Writes a signed or unsigned value to the stream using the given
48    /// number of bits.
49    ///
50    /// # Errors
51    ///
52    /// Passes along any I/O error from the underlying stream.
53    /// Returns an error if the input type is too small
54    /// to hold the given number of bits.
55    /// Returns an error if the value is too large
56    /// to fit the given number of bits.
57    fn write<I>(&mut self, bits: u32, value: I) -> io::Result<()>
58    where
59        I: Integer;
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    fn write_out<const BITS: u32, I>(&mut self, value: I) -> io::Result<()>
72    where
73        I: Integer;
74
75    /// Writes an unsigned value to the stream using the given
76    /// number of bits.
77    ///
78    /// # Errors
79    ///
80    /// Passes along any I/O error from the underlying stream.
81    /// Returns an error if the input type is too small
82    /// to hold the given number of bits.
83    /// Returns an error if the value is too large
84    /// to fit the given number of bits.
85    fn write_unsigned<U>(&mut self, bits: u32, value: U) -> io::Result<()>
86    where
87        U: UnsignedInteger;
88
89    /// Writes an unsigned value to the stream using the given
90    /// const number of bits.
91    ///
92    /// # Errors
93    ///
94    /// Passes along any I/O error from the underlying stream.
95    /// Returns an error if the value is too large
96    /// to fit the given number of bits.
97    /// A compile-time error occurs if the given number of bits
98    /// is larger than the output type.
99    #[inline]
100    fn write_unsigned_out<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
101    where
102        U: UnsignedInteger,
103    {
104        self.write_unsigned(BITS, value)
105    }
106
107    /// Writes a twos-complement signed value to the stream
108    /// with the given number of bits.
109    ///
110    /// # Errors
111    ///
112    /// Passes along any I/O error from the underlying stream.
113    /// Returns an error if the input type is too small
114    /// to hold the given number of bits.
115    /// Returns an error if the number of bits is 0,
116    /// since one bit is always needed for the sign.
117    /// Returns an error if the value is too large
118    /// to fit the given number of bits.
119    fn write_signed<S>(&mut self, bits: u32, value: S) -> io::Result<()>
120    where
121        S: SignedInteger;
122
123    /// Writes a twos-complement signed value to the stream
124    /// with the given const number of bits.
125    ///
126    /// # Errors
127    ///
128    /// Passes along any I/O error from the underlying stream.
129    /// Returns an error if the value is too large
130    /// to fit the given number of bits.
131    /// A compile-time error occurs if the number of bits is 0,
132    /// since one bit is always needed for the sign.
133    /// A compile-time error occurs if the given number of bits
134    /// is larger than the output type.
135    fn write_signed_out<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
136    where
137        S: SignedInteger,
138    {
139        self.write_signed(BITS, value)
140    }
141
142    /// Writes whole value to the stream whose size in bits
143    /// is equal to its type's size.
144    ///
145    /// # Errors
146    ///
147    /// Passes along any I/O error from the underlying stream.
148    fn write_from<V>(&mut self, value: V) -> io::Result<()>
149    where
150        V: Primitive;
151
152    /// Writes whole value to the stream whose size in bits
153    /// is equal to its type's size in an endianness that may
154    /// be different from the stream's endianness.
155    ///
156    /// # Errors
157    ///
158    /// Passes along any I/O error from the underlying stream.
159    fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
160    where
161        F: Endianness,
162        V: Primitive;
163
164    /// Pads the stream by writing 0 over the given number of bits.
165    ///
166    /// # Errors
167    ///
168    /// Passes along any I/O error from the underlying stream.
169    fn pad(&mut self, mut bits: u32) -> io::Result<()> {
170        loop {
171            match bits {
172                0 => break Ok(()),
173                bits @ 1..64 => break self.write(bits, 0u64),
174                _ => {
175                    self.write_out::<64, u64>(0)?;
176                    bits -= 64;
177                }
178            }
179        }
180    }
181
182    /// Writes the entirety of a byte buffer to the stream.
183    ///
184    /// # Errors
185    ///
186    /// Passes along any I/O error from the underlying stream.
187    ///
188    /// # Example
189    ///
190    /// ```
191    /// use std::io::Write;
192    /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
193    /// let mut writer = BitWriter::endian(Vec::new(), BigEndian);
194    /// writer.write_var(8, 0x66u8).unwrap();
195    /// writer.write_var(8, 0x6Fu8).unwrap();
196    /// writer.write_var(8, 0x6Fu8).unwrap();
197    /// writer.write_bytes(b"bar").unwrap();
198    /// assert_eq!(writer.into_writer(), b"foobar");
199    /// ```
200    #[inline]
201    fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
202        buf.iter()
203            .try_for_each(|b| self.write_unsigned_out::<8, _>(*b))
204    }
205
206    /// Writes `value` number of 1 bits to the stream
207    /// and then writes a 0 bit.  This field is variably-sized.
208    ///
209    /// # Errors
210    ///
211    /// Passes along any I/O error from the underyling stream.
212    fn write_unary0(&mut self, value: u32) -> io::Result<()>;
213
214    /// Writes `value` number of 0 bits to the stream
215    /// and then writes a 1 bit.  This field is variably-sized.
216    ///
217    /// # Errors
218    ///
219    /// Passes along any I/O error from the underyling stream.
220    fn write_unary1(&mut self, value: u32) -> io::Result<()>;
221
222    /// Builds and writes complex type
223    fn build<T: ToBitStream>(&mut self, build: &T) -> Result<(), T::Error>
224    where
225        Self: BitWrite,
226    {
227        build.to_writer(self)
228    }
229
230    /// Builds and writes complex type with context
231    fn build_with<'a, T: ToBitStreamWith<'a>>(
232        &mut self,
233        build: &T,
234        context: &T::Context,
235    ) -> Result<(), T::Error>
236    where
237        Self: BitWrite,
238    {
239        build.to_writer(self, context)
240    }
241
242    /// Returns true if the stream is aligned at a whole byte.
243    fn byte_aligned(&self) -> bool;
244
245    /// Pads the stream with 0 bits until it is aligned at a whole byte.
246    /// Does nothing if the stream is already aligned.
247    ///
248    /// # Errors
249    ///
250    /// Passes along any I/O error from the underyling stream.
251    ///
252    /// # Example
253    /// ```
254    /// use std::io::Write;
255    /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite};
256    /// let mut writer = BitWriter::endian(Vec::new(), BigEndian);
257    /// writer.write_var(1, 0u8).unwrap();
258    /// writer.byte_align().unwrap();
259    /// writer.write_var(8, 0xFFu8).unwrap();
260    /// assert_eq!(writer.into_writer(), [0x00, 0xFF]);
261    /// ```
262    fn byte_align(&mut self) -> io::Result<()> {
263        while !self.byte_aligned() {
264            self.write_bit(false)?;
265        }
266        Ok(())
267    }
268
269    /// Given a symbol, writes its representation to the output stream as bits.
270    /// Generates no output if the symbol isn't defined in the Huffman tree.
271    ///
272    /// # Errors
273    ///
274    /// Passes along any I/O error from the underlying stream.
275    ///
276    /// # Example
277    /// ```
278    /// use std::io::Write;
279    /// use oximedia_bitstream::{BigEndian, BitWriter, BitWrite2};
280    /// use oximedia_bitstream::define_huffman_tree;
281    /// define_huffman_tree!(TreeName : char = ['a', ['b', ['c', 'd']]]);
282    /// let mut writer = BitWriter::endian(Vec::new(), BigEndian);
283    /// writer.write_huffman::<TreeName>('b').unwrap();
284    /// writer.write_huffman::<TreeName>('c').unwrap();
285    /// writer.write_huffman::<TreeName>('d').unwrap();
286    /// assert_eq!(writer.into_writer(), [0b10_110_111]);
287    /// ```
288    fn write_huffman<T>(&mut self, value: T::Symbol) -> io::Result<()>
289    where
290        T: crate::huffman::ToBits,
291    {
292        T::to_bits(value, |b| self.write_bit(b))
293    }
294}
295
296impl<W: BitWrite> BitWrite2 for W {
297    #[inline]
298    fn write_bit(&mut self, bit: bool) -> io::Result<()> {
299        BitWrite::write_bit(self, bit)
300    }
301
302    #[inline]
303    fn write<I>(&mut self, bits: u32, value: I) -> io::Result<()>
304    where
305        I: Integer,
306    {
307        BitWrite::write_var(self, bits, value)
308    }
309
310    #[inline]
311    fn write_out<const BITS: u32, I>(&mut self, value: I) -> io::Result<()>
312    where
313        I: Integer,
314    {
315        BitWrite::write::<BITS, I>(self, value)
316    }
317
318    #[inline]
319    fn write_unsigned<U>(&mut self, bits: u32, value: U) -> io::Result<()>
320    where
321        U: UnsignedInteger,
322    {
323        BitWrite::write_unsigned_var::<U>(self, bits, value)
324    }
325
326    #[inline]
327    fn write_unsigned_out<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
328    where
329        U: UnsignedInteger,
330    {
331        BitWrite::write_unsigned::<BITS, U>(self, value)
332    }
333
334    #[inline]
335    fn write_signed<S>(&mut self, bits: u32, value: S) -> io::Result<()>
336    where
337        S: SignedInteger,
338    {
339        BitWrite::write_signed_var::<S>(self, bits, value)
340    }
341
342    #[inline]
343    fn write_signed_out<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
344    where
345        S: SignedInteger,
346    {
347        BitWrite::write_signed::<BITS, S>(self, value)
348    }
349
350    #[inline]
351    fn write_from<V>(&mut self, value: V) -> io::Result<()>
352    where
353        V: Primitive,
354    {
355        BitWrite::write_from(self, value)
356    }
357
358    #[inline]
359    fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
360    where
361        F: Endianness,
362        V: Primitive,
363    {
364        BitWrite::write_as_from::<F, V>(self, value)
365    }
366
367    #[inline]
368    fn pad(&mut self, bits: u32) -> io::Result<()> {
369        BitWrite::pad(self, bits)
370    }
371
372    #[inline]
373    fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
374        BitWrite::write_bytes(self, buf)
375    }
376
377    #[inline]
378    fn write_unary0(&mut self, value: u32) -> io::Result<()> {
379        BitWrite::write_unary::<0>(self, value)
380    }
381
382    #[inline]
383    fn write_unary1(&mut self, value: u32) -> io::Result<()> {
384        BitWrite::write_unary::<1>(self, value)
385    }
386
387    #[inline]
388    fn byte_aligned(&self) -> bool {
389        BitWrite::byte_aligned(self)
390    }
391
392    #[inline]
393    fn byte_align(&mut self) -> io::Result<()> {
394        BitWrite::byte_align(self)
395    }
396}
397
398impl<W: io::Write, E: Endianness> BitWrite for BitWriter<W, E> {
399    fn write_bit(&mut self, bit: bool) -> io::Result<()> {
400        match E::push_bit_flush(&mut self.value, &mut self.bits, bit) {
401            None => Ok(()),
402            Some(byte) => write_byte(&mut self.writer, byte),
403        }
404    }
405
406    #[inline(always)]
407    fn write_unsigned<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
408    where
409        U: UnsignedInteger,
410    {
411        let Self {
412            value: queue_value,
413            bits: queue_bits,
414            writer,
415            ..
416        } = self;
417
418        E::write_bits_checked(
419            writer,
420            queue_value,
421            queue_bits,
422            CheckedUnsigned::<BITS, U>::new_fixed::<BITS>(value)?,
423        )
424    }
425
426    fn write_unsigned_counted<const BITS: u32, U>(
427        &mut self,
428        count: BitCount<BITS>,
429        value: U,
430    ) -> io::Result<()>
431    where
432        U: UnsignedInteger,
433    {
434        let Self {
435            value: queue_value,
436            bits: queue_bits,
437            writer,
438            ..
439        } = self;
440
441        E::write_bits_checked(
442            writer,
443            queue_value,
444            queue_bits,
445            CheckedUnsigned::new(count, value)?,
446        )
447    }
448
449    #[inline(always)]
450    fn write_signed_counted<const BITS: u32, S>(
451        &mut self,
452        bits: impl TryInto<SignedBitCount<BITS>>,
453        value: S,
454    ) -> io::Result<()>
455    where
456        S: SignedInteger,
457    {
458        E::write_signed_bits_checked(
459            &mut self.writer,
460            &mut self.value,
461            &mut self.bits,
462            CheckedSigned::new(
463                bits.try_into().map_err(|_| {
464                    io::Error::new(
465                        io::ErrorKind::InvalidInput,
466                        "signed writes need at least 1 bit for sign",
467                    )
468                })?,
469                value,
470            )?,
471        )
472    }
473
474    #[inline]
475    fn write_signed<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
476    where
477        S: SignedInteger,
478    {
479        E::write_signed_bits_checked(
480            &mut self.writer,
481            &mut self.value,
482            &mut self.bits,
483            CheckedSigned::<BITS, _>::new_fixed::<BITS>(value)?,
484        )
485    }
486
487    #[inline]
488    fn write_from<V>(&mut self, value: V) -> io::Result<()>
489    where
490        V: Primitive,
491    {
492        E::write_bytes::<8, _>(
493            &mut self.writer,
494            &mut self.value,
495            self.bits,
496            E::primitive_to_bytes(value).as_ref(),
497        )
498    }
499
500    #[inline]
501    fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
502    where
503        F: Endianness,
504        V: Primitive,
505    {
506        F::write_bytes::<8, _>(
507            &mut self.writer,
508            &mut self.value,
509            self.bits,
510            F::primitive_to_bytes(value).as_ref(),
511        )
512    }
513
514    #[inline]
515    fn write_checked<C: Checkable>(&mut self, value: C) -> io::Result<()> {
516        value.write_endian::<E, _>(&mut self.writer, &mut self.value, &mut self.bits)
517    }
518
519    #[inline]
520    fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
521        E::write_bytes::<1024, _>(&mut self.writer, &mut self.value, self.bits, buf)
522    }
523
524    #[inline(always)]
525    fn byte_aligned(&self) -> bool {
526        self.bits == 0
527    }
528}