Skip to main content

oximedia_bitstream/read/
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 parsing traits (`FromBitStream` / `FromByteStream` and
8//! their context-carrying variants).
9
10use super::{BitRead, ByteRead};
11
12/// Implemented by complex types that don't require any additional context
13/// to parse themselves from a reader.  Analogous to [`std::str::FromStr`].
14///
15/// # Example
16/// ```
17/// use std::io::Read;
18/// use oximedia_bitstream::{BigEndian, BitRead, BitReader, FromBitStream};
19///
20/// #[derive(Debug, PartialEq, Eq)]
21/// struct BlockHeader {
22///     last_block: bool,
23///     block_type: u8,
24///     block_size: u32,
25/// }
26///
27/// impl FromBitStream for BlockHeader {
28///     type Error = std::io::Error;
29///
30///     fn from_reader<R: BitRead + ?Sized>(r: &mut R) -> std::io::Result<Self> {
31///         Ok(Self {
32///             last_block: r.read_bit()?,
33///             block_type: r.read::<7, _>()?,
34///             block_size: r.read::<24, _>()?,
35///         })
36///     }
37/// }
38///
39/// let mut reader = BitReader::endian(b"\x04\x00\x00\x7A".as_slice(), BigEndian);
40/// assert_eq!(
41///     reader.parse::<BlockHeader>().unwrap(),
42///     BlockHeader { last_block: false, block_type: 4, block_size: 122 }
43/// );
44/// ```
45pub trait FromBitStream {
46    /// Error generated during parsing, such as `io::Error`
47    type Error;
48
49    /// Parse Self from reader
50    fn from_reader<R: BitRead + ?Sized>(r: &mut R) -> Result<Self, Self::Error>
51    where
52        Self: Sized;
53}
54
55/// Implemented by complex types that require some immutable context
56/// to parse themselves from a reader.
57///
58/// # Example
59/// ```
60/// use std::io::Read;
61/// use oximedia_bitstream::{BigEndian, BitRead, BitReader, FromBitStreamWith};
62///
63/// #[derive(Default)]
64/// struct Streaminfo {
65///     minimum_block_size: u16,
66///     maximum_block_size: u16,
67///     minimum_frame_size: u32,
68///     maximum_frame_size: u32,
69///     sample_rate: u32,
70///     channels: u8,
71///     bits_per_sample: u8,
72///     total_samples: u64,
73///     md5: [u8; 16],
74/// }
75///
76/// #[derive(Debug, PartialEq, Eq)]
77/// struct FrameHeader {
78///     variable_block_size: bool,
79///     block_size: u32,
80///     sample_rate: u32,
81///     channel_assignment: u8,
82///     sample_size: u8,
83///     frame_number: u64,
84///     crc8: u8,
85/// }
86///
87/// impl FromBitStreamWith<'_> for FrameHeader {
88///     type Context = Streaminfo;
89///
90///     type Error = FrameHeaderError;
91///
92///     fn from_reader<R: BitRead + ?Sized>(
93///         r: &mut R,
94///         streaminfo: &Streaminfo,
95///     ) -> Result<Self, Self::Error> {
96///         if r.read::<14, u16>()? != 0b11111111111110 {
97///             return Err(FrameHeaderError::InvalidSync);
98///         }
99///
100///         if r.read_bit()? != false {
101///             return Err(FrameHeaderError::InvalidReservedBit);
102///         }
103///
104///         let variable_block_size = r.read_bit()?;
105///
106///         let block_size_bits = r.read::<4, u8>()?;
107///
108///         let sample_rate_bits = r.read::<4, u8>()?;
109///
110///         let channel_assignment = r.read::<4, u8>()?;
111///
112///         let sample_size = match r.read::<3, u8>()? {
113///             0b000 => streaminfo.bits_per_sample,
114///             0b001 => 8,
115///             0b010 => 12,
116///             0b011 => return Err(FrameHeaderError::InvalidSampleSize),
117///             0b100 => 16,
118///             0b101 => 20,
119///             0b110 => 24,
120///             0b111 => 32,
121///             _ => unreachable!(),
122///         };
123///
124///         if r.read_bit()? != false {
125///             return Err(FrameHeaderError::InvalidReservedBit);
126///         }
127///
128///         let frame_number = read_utf8(r)?;
129///
130///         Ok(FrameHeader {
131///             variable_block_size,
132///             block_size: match block_size_bits {
133///                 0b0000 => return Err(FrameHeaderError::InvalidBlockSize),
134///                 0b0001 => 192,
135///                 n @ 0b010..=0b0101 => 576 * (1 << (n - 2)),
136///                 0b0110 => r.read::<8, u32>()? + 1,
137///                 0b0111 => r.read::<16, u32>()? + 1,
138///                 n @ 0b1000..=0b1111 => 256 * (1 << (n - 8)),
139///                 _ => unreachable!(),
140///             },
141///             sample_rate: match sample_rate_bits {
142///                 0b0000 => streaminfo.sample_rate,
143///                 0b0001 => 88200,
144///                 0b0010 => 176400,
145///                 0b0011 => 192000,
146///                 0b0100 => 8000,
147///                 0b0101 => 16000,
148///                 0b0110 => 22050,
149///                 0b0111 => 24000,
150///                 0b1000 => 32000,
151///                 0b1001 => 44100,
152///                 0b1010 => 48000,
153///                 0b1011 => 96000,
154///                 0b1100 => r.read::<8, u32>()? * 1000,
155///                 0b1101 => r.read::<16, u32>()?,
156///                 0b1110 => r.read::<16, u32>()? * 10,
157///                 0b1111 => return Err(FrameHeaderError::InvalidSampleRate),
158///                 _ => unreachable!(),
159///             },
160///             channel_assignment,
161///             sample_size,
162///             frame_number,
163///             crc8: r.read::<8, _>()?
164///         })
165///     }
166/// }
167///
168/// #[derive(Debug)]
169/// enum FrameHeaderError {
170///     Io(std::io::Error),
171///     InvalidSync,
172///     InvalidReservedBit,
173///     InvalidSampleSize,
174///     InvalidBlockSize,
175///     InvalidSampleRate,
176/// }
177///
178/// impl From<std::io::Error> for FrameHeaderError {
179///     fn from(err: std::io::Error) -> Self {
180///         Self::Io(err)
181///     }
182/// }
183///
184/// fn read_utf8<R: BitRead + ?Sized>(r: &mut R) -> Result<u64, std::io::Error> {
185///     r.read::<8, _>()  // left unimplimented in this example
186/// }
187///
188/// let mut reader = BitReader::endian(b"\xFF\xF8\xC9\x18\x00\xC2".as_slice(), BigEndian);
189/// assert_eq!(
190///     reader.parse_with::<FrameHeader>(&Streaminfo::default()).unwrap(),
191///     FrameHeader {
192///         variable_block_size: false,
193///         block_size: 4096,
194///         sample_rate: 44100,
195///         channel_assignment: 1,
196///         sample_size: 16,
197///         frame_number: 0,
198///         crc8: 0xC2,
199///     }
200/// );
201/// ```
202///
203/// # Example with lifetime-contrained `Context`
204///
205/// In some cases, the `Context` can depend on a reference to another `struct`.
206///
207/// ```
208/// use std::io::Read;
209/// use oximedia_bitstream::{BigEndian, BitRead, BitReader, FromBitStreamWith};
210///
211/// #[derive(Default)]
212/// struct ModeParameters {
213///     size_len: u8,
214///     index_len: u8,
215///     index_delta_len: u8,
216///     // ...
217/// }
218///
219/// struct AuHeaderParseContext<'a> {
220///     params: &'a ModeParameters,
221///     base_index: Option<u32>,
222/// }
223///
224/// #[derive(Debug, PartialEq, Eq)]
225/// struct AuHeader {
226///     size: u32,
227///     index: u32,
228///     // ...
229/// }
230///
231/// impl<'a> FromBitStreamWith<'a> for AuHeader {
232///     type Context = AuHeaderParseContext<'a>;
233///
234///     type Error = AuHeaderError;
235///
236///     fn from_reader<R: BitRead + ?Sized>(
237///         r: &mut R,
238///         ctx: &AuHeaderParseContext<'a>,
239///     ) -> Result<Self, Self::Error> {
240///         let size = r.read_var::<u32>(ctx.params.size_len as u32)?;
241///         let index = match ctx.base_index {
242///             None => r.read_var::<u32>(ctx.params.index_len as u32)?,
243///             Some(base_index) => {
244///                 base_index
245///                 + 1
246///                 + r.read_var::<u32>(ctx.params.index_delta_len as u32)?
247///             }
248///         };
249///
250///         Ok(AuHeader {
251///             size,
252///             index,
253///             // ...
254///         })
255///     }
256/// }
257///
258/// #[derive(Debug)]
259/// enum AuHeaderError {
260///     Io(std::io::Error),
261/// }
262///
263/// impl From<std::io::Error> for AuHeaderError {
264///     fn from(err: std::io::Error) -> Self {
265///         Self::Io(err)
266///     }
267/// }
268///
269/// let mut reader = BitReader::endian(b"\xFF\xEA\xFF\x10".as_slice(), BigEndian);
270///
271/// let mode_params = ModeParameters {
272///     size_len: 10,
273///     index_len: 6,
274///     index_delta_len: 2,
275///     // ...
276/// };
277///
278/// let mut ctx = AuHeaderParseContext {
279///     params: &mode_params,
280///     base_index: None,
281/// };
282///
283/// let header1 = reader.parse_with::<AuHeader>(&ctx).unwrap();
284/// assert_eq!(
285///     header1,
286///     AuHeader {
287///         size: 1023,
288///         index: 42,
289///     }
290/// );
291///
292/// ctx.base_index = Some(header1.index);
293///
294/// assert_eq!(
295///     reader.parse_with::<AuHeader>(&ctx).unwrap(),
296///     AuHeader {
297///         size: 1020,
298///         index: 44,
299///     }
300/// );
301/// ```
302pub trait FromBitStreamWith<'a> {
303    /// Some context to use when parsing
304    type Context: 'a;
305
306    /// Error generated during parsing, such as `io::Error`
307    type Error;
308
309    /// Parse Self from reader with the given context
310    fn from_reader<R: BitRead + ?Sized>(
311        r: &mut R,
312        context: &Self::Context,
313    ) -> Result<Self, Self::Error>
314    where
315        Self: Sized;
316}
317
318/// Implemented by complex types that consume some immutable context
319/// to parse themselves from a reader.
320///
321/// Like [`FromBitStreamWith`], but consumes its context
322/// rather than taking a shared reference to it.
323pub trait FromBitStreamUsing {
324    /// Some context to consume when parsing
325    type Context;
326
327    /// Error generated during parsing, such as `io::Error`
328    type Error;
329
330    /// Parse Self from reader with the given context
331    fn from_reader<R: BitRead + ?Sized>(
332        r: &mut R,
333        context: Self::Context,
334    ) -> Result<Self, Self::Error>
335    where
336        Self: Sized;
337}
338
339/// Implemented by complex types that don't require any additional context
340/// to parse themselves from a reader.  Analagous to `FromStr`.
341pub trait FromByteStream {
342    /// Error generated during parsing, such as `io::Error`
343    type Error;
344
345    /// Parse Self from reader
346    fn from_reader<R: ByteRead + ?Sized>(r: &mut R) -> Result<Self, Self::Error>
347    where
348        Self: Sized;
349}
350
351/// Implemented by complex types that require some additional context
352/// to parse themselves from a reader.  Analagous to `FromStr`.
353pub trait FromByteStreamWith<'a> {
354    /// Some context to use when parsing
355    type Context: 'a;
356
357    /// Error generated during parsing, such as `io::Error`
358    type Error;
359
360    /// Parse Self from reader
361    fn from_reader<R: ByteRead + ?Sized>(
362        r: &mut R,
363        context: &Self::Context,
364    ) -> Result<Self, Self::Error>
365    where
366        Self: Sized;
367}
368
369/// Implemented by complex types that consume some additional context
370/// to parse themselves from a reader.
371///
372/// Like [`FromByteStreamWith`], but consumes the context.
373pub trait FromByteStreamUsing {
374    /// Some context to use when parsing
375    type Context;
376
377    /// Error generated during parsing, such as `io::Error`
378    type Error;
379
380    /// Parse Self from reader
381    fn from_reader<R: ByteRead + ?Sized>(
382        r: &mut R,
383        context: Self::Context,
384    ) -> Result<Self, Self::Error>
385    where
386        Self: Sized;
387}