skua_voice/input/adapters/cached/
error.rs

1use crate::{error::JsonError, input::AudioStreamError};
2use audiopus::error::Error as OpusError;
3use std::{
4    error::Error as StdError,
5    fmt::{Display, Formatter, Result as FmtResult},
6};
7use streamcatcher::CatcherError;
8use symphonia_core::errors::Error as SymphError;
9use tokio::task::JoinError;
10
11/// Errors encountered using a [`Memory`] cached source.
12///
13/// [`Memory`]: super::Memory
14#[derive(Debug)]
15pub enum Error {
16    /// The audio stream could not be created.
17    Create(AudioStreamError),
18    /// The audio stream failed to be created due to a panic in `spawn_blocking`.
19    CreatePanicked,
20    /// Streamcatcher's configuration was illegal, and the cache could not be created.
21    Streamcatcher(CatcherError),
22    /// The input stream had already been read (i.e., `Parsed`) and so the whole stream
23    /// could not be used.
24    StreamNotAtStart,
25}
26
27impl Display for Error {
28    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
29        match self {
30            Self::Create(c) => f.write_fmt(format_args!("failed to create audio stream: {c}")),
31            Self::CreatePanicked => f.write_str("sync thread panicked while creating stream"),
32            Self::Streamcatcher(s) =>
33                f.write_fmt(format_args!("illegal streamcatcher config: {s}")),
34            Self::StreamNotAtStart =>
35                f.write_str("stream cannot have been pre-read/parsed, missing headers"),
36        }
37    }
38}
39
40impl StdError for Error {}
41
42impl From<AudioStreamError> for Error {
43    fn from(val: AudioStreamError) -> Self {
44        Self::Create(val)
45    }
46}
47
48impl From<CatcherError> for Error {
49    fn from(val: CatcherError) -> Self {
50        Self::Streamcatcher(val)
51    }
52}
53
54impl From<JoinError> for Error {
55    fn from(_val: JoinError) -> Self {
56        Self::CreatePanicked
57    }
58}
59
60/// Errors encountered using a [`Compressed`] or [`Decompressed`] cached source.
61///
62/// [`Compressed`]: super::Compressed
63/// [`Decompressed`]: super::Decompressed
64#[derive(Debug)]
65pub enum CodecCacheError {
66    /// The audio stream could not be created.
67    Create(AudioStreamError),
68    /// Symphonia failed to parse the container or decode the default stream.
69    Parse(SymphError),
70    /// The Opus encoder could not be created.
71    Opus(OpusError),
72    /// The file's metadata could not be converted to JSON.
73    MetadataEncoding(JsonError),
74    /// The input's metadata was too large after conversion to JSON to fit in a DCA file.
75    MetadataTooLarge,
76    /// The audio stream failed to be created due to a panic in `spawn_blocking`.
77    CreatePanicked,
78    /// The audio stream's channel count could not be determined.
79    UnknownChannelCount,
80    /// Streamcatcher's configuration was illegal, and the cache could not be created.
81    Streamcatcher(CatcherError),
82    /// The input stream had already been read (i.e., `Parsed`) and so the whole stream
83    /// could not be used.
84    StreamNotAtStart,
85}
86
87impl Display for CodecCacheError {
88    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
89        match self {
90            Self::Create(c) => f.write_fmt(format_args!("failed to create audio stream: {c}")),
91            Self::Parse(p) => f.write_fmt(format_args!("failed to parse audio format: {p}")),
92            Self::Opus(o) => f.write_fmt(format_args!("failed to create Opus encoder: {o}")),
93            Self::MetadataEncoding(m) => f.write_fmt(format_args!(
94                "failed to convert track metadata to JSON: {m}"
95            )),
96            Self::MetadataTooLarge => f.write_str("track metadata was too large, >= 32kiB"),
97            Self::CreatePanicked => f.write_str("sync thread panicked while creating stream"),
98            Self::UnknownChannelCount =>
99                f.write_str("audio stream's channel count could not be determined"),
100            Self::Streamcatcher(s) =>
101                f.write_fmt(format_args!("illegal streamcatcher config: {s}")),
102            Self::StreamNotAtStart =>
103                f.write_str("stream cannot have been pre-read/parsed, missing headers"),
104        }
105    }
106}
107
108impl StdError for CodecCacheError {}
109
110impl From<AudioStreamError> for CodecCacheError {
111    fn from(val: AudioStreamError) -> Self {
112        Self::Create(val)
113    }
114}
115
116impl From<CatcherError> for CodecCacheError {
117    fn from(val: CatcherError) -> Self {
118        Self::Streamcatcher(val)
119    }
120}
121
122impl From<JoinError> for CodecCacheError {
123    fn from(_val: JoinError) -> Self {
124        Self::CreatePanicked
125    }
126}
127
128impl From<JsonError> for CodecCacheError {
129    fn from(val: JsonError) -> Self {
130        Self::MetadataEncoding(val)
131    }
132}
133
134impl From<OpusError> for CodecCacheError {
135    fn from(val: OpusError) -> Self {
136        Self::Opus(val)
137    }
138}
139
140impl From<SymphError> for CodecCacheError {
141    fn from(val: SymphError) -> Self {
142        Self::Parse(val)
143    }
144}