1use std::borrow::Cow;
4
5use serde::{Deserialize, Serialize};
6
7mod kind;
8
9pub use kind::ErrorKind;
10
11#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
13pub enum Error {
14 InvalidField {
15 field: String,
16 have: String,
17 expected: String,
18 },
19 Io {
20 kind: ErrorKind,
21 message: String,
22 },
23}
24
25impl Error {
26 pub fn invalid_field<'f, 'h, 'e, F, H, E>(field: F, have: H, expected: E) -> Self
28 where
29 F: Into<Cow<'f, str>>,
30 H: Into<Cow<'h, str>>,
31 E: Into<Cow<'e, str>>,
32 {
33 Self::InvalidField {
34 field: F::into(field).into(),
35 have: H::into(have).into(),
36 expected: E::into(expected).into(),
37 }
38 }
39
40 pub fn std_io(err: std::io::Error) -> Self {
42 Self::Io {
43 kind: ErrorKind::from_io(err.kind()),
44 message: format!("{err}"),
45 }
46 }
47
48 pub fn io<'m, M: Into<Cow<'m, str>>>(kind: ErrorKind, message: M) -> Self {
50 Self::Io {
51 kind,
52 message: M::into(message).into(),
53 }
54 }
55
56 pub fn io_other<'m, M: Into<Cow<'m, str>>>(message: M) -> Self {
58 Self::Io {
59 kind: ErrorKind::Other,
60 message: M::into(message).into(),
61 }
62 }
63
64 pub fn io_filename<'m, M: Into<Cow<'m, str>>>(message: M) -> Self {
66 Self::Io {
67 kind: ErrorKind::InvalidFilename,
68 message: M::into(message).into(),
69 }
70 }
71}
72
73impl std::fmt::Display for Error {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 match self {
76 Self::InvalidField {
77 field,
78 have,
79 expected,
80 } => write!(f, "invalid {field}, have: {have}, expected: {expected}"),
81 Self::Io { kind, message } => write!(f, "I/O error, kind: {kind}, message: {message}"),
82 }
83 }
84}
85
86impl From<std::io::Error> for Error {
87 fn from(err: std::io::Error) -> Self {
88 Self::std_io(err)
89 }
90}
91
92impl From<Error> for std::io::Error {
93 fn from(err: Error) -> Self {
94 match err {
95 Error::Io { kind, message } => Self::new(kind.as_io(), message),
96 err => Self::other(err),
97 }
98 }
99}
100
101impl From<uuid::Error> for Error {
102 fn from(err: uuid::Error) -> Self {
103 Self::std_io(std::io::Error::other(err))
104 }
105}
106
107impl From<reqwest::Error> for Error {
108 fn from(err: reqwest::Error) -> Self {
109 Self::std_io(std::io::Error::other(err))
110 }
111}
112
113impl From<serde_json::Error> for Error {
114 fn from(err: serde_json::Error) -> Self {
115 Self::std_io(std::io::Error::other(err))
116 }
117}
118
119impl From<std::str::Utf8Error> for Error {
120 fn from(err: std::str::Utf8Error) -> Self {
121 Self::std_io(std::io::Error::other(err))
122 }
123}
124
125impl From<std::num::ParseIntError> for Error {
126 fn from(err: std::num::ParseIntError) -> Self {
127 Self::io(ErrorKind::Other, format!("{err}"))
128 }
129}
130
131impl From<reqwest::header::ToStrError> for Error {
132 fn from(err: reqwest::header::ToStrError) -> Self {
133 Self::io(ErrorKind::Other, format!("{err}"))
134 }
135}
136
137#[cfg(target_family = "wasm")]
138impl From<Error> for wasm_bindgen::JsValue {
139 fn from(err: Error) -> Self {
140 serde_wasm_bindgen::to_value(&err).unwrap_or_default()
141 }
142}
143
144impl serde::de::Error for Error {
145 fn custom<T: std::fmt::Display>(msg: T) -> Self {
146 Self::io(ErrorKind::Other, format!("{msg}"))
147 }
148}
149
150impl std::error::Error for Error {}