libflo_audio/core/
error.rs1use alloc::boxed::Box;
4use alloc::string::{String, ToString};
5use core::fmt;
6
7#[non_exhaustive]
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum FloErrorKind {
11 InvalidData,
13 UnsupportedFeature,
15 Io,
17 Codec,
19 Metadata,
21 Lossy,
23 Lossless,
25 Wasm,
27 Internal,
29}
30
31pub struct FloError {
33 kind: FloErrorKind,
34 message: String,
35 source: Option<Box<dyn core::error::Error + Send + Sync + 'static>>,
36}
37
38impl Clone for FloError {
39 fn clone(&self) -> Self {
40 Self {
41 kind: self.kind,
42 message: self.message.clone(),
43 source: None,
45 }
46 }
47}
48
49impl FloError {
50 pub fn new<T: Into<String>>(kind: FloErrorKind, message: T) -> Self {
52 Self {
53 kind,
54 message: message.into(),
55 source: None,
56 }
57 }
58
59 pub fn kind(&self) -> FloErrorKind {
61 self.kind
62 }
63
64 pub fn message(&self) -> &str {
66 &self.message
67 }
68
69 pub fn with_context<T: Into<String>>(mut self, ctx: T) -> Self {
71 let ctx = ctx.into();
72 if self.message.is_empty() {
73 self.message = ctx;
74 } else {
75 self.message = alloc::format!("{ctx}: {}", self.message);
76 }
77 self
78 }
79
80 pub fn with_source(mut self, source: impl core::error::Error + Send + Sync + 'static) -> Self {
81 self.source = Some(Box::new(source));
82 self
83 }
84
85 pub fn into_boxed(self) -> Box<FloError> {
87 Box::new(self)
88 }
89}
90
91impl fmt::Display for FloError {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 fmt::Display::fmt(&self.message, f)
94 }
95}
96
97impl fmt::Debug for FloError {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 let mut d = f.debug_struct("FloError");
100 d.field("kind", &format_args!("{:?}", self.kind));
101 d.field("message", &self.message);
102 d.finish()
103 }
104}
105
106impl core::error::Error for FloError {
107 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
108 self.source
109 .as_deref()
110 .map(|e| e as &(dyn core::error::Error + 'static))
111 }
112}
113
114impl From<fmt::Error> for FloError {
115 fn from(e: fmt::Error) -> Self {
116 Self::new(FloErrorKind::Codec, e.to_string())
117 }
118}
119
120impl From<String> for FloError {
121 fn from(s: String) -> Self {
122 Self::new(FloErrorKind::Internal, s)
123 }
124}
125
126impl From<&str> for FloError {
127 fn from(s: &str) -> Self {
128 Self::new(FloErrorKind::Internal, s.to_string())
129 }
130}
131
132pub trait FloErrorExt<T> {
134 fn context(self, ctx: impl Into<String>) -> Result<T, FloError>;
136}
137
138impl<T> FloErrorExt<T> for Result<T, FloError> {
139 fn context(self, ctx: impl Into<String>) -> Result<T, FloError> {
140 self.map_err(|e| e.with_context(ctx))
141 }
142}
143
144pub type FloResult<T> = Result<T, FloError>;