symphonia_core/
errors.rs

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