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}