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 #[inline]
62 fn from(e: Error) -> Self {
63 Self::Database(e.to_string())
64 }
65}
66
67impl From<std::io::Error> for SerializableLibraryError {
68 #[inline]
69 fn from(e: std::io::Error) -> Self {
70 Self::IO(e.to_string())
71 }
72}
73
74#[cfg(feature = "audio")]
75impl From<rodio::decoder::DecoderError> for SerializableLibraryError {
76 #[inline]
77 fn from(e: rodio::decoder::DecoderError) -> Self {
78 Self::Decoder(e.to_string())
79 }
80}
81
82#[cfg(feature = "rpc")]
83impl From<UdpError> for SerializableLibraryError {
84 #[inline]
85 fn from(e: UdpError) -> Self {
86 Self::Udp(e.to_string())
87 }
88}
89
90impl From<LibraryError> for SerializableLibraryError {
91 #[inline]
92 fn from(e: LibraryError) -> Self {
93 match e {
94 LibraryError::Database(e) => Self::Database(e.to_string()),
95 LibraryError::IO(e) => Self::IO(e.to_string()),
96 #[cfg(feature = "audio")]
97 LibraryError::Decoder(e) => Self::Decoder(e.to_string()),
98 #[cfg(feature = "rpc")]
99 LibraryError::Udp(e) => Self::Udp(e.to_string()),
100 }
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107 use pretty_assertions::assert_str_eq;
108 use rstest::rstest;
109
110 #[rstest]
111 #[case(
112 LibraryError::from(Error::NoId),
113 "Database error: Item is missing an Id."
114 )]
115 #[case(
116 LibraryError::from(std::io::Error::new(std::io::ErrorKind::Other, "test")),
117 "IO error: test"
118 )]
119 #[case(
120 LibraryError::from(rodio::decoder::DecoderError::DecodeError("test")),
121 "Decoder error: test"
122 )]
123 fn test_serializable_library_error(#[case] input: LibraryError, #[case] expected: String) {
124 let actual = SerializableLibraryError::from(input).to_string();
125 assert_str_eq!(actual, expected);
126 }
127
128 #[rstest]
129 #[case(Error::NoId, LibraryError::Database(Error::NoId).into())]
130 #[case(std::io::Error::new(std::io::ErrorKind::Other, "test"), LibraryError::IO(std::io::Error::new(std::io::ErrorKind::Other, "test")).into())]
131 #[case(rodio::decoder::DecoderError::DecodeError("test"), LibraryError::Decoder(rodio::decoder::DecoderError::DecodeError("test")).into())]
132 fn test_serializable_library_error_from<T: Into<SerializableLibraryError>>(
133 #[case] from: T,
134 #[case] to: SerializableLibraryError,
135 ) {
136 let actual = from.into();
137 assert_eq!(actual, to);
138 }
139}