oggopus_embedded/
opus.rs

1/*
2 * Copyright (c) 2025 Tomi Leppänen
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5//! Opus parsing code.
6
7use core::num::NonZeroUsize;
8use nom::{bytes::complete::tag, error::ErrorKind, number, Parser};
9
10/// Error values for formatting.
11#[derive(Debug, PartialEq)]
12#[doc(hidden)]
13#[non_exhaustive]
14pub enum ErrorValues {
15    ZeroStreamCount,
16    BadNumberOfChannels(u8, u8),
17    InvalidChannelIndex(u8),
18    TotalStreamCountExceeds(u16),
19    StreamCountsMismatch(u8, u8),
20    BadTableLength(usize, u8),
21    TableTooBig(usize, u8),
22}
23
24/// Errors from parsing opus data.
25#[derive(Debug, PartialEq)]
26pub enum OpusError {
27    /// Parsing error from nom library.
28    ParsingError(ErrorKind),
29    /// Stream ended abruptly.
30    EndOfStreamError(Option<NonZeroUsize>),
31    /// Stream is not a valid opus stream, e.g. it has a value outside specifications.
32    InvalidStream(ErrorValues),
33    /// Stream is not supported. Enabled features may affect this.
34    UnsupportedStream(&'static str),
35    /// Stream is not an opus stream but something else.
36    NotOpusStream,
37}
38
39impl core::fmt::Display for OpusError {
40    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
41        use OpusError::*;
42        match self {
43            ParsingError(kind) => f.write_fmt(format_args!(
44                "parsing error with Opus: {}",
45                kind.description()
46            ))?,
47            EndOfStreamError(Some(size)) => f.write_fmt(format_args!(
48                "Opus stream ended abruptly with {} more bytes needed",
49                size
50            ))?,
51            EndOfStreamError(None) => f.write_fmt(format_args!("Opus stream ended abruptly"))?,
52            InvalidStream(issue) => match issue {
53                ErrorValues::ZeroStreamCount => {
54                    f.write_str("stream count cannot be 0")?
55                }
56                ErrorValues::BadNumberOfChannels(family, channels) => f.write_fmt(format_args!(
57                    "bad number of channels for family {}: {}",
58                    family, channels
59                ))?,
60                ErrorValues::InvalidChannelIndex(index) => f.write_fmt(format_args!(
61                    "invalid channel index in channel mapping table: {}",
62                    index
63                ))?,
64                ErrorValues::TotalStreamCountExceeds(total) => f.write_fmt(format_args!(
65                    "total stream count cannot be more than 255: {}",
66                    total
67                ))?,
68                ErrorValues::StreamCountsMismatch(coupled_count, stream_count) => f.write_fmt(format_args!(
69                    "coupled stream count ({}) cannot be larger than stream count ({})",
70                    coupled_count, stream_count
71                ))?,
72                ErrorValues::BadTableLength(length, channels) => f.write_fmt(format_args!(
73                    "channel mapping table length does not match the number of channels ({}): {}",
74                    channels, length
75                ))?,
76                ErrorValues::TableTooBig(length, max_size) => f.write_fmt(format_args!(
77                    "channel mapping table does not fit to reserved space ({}), it is {} bytes long",
78                    max_size, length,
79                ))?,
80            },
81            UnsupportedStream(issue) => {
82                f.write_fmt(format_args!("unsupported stream: {}", issue))?
83            }
84            NotOpusStream => f.write_str("this is not an Opus stream")?,
85        };
86        Ok(())
87    }
88}
89
90impl core::error::Error for OpusError {
91    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
92        None
93    }
94}
95
96impl<'data> From<nom::Err<(&'data [u8], ErrorKind)>> for OpusError {
97    fn from(error: nom::Err<(&'data [u8], ErrorKind)>) -> OpusError {
98        use OpusError::*;
99        match error {
100            nom::Err::Failure((_, kind)) => ParsingError(kind),
101            nom::Err::Error((_, kind)) => ParsingError(kind),
102            nom::Err::Incomplete(nom::Needed::Size(size)) => EndOfStreamError(Some(size)),
103            nom::Err::Incomplete(nom::Needed::Unknown) => EndOfStreamError(None),
104        }
105    }
106}
107
108/// Result for opus parsing errors.
109pub type Result<'data, O> = core::result::Result<O, OpusError>;
110
111/// Channel mapping of opus stream.
112#[derive(Debug, PartialEq)]
113#[non_exhaustive]
114pub enum ChannelMapping {
115    /**
116     * Family 0 channel mapping.
117     *
118     * Supports mono and stereo audio.
119     */
120    Family0 {
121        /// The number of channels, which can be 1 (mono) or 2 (stereo).
122        channels: u8,
123    },
124    /**
125     * Family 1 channel mapping.
126     *
127     * Vorbis channel order.
128     */
129    Family1 {
130        /// The number of channels, which can be between 1 and 8.
131        channels: u8,
132        /// Channel mapping table.
133        table: ChannelMappingTable<8>,
134    },
135    #[cfg(feature = "family255")]
136    /**
137     * Family 255 channel mapping.
138     *
139     * Channels are unidentified.
140     *
141     * Only available if family255 feature has been enabled.
142     */
143    Family255 {
144        /// The number of channels.
145        channels: u8,
146        /// Channel mapping table.
147        table: ChannelMappingTable<255>,
148    },
149    #[cfg(feature = "family255")]
150    /**
151     * Reserved channel mapping value was used in the stream.
152     *
153     * Such mapping may be a future extension to the container format.
154     *
155     * Only available if family255 feature has been enabled.
156     */
157    Reserved {
158        /// The number of channels.
159        channels: u8,
160        /// Channel mapping table.
161        table: ChannelMappingTable<255>,
162    },
163}
164
165impl ChannelMapping {
166    /// Get channel count.
167    pub fn get_channel_count(&self) -> u8 {
168        use ChannelMapping::*;
169        match self {
170            Family0 { channels } => *channels,
171            Family1 { channels, .. } => *channels,
172            #[cfg(feature = "family255")]
173            Family255 { channels, .. } => *channels,
174            #[cfg(feature = "family255")]
175            Reserved { channels, .. } => *channels,
176        }
177    }
178
179    /// Get stream count.
180    pub fn get_stream_count(&self) -> u8 {
181        use ChannelMapping::*;
182        match self {
183            Family0 { .. } => 1,
184            Family1 { table, .. } => table.stream_count,
185            #[cfg(feature = "family255")]
186            Family255 { table, .. } => table.stream_count,
187            #[cfg(feature = "family255")]
188            Reserved { table, .. } => table.stream_count,
189        }
190    }
191
192    /// Get coupled stream count.
193    pub fn get_coupled_stream_count(&self) -> u8 {
194        use ChannelMapping::*;
195        match self {
196            Family0 { channels } => *channels - 1,
197            Family1 { table, .. } => table.coupled_count,
198            #[cfg(feature = "family255")]
199            Family255 { table, .. } => table.coupled_count,
200            #[cfg(feature = "family255")]
201            Reserved { table, .. } => table.coupled_count,
202        }
203    }
204
205    /**
206     * Get channel mapping for given channel index.
207     *
208     * Returns [`None`] for invalid channel indexes.
209     */
210    pub fn get_mapping(&self, channel: u8) -> Option<Mapping> {
211        use ChannelMapping::*;
212        let (speaker_location, index, coupled_count) = match self {
213            Family0 { channels } => {
214                let speaker_location = match (*channels, channel) {
215                    (1, 0) => SpeakerLocation::Mono,
216                    (2, 0) => SpeakerLocation::Left,
217                    (2, 1) => SpeakerLocation::Right,
218                    _ => return None,
219                };
220                Some((Some(speaker_location), channel, *channels - 1))
221            }
222            Family1 { channels, table } => {
223                let speaker_location = match (*channels, channel) {
224                    (1, 0) => SpeakerLocation::Mono,
225                    (2..=8, 0) => SpeakerLocation::Left,
226                    (2, 1) | (3, 2) | (4, 1) | (5..=8, 2) => SpeakerLocation::Right,
227                    (3, 1) | (5..=8, 1) => SpeakerLocation::Center,
228                    (4, 2) | (5..=6, 3) | (8, 5) => SpeakerLocation::RearLeft,
229                    (4, 3) | (5..=6, 4) | (8, 6) => SpeakerLocation::RearRight,
230                    (6, 5) | (7, 6) | (8, 7) => SpeakerLocation::LFE,
231                    (7..=8, 3) => SpeakerLocation::SideLeft,
232                    (7..=8, 4) => SpeakerLocation::SideRight,
233                    (7, 5) => SpeakerLocation::RearCenter,
234                    _ => return None,
235                };
236                let ChannelMappingTable {
237                    coupled_count,
238                    mapping,
239                    ..
240                } = &table;
241                let index = mapping[usize::from(channel)];
242                Some((Some(speaker_location), index, *coupled_count))
243            }
244            #[cfg(feature = "family255")]
245            Family255 { channels, table } | Reserved { channels, table } => {
246                if channel >= *channels {
247                    None
248                } else {
249                    let ChannelMappingTable {
250                        coupled_count,
251                        mapping,
252                        ..
253                    } = &table;
254                    let index = mapping[usize::from(channel)];
255                    Some((None, index, *coupled_count))
256                }
257            }
258        }?;
259        if index == 255 {
260            Some(Mapping {
261                stream: None,
262                speaker_location,
263            })
264        } else {
265            let stream = if index < 2 * coupled_count {
266                if index % 2 == 0 {
267                    (index / 2, DecodedChannel::Left)
268                } else {
269                    (index / 2, DecodedChannel::Right)
270                }
271            } else {
272                (index - coupled_count, DecodedChannel::Mono)
273            };
274            let stream = Some(stream);
275            Some(Mapping {
276                stream,
277                speaker_location,
278            })
279        }
280    }
281}
282
283/// Speaker location in audio setup.
284#[derive(Clone, Copy, Debug, PartialEq)]
285#[non_exhaustive]
286pub enum SpeakerLocation {
287    /// Mono speaker.
288    Mono,
289    /// Left channel of a stereo stream. Front left in surround setup.
290    Left,
291    /// Right channel of a stereo stream. Front right in surround setup.
292    Right,
293    /// Center channel in linear surround setup. Front center in surround setup.
294    Center,
295    /// Rear left channel of a surround setup.
296    RearLeft,
297    /// Rear right channel of a surround setup.
298    RearRight,
299    /// Rear center channel of a surround setup.
300    RearCenter,
301    /// Side left channel of a surround setup.
302    SideLeft,
303    /// Side right channel of a surround setup.
304    SideRight,
305    /// Low-frequency effects channel of a surround setup.
306    LFE,
307}
308
309/// Decoded opus channel to use for this audio channel.
310#[derive(Clone, Copy, Debug, PartialEq)]
311pub enum DecodedChannel {
312    /// The opus stream will be mono audio.
313    Mono,
314    /// Use the first decoded channel of the stereo stream.
315    Left,
316    /// Use the second decoded channel of the stereo stream.
317    Right,
318}
319
320/// Channel mapping for an audio channel.
321#[derive(Debug, PartialEq)]
322pub struct Mapping {
323    /// Stream index and decoded opus stream channel to use. Silent channel if [`None`].
324    pub stream: Option<(u8, DecodedChannel)>,
325    /// Speaker location for this index if available.
326    pub speaker_location: Option<SpeakerLocation>,
327}
328
329/// Channel mapping table.
330#[derive(Debug, PartialEq)]
331pub struct ChannelMappingTable<const MAX_CHANNELS: usize> {
332    /// The number of total streams encoded in each Ogg packet.
333    stream_count: u8,
334    /// The number of stereo decoders needed.
335    coupled_count: u8,
336    /// Channel mapping data.
337    mapping: [u8; MAX_CHANNELS],
338}
339
340impl<const MAX_CHANNELS: usize> ChannelMappingTable<MAX_CHANNELS> {
341    fn parse(input: &[u8], channels: u8) -> Result<ChannelMappingTable<MAX_CHANNELS>> {
342        use OpusError::*;
343        let (input, stream_count) = number::u8().parse(input)?;
344        let (input, coupled_count) = number::u8().parse(input)?;
345        let total_stream_count = stream_count.checked_add(coupled_count).ok_or_else(|| {
346            let total = stream_count as u16 + coupled_count as u16;
347            InvalidStream(ErrorValues::TotalStreamCountExceeds(total))
348        })?;
349        if stream_count == 0 {
350            Err(InvalidStream(ErrorValues::ZeroStreamCount))
351        } else if coupled_count > stream_count {
352            Err(InvalidStream(ErrorValues::StreamCountsMismatch(
353                coupled_count,
354                stream_count,
355            )))
356        } else if input.len() != channels.into() {
357            Err(InvalidStream(ErrorValues::BadTableLength(
358                input.len(),
359                channels,
360            )))
361        } else if input.len() > MAX_CHANNELS {
362            Err(InvalidStream(ErrorValues::TableTooBig(
363                input.len(),
364                MAX_CHANNELS as u8, // At most 255
365            )))
366        } else {
367            let mut mapping = [0; MAX_CHANNELS];
368            for (i, &v) in input.iter().enumerate() {
369                if v >= total_stream_count && v != 255 {
370                    return Err(InvalidStream(ErrorValues::InvalidChannelIndex(v)));
371                }
372                mapping[i] = v;
373            }
374            Ok(ChannelMappingTable {
375                stream_count,
376                coupled_count,
377                mapping,
378            })
379        }
380    }
381}
382
383/// Opus header data.
384#[derive(Debug, PartialEq)]
385pub struct OpusHeader {
386    /// Opus version.
387    pub version: u8,
388    /// Channel mapping.
389    pub channels: ChannelMapping,
390    /// The number of samples to skip in the beginning of the stream.
391    pub pre_skip: u16,
392    /// Sample rate used for the original audio.
393    pub sample_rate: u32,
394    /// Output gain.
395    pub output_gain: u16,
396}
397
398impl OpusHeader {
399    /**
400     * Parse opus header from input data.
401     *
402     * May return [`UnsupportedStream`][`OpusError::UnsupportedStream`] if family255 feature has
403     * not been enabled and such stream is encountered.
404     */
405    pub fn parse(input: &[u8]) -> Result<Self> {
406        use OpusError::*;
407        let (input, _) = tag(b"OpusHead".as_slice())(input)
408            .map_err(|_: nom::Err<(&[u8], ErrorKind)>| NotOpusStream)?;
409        let (input, version) = number::u8().parse(input)?;
410        let (input, channels) = number::u8().parse(input)?;
411        let (input, pre_skip) = number::le_u16().parse(input)?;
412        let (input, sample_rate) = number::le_u32().parse(input)?;
413        let (input, output_gain) = number::le_u16().parse(input)?;
414        let (channel_mapping_table, channel_mapping_family) = number::u8().parse(input)?;
415        let channels = match channel_mapping_family {
416            0 => match channels {
417                1..=2 => ChannelMapping::Family0 { channels },
418                _ => return Err(InvalidStream(ErrorValues::BadNumberOfChannels(0, channels))),
419            },
420            1 => match channels {
421                1..=8 => ChannelMapping::Family1 {
422                    channels,
423                    table: ChannelMappingTable::parse(channel_mapping_table, channels)?,
424                },
425                _ => return Err(InvalidStream(ErrorValues::BadNumberOfChannels(1, channels))),
426            },
427            #[cfg(feature = "family255")]
428            255 => ChannelMapping::Family255 {
429                channels,
430                table: ChannelMappingTable::parse(channel_mapping_table, channels)?,
431            },
432            #[cfg(feature = "family255")]
433            _ => ChannelMapping::Reserved {
434                channels,
435                table: ChannelMappingTable::parse(channel_mapping_table, channels)?,
436            },
437            #[cfg(not(feature = "family255"))]
438            _ => {
439                return Err(UnsupportedStream(
440                    "family 255 channel mapping is not supported",
441                ))
442            }
443        };
444        Ok(Self {
445            version,
446            channels,
447            pre_skip,
448            sample_rate,
449            output_gain,
450        })
451    }
452}
453
454#[cfg(test)]
455mod test {
456    use super::*;
457    use core::error::Error;
458
459    #[test]
460    fn parse_header() {
461        let data = include_bytes!("test/opus.data");
462        let header = OpusHeader::parse(data).unwrap();
463        assert_eq!(header.version, 1);
464        if let ChannelMapping::Family0 { channels } = header.channels {
465            assert_eq!(channels, 1);
466        } else {
467            panic!("Channel mapping family must be 0");
468        }
469        assert_eq!(header.pre_skip, 312);
470        assert_eq!(header.sample_rate, 8_000);
471        assert_eq!(header.output_gain, 0);
472    }
473
474    #[test]
475    fn family_0_mono() {
476        let channels = ChannelMapping::Family0 { channels: 1 };
477        assert_eq!(channels.get_channel_count(), 1);
478        assert_eq!(channels.get_stream_count(), 1);
479        assert_eq!(channels.get_coupled_stream_count(), 0);
480        let mapping = channels.get_mapping(0).unwrap();
481        assert_eq!(mapping.stream, Some((0, DecodedChannel::Mono)));
482        assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Mono));
483        for index in 1..=255 {
484            assert_eq!(channels.get_mapping(index), None);
485        }
486    }
487
488    #[test]
489    fn family_0_stereo() {
490        let channels = ChannelMapping::Family0 { channels: 2 };
491        assert_eq!(channels.get_channel_count(), 2);
492        assert_eq!(channels.get_stream_count(), 1);
493        assert_eq!(channels.get_coupled_stream_count(), 1);
494        let mapping = channels.get_mapping(0).unwrap();
495        assert_eq!(mapping.stream, Some((0, DecodedChannel::Left)));
496        assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Left));
497        let mapping = channels.get_mapping(1).unwrap();
498        assert_eq!(mapping.stream, Some((0, DecodedChannel::Right)));
499        assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Right));
500        for index in 2..=255 {
501            assert_eq!(channels.get_mapping(index), None);
502        }
503    }
504
505    #[test]
506    fn family_1_stereo() {
507        let channels = ChannelMapping::Family1 {
508            channels: 2,
509            table: ChannelMappingTable::parse(&[1, 1, 0, 1], 2).unwrap(),
510        };
511        assert_eq!(channels.get_channel_count(), 2);
512        assert_eq!(channels.get_stream_count(), 1);
513        assert_eq!(channels.get_coupled_stream_count(), 1);
514        let mapping = channels.get_mapping(0).unwrap();
515        assert_eq!(mapping.stream, Some((0, DecodedChannel::Left)));
516        assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Left));
517        let mapping = channels.get_mapping(1).unwrap();
518        assert_eq!(mapping.stream, Some((0, DecodedChannel::Right)));
519        assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Right));
520        for index in 2..=255 {
521            assert_eq!(channels.get_mapping(index), None);
522        }
523    }
524
525    #[test]
526    fn family_1_surround_5_1() {
527        let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
528        let channels = ChannelMapping::Family1 {
529            channels: 6,
530            table: ChannelMappingTable::parse(&data, 6).unwrap(),
531        };
532        assert_eq!(channels.get_channel_count(), 6);
533        assert_eq!(channels.get_stream_count(), 4);
534        assert_eq!(channels.get_coupled_stream_count(), 2);
535        let mappings = [
536            (0, DecodedChannel::Left, SpeakerLocation::Left),
537            (2, DecodedChannel::Mono, SpeakerLocation::Center),
538            (0, DecodedChannel::Right, SpeakerLocation::Right),
539            (1, DecodedChannel::Left, SpeakerLocation::RearLeft),
540            (1, DecodedChannel::Right, SpeakerLocation::RearRight),
541            (3, DecodedChannel::Mono, SpeakerLocation::LFE),
542        ];
543        for (index, (stream, channel, location)) in mappings.iter().enumerate() {
544            let mapping = channels.get_mapping(index as u8).unwrap();
545            assert_eq!(mapping.stream, Some((*stream, *channel)));
546            assert_eq!(mapping.speaker_location, Some(*location));
547        }
548        for index in 6..=255 {
549            assert_eq!(channels.get_mapping(index), None);
550        }
551    }
552
553    #[test]
554    #[cfg(feature = "family255")]
555    fn family_255() {
556        let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
557        let channels = ChannelMapping::Family255 {
558            channels: 6,
559            table: ChannelMappingTable::parse(&data, 6).unwrap(),
560        };
561        assert_eq!(channels.get_channel_count(), 6);
562        assert_eq!(channels.get_stream_count(), 4);
563        assert_eq!(channels.get_coupled_stream_count(), 2);
564        let mappings = [
565            (0, DecodedChannel::Left),
566            (2, DecodedChannel::Mono),
567            (0, DecodedChannel::Right),
568            (1, DecodedChannel::Left),
569            (1, DecodedChannel::Right),
570            (3, DecodedChannel::Mono),
571        ];
572        for (index, (stream, channel)) in mappings.iter().enumerate() {
573            let mapping = channels.get_mapping(index as u8).unwrap();
574            assert_eq!(mapping.stream, Some((*stream, *channel)));
575            assert_eq!(mapping.speaker_location, None);
576        }
577        for index in 6..=255 {
578            assert_eq!(channels.get_mapping(index), None);
579        }
580    }
581
582    #[test]
583    #[cfg(feature = "family255")]
584    fn family_reserved() {
585        let data: [u8; 0x06] = [0x02, 0x01, 0x01, 0x00, 0x02, 0xFF];
586        let channels = ChannelMapping::Reserved {
587            channels: 4,
588            table: ChannelMappingTable::parse(&data, 4).unwrap(),
589        };
590        assert_eq!(channels.get_channel_count(), 4);
591        assert_eq!(channels.get_stream_count(), 2);
592        assert_eq!(channels.get_coupled_stream_count(), 1);
593        let mappings = [
594            Some((0, DecodedChannel::Right)),
595            Some((0, DecodedChannel::Left)),
596            Some((1, DecodedChannel::Mono)),
597            None,
598        ];
599        for (index, stream) in mappings.iter().enumerate() {
600            let mapping = channels.get_mapping(index as u8).unwrap();
601            assert_eq!(mapping.stream, *stream);
602            assert_eq!(mapping.speaker_location, None);
603        }
604        for index in 4..=255 {
605            assert_eq!(channels.get_mapping(index), None);
606        }
607    }
608
609    #[test]
610    fn invalid_stream_count() {
611        let data: [u8; 0x08] = [0x04, 0x05, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
612        let result = ChannelMappingTable::<255>::parse(&data, 6);
613        assert_eq!(
614            result,
615            Err(OpusError::InvalidStream(ErrorValues::StreamCountsMismatch(
616                5, 4
617            )))
618        );
619        assert_eq!(
620            result.unwrap_err().to_string(),
621            "coupled stream count (5) cannot be larger than stream count (4)"
622        );
623    }
624
625    #[test]
626    fn zero_stream_count() {
627        let data: [u8; 0x08] = [0x00, 0x01, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
628        let result = ChannelMappingTable::<255>::parse(&data, 6);
629        assert_eq!(
630            result,
631            Err(OpusError::InvalidStream(ErrorValues::ZeroStreamCount))
632        );
633        assert_eq!(result.unwrap_err().to_string(), "stream count cannot be 0");
634    }
635
636    #[test]
637    fn invalid_table_length() {
638        let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
639        let result = ChannelMappingTable::<255>::parse(&data, 2);
640        assert_eq!(
641            result,
642            Err(OpusError::InvalidStream(ErrorValues::BadTableLength(6, 2)))
643        );
644        assert_eq!(
645            result.unwrap_err().to_string(),
646            "channel mapping table length does not match the number of channels (2): 6"
647        );
648    }
649
650    #[test]
651    fn too_long_table() {
652        let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
653        let result = ChannelMappingTable::<5>::parse(&data, 6);
654        assert_eq!(
655            result,
656            Err(OpusError::InvalidStream(ErrorValues::TableTooBig(6, 5)))
657        );
658        assert_eq!(
659            result.unwrap_err().to_string(),
660            "channel mapping table does not fit to reserved space (5), it is 6 bytes long"
661        );
662    }
663
664    #[test]
665    fn invalid_channel_index() {
666        let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0xFF, 0x0A, 0x02, 0x03, 0x05];
667        let result = ChannelMappingTable::<255>::parse(&data, 6);
668        assert_eq!(
669            result,
670            Err(OpusError::InvalidStream(ErrorValues::InvalidChannelIndex(
671                0x0A
672            )))
673        );
674        assert_eq!(
675            result.unwrap_err().to_string(),
676            "invalid channel index in channel mapping table: 10"
677        );
678    }
679
680    #[test]
681    fn too_many_streams() {
682        let data: [u8; 0x02] = [0x90, 0x90];
683        let result = ChannelMappingTable::<5>::parse(&data, 6);
684        assert_eq!(
685            result,
686            Err(OpusError::InvalidStream(
687                ErrorValues::TotalStreamCountExceeds(0x90 * 2)
688            ))
689        );
690        assert_eq!(
691            result.unwrap_err().to_string(),
692            "total stream count cannot be more than 255: 288"
693        );
694    }
695
696    #[test]
697    fn corrupted_stream() {
698        let mut data = Vec::from(include_bytes!("test/opus.data"));
699        data[2] = 10;
700        let result = OpusHeader::parse(&data);
701        assert_eq!(result, Err(OpusError::NotOpusStream));
702        assert!(result.unwrap_err().source().is_none());
703    }
704
705    #[test]
706    fn incomplete_header() {
707        let data = include_bytes!("test/opus.data");
708        let result = OpusHeader::parse(&data[..10]);
709        assert_eq!(
710            result,
711            Err(OpusError::EndOfStreamError(Some(2.try_into().unwrap())))
712        );
713        assert!(result.unwrap_err().source().is_none());
714    }
715
716    #[test]
717    fn invalid_channels() {
718        let mut data = Vec::from(include_bytes!("test/opus.data"));
719        data[9] = 0;
720        let result = OpusHeader::parse(&data);
721        assert_eq!(
722            result,
723            Err(OpusError::InvalidStream(ErrorValues::BadNumberOfChannels(
724                0, 0
725            )))
726        );
727        assert!(result.unwrap_err().source().is_none());
728        data[0x12] = 1;
729        let result = OpusHeader::parse(&data);
730        assert_eq!(
731            result,
732            Err(OpusError::InvalidStream(ErrorValues::BadNumberOfChannels(
733                1, 0
734            )))
735        );
736        assert!(result.unwrap_err().source().is_none());
737    }
738}