1use ffi;
2use std::ffi::NulError;
3use std::os::raw::c_int;
4use std::{error, fmt};
5
6pub type Result<T> = ::std::result::Result<T, Error>;
7
8#[derive(PartialEq, Eq, Clone, Debug, Copy)]
10pub enum ErrorCode {
11 Error,
13 InvalidFormat,
15 InvalidParameter,
17 NotSupported,
19 DeviceUnavailable,
21}
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq)]
24pub struct Error {
25 code: ErrorCode,
26}
27
28impl Error {
29 #[allow(clippy::self_named_constructors)]
30 pub fn error() -> Self {
31 Error {
32 code: ErrorCode::Error,
33 }
34 }
35 pub fn invalid_format() -> Self {
36 Error {
37 code: ErrorCode::InvalidFormat,
38 }
39 }
40 pub fn invalid_parameter() -> Self {
41 Error {
42 code: ErrorCode::InvalidParameter,
43 }
44 }
45 pub fn not_supported() -> Self {
46 Error {
47 code: ErrorCode::NotSupported,
48 }
49 }
50 pub fn device_unavailable() -> Self {
51 Error {
52 code: ErrorCode::DeviceUnavailable,
53 }
54 }
55
56 pub fn from_raw(code: c_int) -> Error {
57 let code = match code {
58 ffi::CUBEB_ERROR_INVALID_FORMAT => ErrorCode::InvalidFormat,
59 ffi::CUBEB_ERROR_INVALID_PARAMETER => ErrorCode::InvalidParameter,
60 ffi::CUBEB_ERROR_NOT_SUPPORTED => ErrorCode::NotSupported,
61 ffi::CUBEB_ERROR_DEVICE_UNAVAILABLE => ErrorCode::DeviceUnavailable,
62 _ => ErrorCode::Error,
64 };
65
66 Error { code }
67 }
68
69 pub fn code(&self) -> ErrorCode {
70 self.code
71 }
72
73 pub fn raw_code(&self) -> c_int {
74 match self.code {
75 ErrorCode::Error => ffi::CUBEB_ERROR,
76 ErrorCode::InvalidFormat => ffi::CUBEB_ERROR_INVALID_FORMAT,
77 ErrorCode::InvalidParameter => ffi::CUBEB_ERROR_INVALID_PARAMETER,
78 ErrorCode::NotSupported => ffi::CUBEB_ERROR_NOT_SUPPORTED,
79 ErrorCode::DeviceUnavailable => ffi::CUBEB_ERROR_DEVICE_UNAVAILABLE,
80 }
81 }
82}
83
84impl Default for Error {
85 fn default() -> Self {
86 Error::error()
87 }
88}
89
90impl error::Error for Error {
91 fn description(&self) -> &str {
92 match self.code {
93 ErrorCode::Error => "Error",
94 ErrorCode::InvalidFormat => "Invalid format",
95 ErrorCode::InvalidParameter => "Invalid parameter",
96 ErrorCode::NotSupported => "Not supported",
97 ErrorCode::DeviceUnavailable => "Device unavailable",
98 }
99 }
100}
101
102impl fmt::Display for Error {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 write!(f, "{self:?}")
105 }
106}
107
108impl From<ErrorCode> for Error {
109 fn from(code: ErrorCode) -> Error {
110 Error { code }
111 }
112}
113
114impl From<NulError> for Error {
115 fn from(_: NulError) -> Error {
116 Error::from_raw(ffi::CUBEB_ERROR)
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use ffi;
124
125 #[test]
126 fn test_from_raw() {
127 macro_rules! test {
128 ( $($raw:ident => $err:ident),* ) => {{
129 $(
130 let e = Error::from_raw(ffi::$raw);
131 assert_eq!(e.raw_code(), ffi::$raw);
132 assert_eq!(e.code(), ErrorCode::$err);
133 )*
134 }};
135 }
136 test!(CUBEB_ERROR => Error,
137 CUBEB_ERROR_INVALID_FORMAT => InvalidFormat,
138 CUBEB_ERROR_INVALID_PARAMETER => InvalidParameter,
139 CUBEB_ERROR_NOT_SUPPORTED => NotSupported,
140 CUBEB_ERROR_DEVICE_UNAVAILABLE => DeviceUnavailable
141 );
142 }
143
144 #[test]
145 fn test_from_error_code() {
146 macro_rules! test {
147 ( $($raw:ident => $err:ident),* ) => {{
148 $(
149 let e = Error::from(ErrorCode::$err);
150 assert_eq!(e.raw_code(), ffi::$raw);
151 assert_eq!(e.code(), ErrorCode::$err);
152 )*
153 }};
154 }
155 test!(CUBEB_ERROR => Error,
156 CUBEB_ERROR_INVALID_FORMAT => InvalidFormat,
157 CUBEB_ERROR_INVALID_PARAMETER => InvalidParameter,
158 CUBEB_ERROR_NOT_SUPPORTED => NotSupported,
159 CUBEB_ERROR_DEVICE_UNAVAILABLE => DeviceUnavailable
160 );
161 }
162}