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}