irox_bits/
error.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2024 IROX Contributors
3//
4
5/// Type alias to [`BitsError`]
6///
7/// Originally would map to [`std::io::Error`] when the `std` feature was enabled, but that proved
8/// less ergonomic than just a internal error struct.
9pub type Error = BitsError;
10
11/// Type alias to [`BitsErrorKind`]
12///
13/// Originally would map to [`std::io::ErrorKind`] when the `std` feature was enabled, but that proved
14/// less ergonomic than just a internal error struct.
15pub type ErrorKind = BitsErrorKind;
16
17/// Error returned from the various Bits methods.
18///
19/// This used to be a no-std 1:1 swap out with [`std::io::Error`], but it become more ergonomic to
20/// simply use this error type everywhere.
21#[derive(Debug, Copy, Clone, Eq, PartialEq)]
22pub struct BitsError {
23    kind: BitsErrorKind,
24    msg: &'static str,
25}
26
27impl BitsError {
28    /// Creates a new error
29    pub const fn new(kind: BitsErrorKind, msg: &'static str) -> Self {
30        BitsError { kind, msg }
31    }
32
33    /// Returns the error type/kind of this error
34    pub const fn kind(&self) -> BitsErrorKind {
35        self.kind
36    }
37
38    /// Returns the error message.
39    pub const fn msg(&self) -> &'static str {
40        self.msg
41    }
42
43    /// Creates an error variant of this type
44    pub const fn err<T>(kind: BitsErrorKind, msg: &'static str) -> Result<T, Self> {
45        Err(Self::new(kind, msg))
46    }
47}
48
49impl From<BitsErrorKind> for BitsError {
50    fn from(kind: BitsErrorKind) -> Self {
51        BitsError {
52            kind,
53            msg: match kind {
54                BitsErrorKind::InvalidData => "Invalid Data",
55                BitsErrorKind::UnexpectedEof => "Unexpected EOF",
56                BitsErrorKind::FormatError => "Unspecified Formatting Error",
57                BitsErrorKind::OutOfMemory => "Out of Memory",
58
59                BitsErrorKind::NotFound => "Not Found",
60                BitsErrorKind::PermissionDenied => "Permission Denied",
61                BitsErrorKind::ConnectionRefused => "Connection Refused",
62                BitsErrorKind::ConnectionReset => "Connection Reset",
63                BitsErrorKind::ConnectionAborted => "Connection Aborted",
64                BitsErrorKind::AddrInUse => "Address In Use",
65                BitsErrorKind::AddrNotAvailable => "Address Not Available",
66                BitsErrorKind::BrokenPipe => "Broken Pipe",
67                BitsErrorKind::AlreadyExists => "Already Exists",
68                BitsErrorKind::WouldBlock => "Would Block",
69                BitsErrorKind::InvalidInput => "Invalid Input",
70                BitsErrorKind::TimedOut => "Timed Out",
71                BitsErrorKind::WriteZero => "Write Zero",
72                BitsErrorKind::Interrupted => "Interrupted",
73                BitsErrorKind::NotConnected => "Not Connected",
74                BitsErrorKind::Unsupported => "Unsupported",
75                BitsErrorKind::Other => "Other",
76            },
77        }
78    }
79}
80
81impl From<BitsError> for core::fmt::Error {
82    fn from(_kind: BitsError) -> Self {
83        core::fmt::Error
84    }
85}
86
87impl From<core::fmt::Error> for BitsError {
88    fn from(_value: core::fmt::Error) -> Self {
89        BitsErrorKind::FormatError.into()
90    }
91}
92
93#[cfg(feature = "std")]
94impl From<std::io::Error> for BitsError {
95    fn from(value: std::io::Error) -> Self {
96        BitsError {
97            kind: value.kind().into(),
98            msg: "IO Error",
99        }
100    }
101}
102
103#[cfg(feature = "std")]
104impl From<BitsError> for std::io::Error {
105    fn from(value: BitsError) -> Self {
106        Into::<std::io::ErrorKind>::into(value.kind).into()
107    }
108}
109
110#[cfg(feature = "std")]
111impl From<std::io::ErrorKind> for BitsErrorKind {
112    fn from(value: std::io::ErrorKind) -> Self {
113        use std::io::ErrorKind;
114        match value {
115            ErrorKind::NotFound => BitsErrorKind::NotFound,
116            ErrorKind::PermissionDenied => BitsErrorKind::PermissionDenied,
117            ErrorKind::ConnectionRefused => BitsErrorKind::ConnectionRefused,
118            ErrorKind::ConnectionReset => BitsErrorKind::ConnectionReset,
119            ErrorKind::ConnectionAborted => BitsErrorKind::ConnectionAborted,
120            ErrorKind::NotConnected => BitsErrorKind::NotConnected,
121            ErrorKind::AddrInUse => BitsErrorKind::AddrInUse,
122            ErrorKind::AddrNotAvailable => BitsErrorKind::AddrNotAvailable,
123            ErrorKind::BrokenPipe => BitsErrorKind::BrokenPipe,
124            ErrorKind::AlreadyExists => BitsErrorKind::AlreadyExists,
125            ErrorKind::WouldBlock => BitsErrorKind::WouldBlock,
126            ErrorKind::InvalidInput => BitsErrorKind::InvalidInput,
127            ErrorKind::InvalidData => BitsErrorKind::InvalidData,
128            ErrorKind::TimedOut => BitsErrorKind::TimedOut,
129            ErrorKind::WriteZero => BitsErrorKind::WriteZero,
130            ErrorKind::Interrupted => BitsErrorKind::Interrupted,
131            ErrorKind::Unsupported => BitsErrorKind::Unsupported,
132            ErrorKind::UnexpectedEof => BitsErrorKind::UnexpectedEof,
133            ErrorKind::OutOfMemory => BitsErrorKind::OutOfMemory,
134            _ => BitsErrorKind::Other,
135        }
136    }
137}
138
139#[cfg(feature = "std")]
140impl From<BitsErrorKind> for std::io::ErrorKind {
141    fn from(value: BitsErrorKind) -> Self {
142        use std::io::ErrorKind;
143        match value {
144            BitsErrorKind::InvalidData => ErrorKind::InvalidData,
145            BitsErrorKind::UnexpectedEof => ErrorKind::UnexpectedEof,
146            BitsErrorKind::OutOfMemory => ErrorKind::OutOfMemory,
147            BitsErrorKind::NotFound => ErrorKind::NotFound,
148            BitsErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
149            BitsErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused,
150            BitsErrorKind::ConnectionReset => ErrorKind::ConnectionReset,
151            BitsErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted,
152            BitsErrorKind::AddrInUse => ErrorKind::AddrInUse,
153            BitsErrorKind::AddrNotAvailable => ErrorKind::AddrNotAvailable,
154            BitsErrorKind::BrokenPipe => ErrorKind::BrokenPipe,
155            BitsErrorKind::AlreadyExists => ErrorKind::AlreadyExists,
156            BitsErrorKind::WouldBlock => ErrorKind::WouldBlock,
157            BitsErrorKind::InvalidInput => ErrorKind::InvalidInput,
158            BitsErrorKind::TimedOut => ErrorKind::TimedOut,
159            BitsErrorKind::WriteZero => ErrorKind::WriteZero,
160            BitsErrorKind::Interrupted => ErrorKind::Interrupted,
161            BitsErrorKind::Unsupported => ErrorKind::Unsupported,
162            BitsErrorKind::NotConnected => ErrorKind::NotConnected,
163            _ => ErrorKind::Other,
164        }
165    }
166}
167
168/// Enum originally modelled after [`std::io::ErrorKind`], used to indicate the
169/// type of the error encountered.
170#[derive(Debug, Copy, Clone, Eq, PartialEq)]
171pub enum BitsErrorKind {
172    InvalidData,
173    UnexpectedEof,
174    FormatError,
175    OutOfMemory,
176    NotFound,
177    PermissionDenied,
178    ConnectionRefused,
179    ConnectionReset,
180    ConnectionAborted,
181    AddrInUse,
182    AddrNotAvailable,
183    BrokenPipe,
184    AlreadyExists,
185    WouldBlock,
186    InvalidInput,
187    TimedOut,
188    WriteZero,
189    Interrupted,
190    NotConnected,
191    Unsupported,
192    Other,
193}
194
195impl BitsErrorKind {
196    pub const fn err<T>(self, msg: &'static str) -> Result<T, BitsError> {
197        Err(BitsError::new(self, msg))
198    }
199}
200
201#[cfg(feature = "std")]
202impl std::error::Error for BitsError {}
203
204impl core::fmt::Display for BitsError {
205    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
206        write!(f, "BitsError({:?}): {}", self.kind, self.msg)
207    }
208}
209
210cfg_feature_alloc! {
211    impl From<alloc::string::FromUtf8Error> for BitsError {
212        fn from(_value: alloc::string::FromUtf8Error) -> Self {
213            BitsError {
214                kind: BitsErrorKind::InvalidInput,
215                msg: "Invalid UTF-8 detected while trying to process input.",
216            }
217        }
218    }
219}