Skip to content

Commit 96bcd4e

Browse files
committed
Strip std::io down
0 parents  commit 96bcd4e

File tree

4 files changed

+1493
-0
lines changed

4 files changed

+1493
-0
lines changed

.gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/target
2+
3+
4+
#Added by cargo
5+
#
6+
#already existing elements were commented out
7+
8+
#/target
9+
Cargo.lock

Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "bare-io"
3+
version = "0.1.0"
4+
authors = ["Brendan Molloy <[email protected]>"]
5+
description = "The bare essentials of std::io for use in no_std. No alloc!"
6+
license = "Apache-2.0 OR MIT"
7+
edition = "2018"
8+
9+
[dependencies]

src/error.rs

+342
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
use core::{convert::From, fmt, result};
2+
3+
/// A specialized [`Result`] type for I/O operations.
4+
///
5+
/// This type is broadly used across [`std::io`] for any operation which may
6+
/// produce an error.
7+
///
8+
/// This typedef is generally used to avoid writing out [`io::Error`] directly and
9+
/// is otherwise a direct mapping to [`Result`].
10+
///
11+
/// While usual Rust style is to import types directly, aliases of [`Result`]
12+
/// often are not, to make it easier to distinguish between them. [`Result`] is
13+
/// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias
14+
/// will generally use `io::Result` instead of shadowing the [prelude]'s import
15+
/// of [`std::result::Result`][`Result`].
16+
///
17+
/// [`std::io`]: crate::io
18+
/// [`io::Error`]: Error
19+
/// [`Result`]: crate::result::Result
20+
/// [prelude]: crate::prelude
21+
///
22+
/// # Examples
23+
///
24+
/// A convenience function that bubbles an `io::Result` to its caller:
25+
///
26+
/// ```
27+
/// use std::io;
28+
///
29+
/// fn get_string() -> io::Result<String> {
30+
/// let mut buffer = String::new();
31+
///
32+
/// io::stdin().read_line(&mut buffer)?;
33+
///
34+
/// Ok(buffer)
35+
/// }
36+
/// ```
37+
pub type Result<T> = result::Result<T, Error>;
38+
39+
/// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and
40+
/// associated traits.
41+
///
42+
/// Errors mostly originate from the underlying OS, but custom instances of
43+
/// `Error` can be created with crafted error messages and a particular value of
44+
/// [`ErrorKind`].
45+
///
46+
/// [`Read`]: crate::io::Read
47+
/// [`Write`]: crate::io::Write
48+
/// [`Seek`]: crate::io::Seek
49+
pub struct Error {
50+
repr: Repr,
51+
}
52+
53+
impl fmt::Debug for Error {
54+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55+
fmt::Debug::fmt(&self.repr, f)
56+
}
57+
}
58+
59+
enum Repr {
60+
Simple(ErrorKind),
61+
Custom(Custom),
62+
}
63+
64+
#[derive(Debug)]
65+
struct Custom {
66+
kind: ErrorKind,
67+
error: &'static str,
68+
}
69+
70+
/// A list specifying general categories of I/O error.
71+
///
72+
/// This list is intended to grow over time and it is not recommended to
73+
/// exhaustively match against it.
74+
///
75+
/// It is used with the [`io::Error`] type.
76+
///
77+
/// [`io::Error`]: Error
78+
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
79+
// #[allow(deprecated)]
80+
#[non_exhaustive]
81+
pub enum ErrorKind {
82+
/// An entity was not found, often a file.
83+
NotFound,
84+
/// The operation lacked the necessary privileges to complete.
85+
PermissionDenied,
86+
/// The connection was refused by the remote server.
87+
ConnectionRefused,
88+
/// The connection was reset by the remote server.
89+
ConnectionReset,
90+
/// The connection was aborted (terminated) by the remote server.
91+
ConnectionAborted,
92+
/// The network operation failed because it was not connected yet.
93+
NotConnected,
94+
/// A socket address could not be bound because the address is already in
95+
/// use elsewhere.
96+
AddrInUse,
97+
/// A nonexistent interface was requested or the requested address was not
98+
/// local.
99+
AddrNotAvailable,
100+
/// The operation failed because a pipe was closed.
101+
BrokenPipe,
102+
/// An entity already exists, often a file.
103+
AlreadyExists,
104+
/// The operation needs to block to complete, but the blocking operation was
105+
/// requested to not occur.
106+
WouldBlock,
107+
/// A parameter was incorrect.
108+
InvalidInput,
109+
/// Data not valid for the operation were encountered.
110+
///
111+
/// Unlike [`InvalidInput`], this typically means that the operation
112+
/// parameters were valid, however the error was caused by malformed
113+
/// input data.
114+
///
115+
/// For example, a function that reads a file into a string will error with
116+
/// `InvalidData` if the file's contents are not valid UTF-8.
117+
///
118+
/// [`InvalidInput`]: ErrorKind::InvalidInput
119+
InvalidData,
120+
/// The I/O operation's timeout expired, causing it to be canceled.
121+
TimedOut,
122+
/// An error returned when an operation could not be completed because a
123+
/// call to [`write`] returned [`Ok(0)`].
124+
///
125+
/// This typically means that an operation could only succeed if it wrote a
126+
/// particular number of bytes but only a smaller number of bytes could be
127+
/// written.
128+
///
129+
/// [`write`]: crate::io::Write::write
130+
/// [`Ok(0)`]: Ok
131+
WriteZero,
132+
/// This operation was interrupted.
133+
///
134+
/// Interrupted operations can typically be retried.
135+
Interrupted,
136+
/// Any I/O error not part of this list.
137+
///
138+
/// Errors that are `Other` now may move to a different or a new
139+
/// [`ErrorKind`] variant in the future. It is not recommended to match
140+
/// an error against `Other` and to expect any additional characteristics,
141+
/// e.g., a specific [`Error::raw_os_error`] return value.
142+
Other,
143+
144+
/// An error returned when an operation could not be completed because an
145+
/// "end of file" was reached prematurely.
146+
///
147+
/// This typically means that an operation could only succeed if it read a
148+
/// particular number of bytes but only a smaller number of bytes could be
149+
/// read.
150+
UnexpectedEof,
151+
}
152+
153+
impl ErrorKind {
154+
pub(crate) fn as_str(&self) -> &'static str {
155+
match *self {
156+
ErrorKind::NotFound => "entity not found",
157+
ErrorKind::PermissionDenied => "permission denied",
158+
ErrorKind::ConnectionRefused => "connection refused",
159+
ErrorKind::ConnectionReset => "connection reset",
160+
ErrorKind::ConnectionAborted => "connection aborted",
161+
ErrorKind::NotConnected => "not connected",
162+
ErrorKind::AddrInUse => "address in use",
163+
ErrorKind::AddrNotAvailable => "address not available",
164+
ErrorKind::BrokenPipe => "broken pipe",
165+
ErrorKind::AlreadyExists => "entity already exists",
166+
ErrorKind::WouldBlock => "operation would block",
167+
ErrorKind::InvalidInput => "invalid input parameter",
168+
ErrorKind::InvalidData => "invalid data",
169+
ErrorKind::TimedOut => "timed out",
170+
ErrorKind::WriteZero => "write zero",
171+
ErrorKind::Interrupted => "operation interrupted",
172+
ErrorKind::Other => "other os error",
173+
ErrorKind::UnexpectedEof => "unexpected end of file",
174+
}
175+
}
176+
}
177+
178+
/// Intended for use for errors not exposed to the user, where allocating onto
179+
/// the heap (for normal construction via Error::new) is too costly.
180+
impl From<ErrorKind> for Error {
181+
/// Converts an [`ErrorKind`] into an [`Error`].
182+
///
183+
/// This conversion allocates a new error with a simple representation of error kind.
184+
///
185+
/// # Examples
186+
///
187+
/// ```
188+
/// use std::io::{Error, ErrorKind};
189+
///
190+
/// let not_found = ErrorKind::NotFound;
191+
/// let error = Error::from(not_found);
192+
/// assert_eq!("entity not found", format!("{}", error));
193+
/// ```
194+
#[inline]
195+
fn from(kind: ErrorKind) -> Error {
196+
Error { repr: Repr::Simple(kind) }
197+
}
198+
}
199+
200+
impl Error {
201+
/// Creates a new I/O error from a known kind of error as well as an
202+
/// arbitrary error payload.
203+
///
204+
/// This function is used to generically create I/O errors which do not
205+
/// originate from the OS itself. The `error` argument is an arbitrary
206+
/// payload which will be contained in this [`Error`].
207+
///
208+
/// # Examples
209+
///
210+
/// ```
211+
/// use std::io::{Error, ErrorKind};
212+
///
213+
/// // errors can be created from strings
214+
/// let custom_error = Error::new(ErrorKind::Other, "oh no!");
215+
///
216+
/// // errors can also be created from other errors
217+
/// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
218+
/// ```
219+
pub fn new(kind: ErrorKind, error: &'static str) -> Error {
220+
Self::_new(kind, error.into())
221+
}
222+
223+
fn _new(kind: ErrorKind, error: &'static str) -> Error {
224+
Error { repr: Repr::Custom(Custom { kind, error }) }
225+
}
226+
227+
/// Returns a reference to the inner error wrapped by this error (if any).
228+
///
229+
/// If this [`Error`] was constructed via [`new`] then this function will
230+
/// return [`Some`], otherwise it will return [`None`].
231+
///
232+
/// [`new`]: Error::new
233+
///
234+
/// # Examples
235+
///
236+
/// ```
237+
/// use std::io::{Error, ErrorKind};
238+
///
239+
/// fn print_error(err: &Error) {
240+
/// if let Some(inner_err) = err.get_ref() {
241+
/// println!("Inner error: {:?}", inner_err);
242+
/// } else {
243+
/// println!("No inner error");
244+
/// }
245+
/// }
246+
///
247+
/// fn main() {
248+
/// // Will print "No inner error".
249+
/// print_error(&Error::last_os_error());
250+
/// // Will print "Inner error: ...".
251+
/// print_error(&Error::new(ErrorKind::Other, "oh no!"));
252+
/// }
253+
/// ```
254+
pub fn get_ref(&self) -> Option<&&'static str> {
255+
match self.repr {
256+
Repr::Simple(..) => None,
257+
Repr::Custom(ref c) => Some(&c.error),
258+
}
259+
}
260+
261+
/// Consumes the `Error`, returning its inner error (if any).
262+
///
263+
/// If this [`Error`] was constructed via [`new`] then this function will
264+
/// return [`Some`], otherwise it will return [`None`].
265+
///
266+
/// [`new`]: Error::new
267+
///
268+
/// # Examples
269+
///
270+
/// ```
271+
/// use std::io::{Error, ErrorKind};
272+
///
273+
/// fn print_error(err: Error) {
274+
/// if let Some(inner_err) = err.into_inner() {
275+
/// println!("Inner error: {}", inner_err);
276+
/// } else {
277+
/// println!("No inner error");
278+
/// }
279+
/// }
280+
///
281+
/// fn main() {
282+
/// // Will print "No inner error".
283+
/// print_error(Error::last_os_error());
284+
/// // Will print "Inner error: ...".
285+
/// print_error(Error::new(ErrorKind::Other, "oh no!"));
286+
/// }
287+
/// ```
288+
pub fn into_inner(self) -> Option<&'static str> {
289+
match self.repr {
290+
Repr::Simple(..) => None,
291+
Repr::Custom(c) => Some(c.error),
292+
}
293+
}
294+
295+
/// Returns the corresponding [`ErrorKind`] for this error.
296+
///
297+
/// # Examples
298+
///
299+
/// ```
300+
/// use std::io::{Error, ErrorKind};
301+
///
302+
/// fn print_error(err: Error) {
303+
/// println!("{:?}", err.kind());
304+
/// }
305+
///
306+
/// fn main() {
307+
/// // Will print "Other".
308+
/// print_error(Error::last_os_error());
309+
/// // Will print "AddrInUse".
310+
/// print_error(Error::new(ErrorKind::AddrInUse, "oh no!"));
311+
/// }
312+
/// ```
313+
pub fn kind(&self) -> ErrorKind {
314+
match self.repr {
315+
Repr::Custom(ref c) => c.kind,
316+
Repr::Simple(kind) => kind,
317+
}
318+
}
319+
}
320+
321+
impl fmt::Debug for Repr {
322+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
323+
match *self {
324+
Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
325+
Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
326+
}
327+
}
328+
}
329+
330+
impl fmt::Display for Error {
331+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
332+
match self.repr {
333+
Repr::Custom(ref c) => c.error.fmt(fmt),
334+
Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
335+
}
336+
}
337+
}
338+
339+
fn _assert_error_is_sync_send() {
340+
fn _is_sync_send<T: Sync + Send>() {}
341+
_is_sync_send::<Error>();
342+
}

0 commit comments

Comments
 (0)