Skip to content
This repository was archived by the owner on Nov 30, 2022. It is now read-only.

Commit 38bb903

Browse files
committed
Add literacy:Error with inexpensive ErrorKind and inner error for introspection, adds ErrorTrait to expose kind
1 parent c6d4ca4 commit 38bb903

File tree

2 files changed

+117
-15
lines changed

2 files changed

+117
-15
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub mod _export {
5252

5353
#[cfg(feature = "schemars")] extern crate schemars;
5454

55-
#[cfg(all(not(feature = "use-core2"), not(feature = "std")))]
55+
#[cfg(not(feature = "std"))]
5656
extern crate alloc;
5757

5858
#[macro_use] mod util;

src/literacy.rs

Lines changed: 116 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,113 @@
2222
//! and `impl Write for ::alloc::vec::Vec<u8>` are provided
2323
//!
2424
25+
#[cfg(feature = "std")]
26+
use std::boxed::Box as AllocBox;
27+
28+
#[cfg(not(feature = "std"))]
29+
use alloc::boxed::Box as AllocBox;
30+
2531
/// The Read trait allows for reading bytes from a source.
2632
pub trait Read {
2733
/// The error type returned in Result
28-
type Error;
34+
type Error: ErrorTrait;
35+
2936
/// see [std::io::Read::read]
3037
fn read(&mut self, buf: &mut [u8]) -> ::core::result::Result<usize, Self::Error>;
38+
3139
/// see [std::io::Read::read_exact]
3240
fn read_exact(&mut self, buf: &mut [u8]) -> ::core::result::Result<(), Self::Error>;
3341
}
3442

3543
/// The Write trait allows to write bytes in the object implementing it.
3644
pub trait Write {
3745
/// The error type returned in Result
38-
type Error;
46+
type Error: ErrorTrait;
47+
3948
/// see [std::io::Write::write]
4049
fn write(&mut self, buf: &[u8]) -> ::core::result::Result<usize, Self::Error>;
50+
4151
/// see [std::io::Write::write_all]
4252
fn write_all(&mut self, buf: &[u8]) -> ::core::result::Result<(), Self::Error>;
53+
4354
/// see [std::io::Write::flush]
4455
fn flush(&mut self) -> ::core::result::Result<(), Self::Error>;
4556
}
4657

58+
/// The literacy Error trait, custom errors must implement this
59+
pub trait ErrorTrait {
60+
/// The error category
61+
fn kind(&self) -> ErrorKind;
62+
}
63+
64+
/// Same as [std::io::ErrorKind] that we have to duplicate because ErrorKind is not in `core`
65+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
66+
#[allow(missing_docs)]
67+
pub enum ErrorKind {
68+
NotFound,
69+
PermissionDenied,
70+
ConnectionRefused,
71+
ConnectionReset,
72+
ConnectionAborted,
73+
NotConnected,
74+
AddrInUse,
75+
AddrNotAvailable,
76+
BrokenPipe,
77+
AlreadyExists,
78+
WouldBlock,
79+
InvalidInput,
80+
InvalidData,
81+
TimedOut,
82+
WriteZero,
83+
Interrupted,
84+
Other,
85+
UnexpectedEof,
86+
}
87+
88+
/// The Error type in case we are not using [std::io::Error] or [core2::io::Error]
89+
#[derive(Debug)]
90+
pub struct Error {
91+
kind: ErrorKind,
92+
93+
error: AllocBox<dyn InnerError>,
94+
}
95+
96+
trait InnerError: ::core::fmt::Debug + ::core::any::Any {}
97+
98+
impl InnerError for () {}
99+
100+
impl ErrorTrait for Error {
101+
fn kind(&self) -> ErrorKind {
102+
self.kind
103+
}
104+
}
105+
47106
#[cfg(all(feature = "std", not(feature = "use-core2")))]
48-
pub use ::std::io::Error;
107+
impl ErrorTrait for ::std::io::Error {
108+
fn kind(&self) -> ErrorKind {
109+
match self.kind() {
110+
::std::io::ErrorKind::NotFound => ErrorKind::NotFound,
111+
::std::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
112+
::std::io::ErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused,
113+
::std::io::ErrorKind::ConnectionReset => ErrorKind::ConnectionReset,
114+
::std::io::ErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted,
115+
::std::io::ErrorKind::NotConnected => ErrorKind::NotConnected,
116+
::std::io::ErrorKind::AddrInUse => ErrorKind::AddrInUse,
117+
::std::io::ErrorKind::AddrNotAvailable => ErrorKind::AddrNotAvailable,
118+
::std::io::ErrorKind::BrokenPipe => ErrorKind::BrokenPipe,
119+
::std::io::ErrorKind::AlreadyExists => ErrorKind::AlreadyExists,
120+
::std::io::ErrorKind::WouldBlock => ErrorKind::WouldBlock,
121+
::std::io::ErrorKind::InvalidInput => ErrorKind::InvalidInput,
122+
::std::io::ErrorKind::InvalidData => ErrorKind::InvalidData,
123+
::std::io::ErrorKind::TimedOut => ErrorKind::TimedOut,
124+
::std::io::ErrorKind::WriteZero => ErrorKind::WriteZero,
125+
::std::io::ErrorKind::Interrupted => ErrorKind::Interrupted,
126+
::std::io::ErrorKind::Other => ErrorKind::Other,
127+
::std::io::ErrorKind::UnexpectedEof => ErrorKind::UnexpectedEof,
128+
_ => ErrorKind::Other,
129+
}
130+
}
131+
}
49132

50133
#[cfg(all(feature = "std", not(feature = "use-core2")))]
51134
mod std_impl {
@@ -81,7 +164,31 @@ mod std_impl {
81164
}
82165

83166
#[cfg(feature = "use-core2")]
84-
pub use core2::io::Error;
167+
impl ErrorTrait for core2::io::Error {
168+
fn kind(&self) -> ErrorKind {
169+
match self.kind() {
170+
core2::io::ErrorKind::NotFound => ErrorKind::NotFound,
171+
core2::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
172+
core2::io::ErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused,
173+
core2::io::ErrorKind::ConnectionReset => ErrorKind::ConnectionReset,
174+
core2::io::ErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted,
175+
core2::io::ErrorKind::NotConnected => ErrorKind::NotConnected,
176+
core2::io::ErrorKind::AddrInUse => ErrorKind::AddrInUse,
177+
core2::io::ErrorKind::AddrNotAvailable => ErrorKind::AddrNotAvailable,
178+
core2::io::ErrorKind::BrokenPipe => ErrorKind::BrokenPipe,
179+
core2::io::ErrorKind::AlreadyExists => ErrorKind::AlreadyExists,
180+
core2::io::ErrorKind::WouldBlock => ErrorKind::WouldBlock,
181+
core2::io::ErrorKind::InvalidInput => ErrorKind::InvalidInput,
182+
core2::io::ErrorKind::InvalidData => ErrorKind::InvalidData,
183+
core2::io::ErrorKind::TimedOut => ErrorKind::TimedOut,
184+
core2::io::ErrorKind::WriteZero => ErrorKind::WriteZero,
185+
core2::io::ErrorKind::Interrupted => ErrorKind::Interrupted,
186+
core2::io::ErrorKind::Other => ErrorKind::Other,
187+
core2::io::ErrorKind::UnexpectedEof => ErrorKind::UnexpectedEof,
188+
_ => ErrorKind::Other,
189+
}
190+
}
191+
}
85192

86193
#[cfg(feature = "use-core2")]
87194
mod core2_impl {
@@ -116,17 +223,9 @@ mod core2_impl {
116223
}
117224
}
118225

119-
#[cfg(all(not(feature = "use-core2"), not(feature = "std")))]
120-
#[derive(Debug)]
121-
/// The Error for the default implementation
122-
pub enum Error {
123-
/// Unexpected "end of file"
124-
UnexpectedEof,
125-
}
126-
127226
#[cfg(all(not(feature = "use-core2"), not(feature = "std")))]
128227
mod default_impl {
129-
use super::{Read, Write, Error};
228+
use super::{Read, Write, Error, ErrorKind};
130229

131230
impl<'a> Read for &'a [u8] {
132231
type Error = Error;
@@ -150,7 +249,10 @@ mod default_impl {
150249

151250
fn read_exact(&mut self, buf: &mut [u8]) -> ::core::result::Result<(), Self::Error> {
152251
if buf.len() > self.len() {
153-
return Err(Self::Error::UnexpectedEof);
252+
return Err( Self::Error {
253+
kind: ErrorKind::UnexpectedEof,
254+
error: alloc::boxed::Box::new(()),
255+
});
154256
}
155257
let (a, b) = self.split_at(buf.len());
156258

0 commit comments

Comments
 (0)