Skip to main content

symphonia_core/
errors.rs

1// Symphonia
2// Copyright (c) 2019-2026 The Project Symphonia Developers.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
8//! The `errors` module defines the common error type.
9
10use std::error;
11use std::fmt;
12use std::io;
13use std::result;
14
15/// `SeekErrorKind` is a list of generic reasons why a seek may fail.
16#[non_exhaustive]
17#[derive(Debug)]
18pub enum SeekErrorKind {
19    /// The stream is not seekable at all.
20    Unseekable,
21    /// The stream can only be seeked forward.
22    ForwardOnly,
23    /// The timestamp to seek to is out of range.
24    OutOfRange,
25    /// The track ID provided is invalid.
26    InvalidTrack,
27}
28
29impl SeekErrorKind {
30    fn as_str(&self) -> &'static str {
31        match *self {
32            SeekErrorKind::Unseekable => "stream is not seekable",
33            SeekErrorKind::ForwardOnly => "stream can only be seeked forward",
34            SeekErrorKind::OutOfRange => "requested seek timestamp is out-of-range for stream",
35            SeekErrorKind::InvalidTrack => "invalid track id",
36        }
37    }
38}
39
40/// `Error` provides an enumeration of all possible errors reported by Symphonia.
41#[non_exhaustive]
42#[derive(Debug)]
43pub enum Error {
44    /// An IO error occured while reading, writing, or seeking the stream.
45    IoError(std::io::Error),
46    /// The stream contained malformed data and could not be decoded or demuxed.
47    DecodeError(&'static str),
48    /// The stream could not be seeked.
49    SeekError(SeekErrorKind),
50    /// An unsupported container or codec feature was encounted.
51    Unsupported(&'static str),
52    /// A default or user-defined limit was reached while decoding or demuxing the stream. Limits
53    /// are used to prevent denial-of-service attacks from malicious streams.
54    LimitError(&'static str),
55    /// The demuxer or decoder needs to be reset before continuing.
56    ResetRequired,
57}
58
59impl fmt::Display for Error {
60    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61        match *self {
62            Error::IoError(ref err) => err.fmt(f),
63            Error::DecodeError(msg) => {
64                write!(f, "malformed stream: {msg}")
65            }
66            Error::SeekError(ref kind) => {
67                write!(f, "seek error: {}", kind.as_str())
68            }
69            Error::Unsupported(feature) => {
70                write!(f, "unsupported feature: {feature}")
71            }
72            Error::LimitError(constraint) => {
73                write!(f, "limit reached: {constraint}")
74            }
75            Error::ResetRequired => {
76                write!(f, "decoder needs to be reset")
77            }
78        }
79    }
80}
81
82impl std::error::Error for Error {
83    fn cause(&self) -> Option<&dyn error::Error> {
84        match *self {
85            Error::IoError(ref err) => Some(err),
86            Error::DecodeError(_) => None,
87            Error::SeekError(_) => None,
88            Error::Unsupported(_) => None,
89            Error::LimitError(_) => None,
90            Error::ResetRequired => None,
91        }
92    }
93}
94
95impl From<io::Error> for Error {
96    fn from(err: io::Error) -> Error {
97        Error::IoError(err)
98    }
99}
100
101pub type Result<T> = result::Result<T, Error>;
102
103/// Convenience function to create a decode error.
104pub fn decode_error<T>(desc: &'static str) -> Result<T> {
105    Err(Error::DecodeError(desc))
106}
107
108/// Convenience function to create a seek error.
109pub fn seek_error<T>(kind: SeekErrorKind) -> Result<T> {
110    Err(Error::SeekError(kind))
111}
112
113/// Convenience function to create an unsupport feature error.
114pub fn unsupported_error<T>(feature: &'static str) -> Result<T> {
115    Err(Error::Unsupported(feature))
116}
117
118/// Convenience function to create a limit error.
119pub fn limit_error<T>(constraint: &'static str) -> Result<T> {
120    Err(Error::LimitError(constraint))
121}
122
123/// Convenience function to create a reset required error.
124pub fn reset_error<T>() -> Result<T> {
125    Err(Error::ResetRequired)
126}