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/.
78//! The `errors` module defines the common error type.
910use std::error;
11use std::fmt;
12use std::io;
13use std::result;
1415/// `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.
19Unseekable,
20/// The stream can only be seeked forward.
21ForwardOnly,
22/// The timestamp to seek to is out of range.
23OutOfRange,
24/// The track ID provided is invalid.
25InvalidTrack,
26}
2728impl SeekErrorKind {
29fn as_str(&self) -> &'static str {
30match *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}
3839/// `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.
43IoError(std::io::Error),
44/// The stream contained malformed data and could not be decoded or demuxed.
45DecodeError(&'static str),
46/// The stream could not be seeked.
47SeekError(SeekErrorKind),
48/// An unsupported container or codec feature was encounted.
49Unsupported(&'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.
52LimitError(&'static str),
53/// The demuxer or decoder needs to be reset before continuing.
54ResetRequired,
55}
5657impl fmt::Display for Error {
58fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59match *self {
60 Error::IoError(ref err) => err.fmt(f),
61 Error::DecodeError(msg) => {
62write!(f, "malformed stream: {}", msg)
63 }
64 Error::SeekError(ref kind) => {
65write!(f, "seek error: {}", kind.as_str())
66 }
67 Error::Unsupported(feature) => {
68write!(f, "unsupported feature: {}", feature)
69 }
70 Error::LimitError(constraint) => {
71write!(f, "limit reached: {}", constraint)
72 }
73 Error::ResetRequired => {
74write!(f, "decoder needs to be reset")
75 }
76 }
77 }
78}
7980impl std::error::Error for Error {
81fn cause(&self) -> Option<&dyn error::Error> {
82match *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}
9293impl From<io::Error> for Error {
94fn from(err: io::Error) -> Error {
95 Error::IoError(err)
96 }
97}
9899pub type Result<T> = result::Result<T, Error>;
100101/// Convenience function to create a decode error.
102pub fn decode_error<T>(desc: &'static str) -> Result<T> {
103Err(Error::DecodeError(desc))
104}
105106/// Convenience function to create a seek error.
107pub fn seek_error<T>(kind: SeekErrorKind) -> Result<T> {
108Err(Error::SeekError(kind))
109}
110111/// Convenience function to create an unsupport feature error.
112pub fn unsupported_error<T>(feature: &'static str) -> Result<T> {
113Err(Error::Unsupported(feature))
114}
115116/// Convenience function to create a limit error.
117pub fn limit_error<T>(constraint: &'static str) -> Result<T> {
118Err(Error::LimitError(constraint))
119}
120121/// Convenience function to create a reset required error.
122pub fn reset_error<T>() -> Result<T> {
123Err(Error::ResetRequired)
124}
125126/// Convenience function to create an end-of-stream error.
127pub fn end_of_stream_error<T>() -> Result<T> {
128Err(Error::IoError(io::Error::new(io::ErrorKind::UnexpectedEof, "end of stream")))
129}