Skip to main content

oximedia_bitstream/write/
bit_writer.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//! `BitWriter` — the concrete partial-byte accumulator.
8
9use std::io;
10
11use super::{BitWrite, ByteWriter, Endianness, PhantomData};
12
13/// For writing bit values to an underlying stream in a given endianness.
14///
15/// Because this only writes whole bytes to the underlying stream,
16/// it is important that output is byte-aligned before the bitstream
17/// writer's lifetime ends.
18/// **Partial bytes will be lost** if the writer is disposed of
19/// before they can be written.
20pub struct BitWriter<W: io::Write, E: Endianness> {
21    // our underlying writer
22    pub(crate) writer: W,
23    // our partial byte
24    pub(crate) value: u8,
25    // the number of bits in our partial byte
26    pub(crate) bits: u32,
27    // a container for our endianness
28    phantom: PhantomData<E>,
29}
30
31impl<W: io::Write, E: Endianness> BitWriter<W, E> {
32    /// Wraps a BitWriter around something that implements `Write`
33    pub fn new(writer: W) -> BitWriter<W, E> {
34        BitWriter {
35            writer,
36            value: 0,
37            bits: 0,
38            phantom: PhantomData,
39        }
40    }
41
42    /// Wraps a BitWriter around something that implements `Write`
43    /// with the given endianness.
44    pub fn endian(writer: W, _endian: E) -> BitWriter<W, E> {
45        BitWriter {
46            writer,
47            value: 0,
48            bits: 0,
49            phantom: PhantomData,
50        }
51    }
52
53    /// Unwraps internal writer and disposes of BitWriter.
54    ///
55    /// # Warning
56    ///
57    /// Any unwritten partial bits are discarded.
58    #[inline]
59    pub fn into_writer(self) -> W {
60        self.writer
61    }
62
63    /// If stream is byte-aligned, provides mutable reference
64    /// to internal writer.  Otherwise returns `None`
65    #[inline]
66    pub fn writer(&mut self) -> Option<&mut W> {
67        if BitWrite::byte_aligned(self) {
68            Some(&mut self.writer)
69        } else {
70            None
71        }
72    }
73
74    /// Returns byte-aligned mutable reference to internal writer.
75    ///
76    /// Bytes aligns stream if it is not already aligned.
77    ///
78    /// # Errors
79    ///
80    /// Passes along any I/O error from the underlying stream.
81    #[inline]
82    pub fn aligned_writer(&mut self) -> io::Result<&mut W> {
83        BitWrite::byte_align(self)?;
84        Ok(&mut self.writer)
85    }
86
87    /// Converts `BitWriter` to `ByteWriter` in the same endianness.
88    ///
89    /// # Warning
90    ///
91    /// Any written partial bits are discarded.
92    #[inline]
93    pub fn into_bytewriter(self) -> ByteWriter<W, E> {
94        ByteWriter::new(self.into_writer())
95    }
96
97    /// If stream is byte-aligned, provides temporary `ByteWriter`
98    /// in the same endianness.  Otherwise returns `None`
99    ///
100    /// # Warning
101    ///
102    /// Any unwritten bits left over when `ByteWriter` is dropped are lost.
103    #[inline]
104    pub fn bytewriter(&mut self) -> Option<ByteWriter<&mut W, E>> {
105        self.writer().map(ByteWriter::new)
106    }
107
108    /// Flushes output stream to disk, if necessary.
109    /// Any partial bytes are not flushed.
110    ///
111    /// # Errors
112    ///
113    /// Passes along any errors from the underlying stream.
114    #[inline(always)]
115    pub fn flush(&mut self) -> io::Result<()> {
116        self.writer.flush()
117    }
118}