opus_pure/error.rs
1//! The crate's error type.
2
3use std::fmt;
4
5/// Anything that can go wrong encoding, decoding, or parsing an Opus stream.
6///
7/// The enum is `#[non_exhaustive]`, so match with a `_` arm: new variants are
8/// not a breaking change. The individual variants are not, deliberately —
9/// marking a tuple variant `#[non_exhaustive]` stops callers destructuring it
10/// at all, which would take away the message rather than protect it.
11/// [`BufferTooSmall`](Self::BufferTooSmall) is the exception, because a struct
12/// variant can be marked and still be matched with `..`.
13///
14/// Variants are grouped by who is at fault: [`Error::InvalidArgument`] and
15/// [`Error::BufferTooSmall`] mean the *caller* passed something the codec cannot
16/// honour, [`Error::InvalidPacket`] means the *bitstream* is malformed, and
17/// [`Error::Internal`] means a codec stage failed in a way that is not
18/// attributable to either.
19#[derive(Debug)]
20#[non_exhaustive]
21pub enum Error {
22 /// A configuration value is outside the range Opus allows — an unsupported
23 /// sample rate or channel count, a frame size no coding mode can carry, or a
24 /// mapping family that does not accept the requested layout.
25 InvalidArgument(&'static str),
26
27 /// The caller's output slice cannot hold the result. Both sizes are in the
28 /// unit of the call: bytes for `encode`, samples-per-channel for `decode`.
29 #[non_exhaustive]
30 BufferTooSmall {
31 /// What the operation needs.
32 needed: usize,
33 /// What the caller provided.
34 provided: usize,
35 },
36
37 /// The packet does not decode as Opus: a truncated or self-inconsistent
38 /// frame-length field, an impossible frame count, padding that runs off the
39 /// end, or a total duration above the 120 ms an Opus packet may carry.
40 InvalidPacket(&'static str),
41
42 /// The Ogg container is malformed: a missing capture pattern, an unsupported
43 /// page version, a CRC mismatch, or an `OpusHead`/`OpusTags` packet that does
44 /// not match RFC 7845.
45 InvalidStream(&'static str),
46
47 /// The underlying reader or writer failed.
48 Io(std::io::Error),
49
50 /// A codec stage failed. Reaching this from well-formed input is a bug in
51 /// this crate; the string names the stage.
52 Internal(&'static str),
53}
54
55impl Error {
56 pub(crate) fn buffer_too_small(needed: usize, provided: usize) -> Self {
57 Error::BufferTooSmall { needed, provided }
58 }
59}
60
61impl fmt::Display for Error {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 match self {
64 Error::InvalidArgument(what) => write!(f, "invalid argument: {what}"),
65 Error::BufferTooSmall { needed, provided } => {
66 write!(f, "buffer too small: need {needed}, got {provided}")
67 }
68 Error::InvalidPacket(what) => write!(f, "invalid packet: {what}"),
69 Error::InvalidStream(what) => write!(f, "invalid ogg stream: {what}"),
70 Error::Io(e) => write!(f, "io error: {e}"),
71 Error::Internal(what) => write!(f, "internal codec error: {what}"),
72 }
73 }
74}
75
76impl std::error::Error for Error {
77 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
78 match self {
79 Error::Io(e) => Some(e),
80 _ => None,
81 }
82 }
83}
84
85impl From<std::io::Error> for Error {
86 fn from(e: std::io::Error) -> Self {
87 Error::Io(e)
88 }
89}
90
91/// Shorthand for a codec result.
92pub type Result<T> = std::result::Result<T, Error>;