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}