Skip to main content

oximedia_bitstream/write/
stream_traits.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//! Declarative streaming traits (`ToBitStream` / `ToByteStream` and their
8//! context-carrying variants).
9
10use core::convert::TryInto;
11use std::io;
12
13use super::{BitWrite, BitsWritten, ByteWrite, Counter, Endianness, Overflowed, Primitive};
14
15/// Implemented by complex types that don't require any additional context
16/// to build themselves to a writer
17///
18/// # Example
19/// ```
20/// use std::io::Read;
21/// use oximedia_bitstream::{BigEndian, BitWrite, BitWriter, ToBitStream};
22///
23/// #[derive(Debug, PartialEq, Eq)]
24/// struct BlockHeader {
25///     last_block: bool,
26///     block_type: u8,
27///     block_size: u32,
28/// }
29///
30/// impl ToBitStream for BlockHeader {
31///     type Error = std::io::Error;
32///
33///     fn to_writer<W: BitWrite + ?Sized>(&self, w: &mut W) -> std::io::Result<()> {
34///         w.write_bit(self.last_block)?;
35///         w.write::<7, _>(self.block_type)?;
36///         w.write::<24, _>(self.block_size)
37///     }
38/// }
39///
40/// let mut data = Vec::new();
41/// let mut writer = BitWriter::endian(&mut data, BigEndian);
42/// writer.build(&BlockHeader { last_block: false, block_type: 4, block_size: 122 }).unwrap();
43/// assert_eq!(data, b"\x04\x00\x00\x7A");
44/// ```
45pub trait ToBitStream {
46    /// Error generated during building, such as `io::Error`
47    type Error;
48
49    /// Generate self to writer
50    fn to_writer<W: BitWrite + ?Sized>(&self, w: &mut W) -> Result<(), Self::Error>
51    where
52        Self: Sized;
53
54    /// Returns length of self in bits, if possible
55    fn bits<C: Counter>(&self) -> Result<C, Self::Error>
56    where
57        Self: Sized,
58    {
59        let mut c: BitsWritten<C> = BitsWritten::default();
60        self.to_writer(&mut c)?;
61        Ok(c.into_written())
62    }
63
64    /// Returns total length of self, if possible
65    #[deprecated(since = "4.0.0", note = "use of bits() is preferred")]
66    #[inline]
67    fn bits_len<C: Counter, E: Endianness>(&self) -> Result<C, Self::Error>
68    where
69        Self: Sized,
70    {
71        self.bits()
72    }
73}
74
75/// Implemented by complex types that require additional context
76/// to build themselves to a writer
77pub trait ToBitStreamWith<'a> {
78    /// Some context to use when writing
79    type Context: 'a;
80
81    /// Error generated during building, such as `io::Error`
82    type Error;
83
84    /// Generate self to writer
85    fn to_writer<W: BitWrite + ?Sized>(
86        &self,
87        w: &mut W,
88        context: &Self::Context,
89    ) -> Result<(), Self::Error>
90    where
91        Self: Sized;
92
93    /// Returns length of self in bits, if possible
94    fn bits<C: Counter>(&self, context: &Self::Context) -> Result<C, Self::Error>
95    where
96        Self: Sized,
97    {
98        let mut c: BitsWritten<C> = BitsWritten::default();
99        self.to_writer(&mut c, context)?;
100        Ok(c.into_written())
101    }
102
103    /// Returns total length of self, if possible
104    #[deprecated(since = "4.0.0", note = "use of len() is preferred")]
105    #[inline]
106    fn bits_len<C: Counter, E: Endianness>(&self, context: &Self::Context) -> Result<C, Self::Error>
107    where
108        Self: Sized,
109    {
110        self.bits(context)
111    }
112}
113
114/// Implemented by complex types that consume additional context
115/// to build themselves to a writer
116pub trait ToBitStreamUsing {
117    /// Some context to consume when writing
118    type Context;
119
120    /// Error generated during building, such as `io::Error`
121    type Error;
122
123    /// Generate self to writer
124    fn to_writer<W: BitWrite + ?Sized>(
125        &self,
126        w: &mut W,
127        context: Self::Context,
128    ) -> Result<(), Self::Error>
129    where
130        Self: Sized;
131
132    /// Returns length of self in bits, if possible
133    fn bits<C: Counter>(&self, context: Self::Context) -> Result<C, Self::Error>
134    where
135        Self: Sized,
136    {
137        let mut c: BitsWritten<C> = BitsWritten::default();
138        self.to_writer(&mut c, context)?;
139        Ok(c.into_written())
140    }
141}
142
143/// Implemented by complex types that don't require any additional context
144/// to build themselves to a writer
145pub trait ToByteStream {
146    /// Error generated during building, such as `io::Error`
147    type Error;
148
149    /// Generate self to writer
150    fn to_writer<W: ByteWrite + ?Sized>(&self, w: &mut W) -> Result<(), Self::Error>
151    where
152        Self: Sized;
153
154    /// Returns length of self in bytes, if possible
155    fn bytes<C: Counter>(&self) -> Result<C, Self::Error>
156    where
157        Self: Sized,
158    {
159        let mut counter = ByteCount::default();
160        self.to_writer(&mut counter)?;
161        Ok(counter.writer.count)
162    }
163}
164
165/// Implemented by complex types that require additional context
166/// to build themselves to a writer
167pub trait ToByteStreamWith<'a> {
168    /// Some context to use when writing
169    type Context: 'a;
170
171    /// Error generated during building, such as `io::Error`
172    type Error;
173
174    /// Generate self to writer
175    fn to_writer<W: ByteWrite + ?Sized>(
176        &self,
177        w: &mut W,
178        context: &Self::Context,
179    ) -> Result<(), Self::Error>
180    where
181        Self: Sized;
182
183    /// Returns length of self in bytes, if possible
184    fn bytes<C: Counter>(&self, context: &Self::Context) -> Result<C, Self::Error>
185    where
186        Self: Sized,
187    {
188        let mut counter = ByteCount::default();
189        self.to_writer(&mut counter, context)?;
190        Ok(counter.writer.count)
191    }
192}
193
194/// Implemented by complex types that consume additional context
195/// to build themselves to a writer
196pub trait ToByteStreamUsing {
197    /// Some context to consume when writing
198    type Context;
199
200    /// Error generated during building, such as `io::Error`
201    type Error;
202
203    /// Generate self to writer
204    fn to_writer<W: ByteWrite + ?Sized>(
205        &self,
206        w: &mut W,
207        context: Self::Context,
208    ) -> Result<(), Self::Error>
209    where
210        Self: Sized;
211
212    /// Returns length of self in bytes, if possible
213    fn bytes<C: Counter>(&self, context: Self::Context) -> Result<C, Self::Error>
214    where
215        Self: Sized,
216    {
217        let mut counter = ByteCount::default();
218        self.to_writer(&mut counter, context)?;
219        Ok(counter.writer.count)
220    }
221}
222
223#[derive(Default)]
224struct ByteCounterWriter<C> {
225    count: C,
226}
227
228impl<C: Counter> io::Write for ByteCounterWriter<C> {
229    #[inline]
230    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
231        self.count
232            .checked_add_assign(buf.len().try_into().map_err(|_| Overflowed)?)?;
233
234        Ok(buf.len())
235    }
236
237    #[inline]
238    fn flush(&mut self) -> io::Result<()> {
239        // nothing to do
240        Ok(())
241    }
242}
243
244#[derive(Default)]
245struct ByteCount<C> {
246    writer: ByteCounterWriter<C>,
247}
248
249impl<C: Counter> ByteWrite for ByteCount<C> {
250    fn write<V: Primitive>(&mut self, _value: V) -> io::Result<()> {
251        self.writer.count.checked_add_assign(
252            V::buffer()
253                .as_ref()
254                .len()
255                .try_into()
256                .map_err(|_| Overflowed)?,
257        )?;
258
259        Ok(())
260    }
261
262    fn write_as<F: Endianness, V: Primitive>(&mut self, _value: V) -> io::Result<()> {
263        self.writer.count.checked_add_assign(
264            V::buffer()
265                .as_ref()
266                .len()
267                .try_into()
268                .map_err(|_| Overflowed)?,
269        )?;
270
271        Ok(())
272    }
273
274    fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
275        self.writer
276            .count
277            .checked_add_assign(buf.len().try_into().map_err(|_| Overflowed)?)?;
278
279        Ok(())
280    }
281
282    fn pad(&mut self, bytes: u32) -> io::Result<()> {
283        self.writer
284            .count
285            .checked_add_assign(bytes.try_into().map_err(|_| Overflowed)?)?;
286
287        Ok(())
288    }
289
290    fn writer_ref(&mut self) -> &mut dyn io::Write {
291        &mut self.writer
292    }
293}