1use mecomp_storage::errors::Error;
2use serde::{Deserialize, Serialize};
3use thiserror::Error;
4
5#[derive(Error, Debug)]
7#[cfg(feature = "rpc")]
8pub enum UdpError {
9 #[error("IO error: {0}")]
10 IO(#[from] std::io::Error),
11 #[error("Ciborium deserialization error: {0}")]
12 CiboriumDeserialization(#[from] ciborium::de::Error<std::io::Error>),
13 #[error("Ciborium serialization error: {0}")]
14 CiboriumSerialization(#[from] ciborium::ser::Error<std::io::Error>),
15}
16
17#[derive(Error, Debug)]
19pub enum DirectoryError {
20 #[error("Unable to find the config directory for mecomp.")]
21 Config,
22 #[error("Unable to find the data directory for mecomp.")]
23 Data,
24}
25
26#[derive(Error, Debug)]
28pub enum LibraryError {
29 #[error("Database error: {0}")]
30 Database(#[from] Error),
31 #[error("IO error: {0}")]
32 IO(#[from] std::io::Error),
33 #[error("Decoder error: {0}")]
34 #[cfg(feature = "audio")]
35 Decoder(#[from] rodio::decoder::DecoderError),
36 #[error("UdpError: {0}")]
37 #[cfg(feature = "rpc")]
38 Udp(#[from] UdpError),
39}
40
41#[derive(Error, Debug, Deserialize, Serialize, PartialEq, Eq)]
42pub enum SerializableLibraryError {
43 #[error("Database error: {0}")]
44 Database(String),
45 #[error("IO error: {0}")]
46 IO(String),
47 #[error("Decoder error: {0}")]
48 Decoder(String),
49 #[error("Library Rescan already in progress.")]
50 RescanInProgress,
51 #[error("Library Analysis already in progress.")]
52 AnalysisInProgress,
53 #[error("Collection Reclustering already in progress.")]
54 ReclusterInProgress,
55 #[error("UdpError: {0}")]
56 #[cfg(feature = "rpc")]
57 Udp(String),
58}
59
60impl From<Error> for SerializableLibraryError {
61 fn from(e: Error) -> Self {
62 Self::Database(e.to_string())
63 }
64}
65
66impl From<std::io::Error> for SerializableLibraryError {
67 fn from(e: std::io::Error) -> Self {
68 Self::IO(e.to_string())
69 }
70}
71
72#[cfg(feature = "audio")]
73impl From<rodio::decoder::DecoderError> for SerializableLibraryError {
74 fn from(e: rodio::decoder::DecoderError) -> Self {
75 Self::Decoder(e.to_string())
76 }
77}
78
79#[cfg(feature = "rpc")]
80impl From<UdpError> for SerializableLibraryError {
81 fn from(e: UdpError) -> Self {
82 Self::Udp(e.to_string())
83 }
84}
85
86impl From<LibraryError> for SerializableLibraryError {
87 fn from(e: LibraryError) -> Self {
88 match e {
89 LibraryError::Database(e) => Self::Database(e.to_string()),
90 LibraryError::IO(e) => Self::IO(e.to_string()),
91 #[cfg(feature = "audio")]
92 LibraryError::Decoder(e) => Self::Decoder(e.to_string()),
93 #[cfg(feature = "rpc")]
94 LibraryError::Udp(e) => Self::Udp(e.to_string()),
95 }
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use pretty_assertions::assert_str_eq;
103 use rstest::rstest;
104
105 #[rstest]
106 #[case(
107 LibraryError::from(Error::NoId),
108 "Database error: Item is missing an Id."
109 )]
110 #[case(
111 LibraryError::from(std::io::Error::new(std::io::ErrorKind::Other, "test")),
112 "IO error: test"
113 )]
114 #[case(
115 LibraryError::from(rodio::decoder::DecoderError::DecodeError("test")),
116 "Decoder error: test"
117 )]
118 fn test_serializable_library_error(#[case] input: LibraryError, #[case] expected: String) {
119 let actual = SerializableLibraryError::from(input).to_string();
120 assert_str_eq!(actual, expected);
121 }
122
123 #[rstest]
124 #[case(Error::NoId, LibraryError::Database(Error::NoId).into())]
125 #[case(std::io::Error::new(std::io::ErrorKind::Other, "test"), LibraryError::IO(std::io::Error::new(std::io::ErrorKind::Other, "test")).into())]
126 #[case(rodio::decoder::DecoderError::DecodeError("test"), LibraryError::Decoder(rodio::decoder::DecoderError::DecodeError("test")).into())]
127 fn test_serializable_library_error_from<T: Into<SerializableLibraryError>>(
128 #[case] from: T,
129 #[case] to: SerializableLibraryError,
130 ) {
131 let actual = from.into();
132 assert_eq!(actual, to);
133 }
134}