genio/
error.rs

1//! Error types and various operations on them.
2
3use void::Void;
4use void;
5use ::core::fmt;
6
7/// Specifies an error that happened during I/O operation. This enables one to compose read and
8/// write errors into single type.
9///
10/// This is different than `std::io::Error`!
11#[derive(Debug)]
12pub enum IOError<R, W> {
13    /// Read operation failed.
14    Read(R),
15    /// Write operation failed.
16    Write(W),
17}
18
19impl<R, W> IOError<R, W> {
20    /// Merges the variants into common type.
21    pub fn merge<E>(e: IOError<R, W>) -> E where R: Into<E>, W: Into<E> {
22        match e {
23            IOError::Read(e) => e.into(),
24            IOError::Write(e) => e.into(),
25        }
26    }
27
28    /// Get `IOError` containing references to errors.
29    pub fn as_ref(&self) -> IOError<&R, &W> {
30        match *self {
31            IOError::Read(ref f) => IOError::Read(f),
32            IOError::Write(ref s) => IOError::Write(s),
33        }
34    }
35
36    /// Get `IOError` containing mutable references to errors.
37    pub fn as_ref_mut(&mut self) -> IOError<&mut R, &mut W> {
38        match *self {
39            IOError::Read(ref mut f) => IOError::Read(f),
40            IOError::Write(ref mut s) => IOError::Write(s),
41        }
42    }
43}
44
45/// Error that might occur when reading exact amount of bytes.
46#[derive(Debug)]
47pub enum ReadExactError<E> {
48    /// Low-level error happened.
49    Other(E),
50
51    /// Reader reached end unexpectedly.
52    ///
53    /// Usually EOF, closed connection, etc.
54    UnexpectedEnd,
55}
56
57impl<E> From<E> for ReadExactError<E> {
58    fn from(e: E) -> Self {
59        ReadExactError::Other(e)
60    }
61}
62
63/// Error returned when chained readers fail. It allows inspecting which reader failed, keeping
64/// it's own error type. For simplicity it can be also merged, if the two errors are convertible to
65/// resulting error.
66#[derive(Debug)]
67pub enum ChainError<F, S> {
68    /// First reader failed.
69    First(F),
70    /// Second reader failed.
71    Second(S),
72}
73
74impl<F, S> ChainError<F, S> {
75    /// If the two errors can be converted to same type, they can be easily merged by this method.
76    /// This simply performs the conversion.
77    pub fn merge<E>(self) -> E where F: Into<E>, S: Into<E> {
78        match self {
79            ChainError::First(f) => f.into(),
80            ChainError::Second(s) => s.into(),
81        }
82    }
83
84    /// Get `ChainError` containing references to errors.
85    pub fn as_ref(&self) -> ChainError<&F, &S> {
86        match *self {
87            ChainError::First(ref f) => ChainError::First(f),
88            ChainError::Second(ref s) => ChainError::Second(s),
89        }
90    }
91
92    /// Get ChainError containing mutable references to errors.
93    pub fn as_ref_mut(&mut self) -> ChainError<&mut F, &mut S> {
94        match *self {
95            ChainError::First(ref mut f) => ChainError::First(f),
96            ChainError::Second(ref mut s) => ChainError::Second(s),
97        }
98    }
99}
100
101/// This error type indicates that operation might fail in restartible manner. The most obvious
102/// case is `EINTR` returned from syscalls when a signal is delivered while doing `read`.
103#[derive(Debug)]
104pub enum IntrError<E> {
105    /// The error wasn't interruption.
106    Other(E),
107    /// An operation was interrupted. This variant means that operation can be retried and it will
108    /// likely succeed.
109    Interrupted,
110}
111
112/// Trait for custom error types that can also represent interruption.
113pub trait IntoIntrError {
114    /// Type representing other error (non-interrupt).
115    type NonIntr;
116
117    /// Performs the conversion.
118    fn into_intr_error(self) -> IntrError<Self::NonIntr>;
119}
120
121impl<E> IntoIntrError for IntrError<E> {
122    type NonIntr = E;
123
124    fn into_intr_error(self) -> IntrError<Self::NonIntr> {
125        self
126    }
127}
128
129impl<T> From<Void> for IntrError<T> {
130    fn from(e: Void) -> Self {
131        void::unreachable(e)
132    }
133}
134
135// Should this be implemented?
136/*
137impl IntoIntrError for Void {
138    type NonIntr = Void;
139
140    fn into_intr_error(self) -> IntrError<Self::NonIntr> {
141        self.into()
142    }
143}
144*/
145
146/// Error that might occur when interacting with buf reader.
147#[derive(Debug)]
148pub enum BufError<B, E> {
149    /// The underlying stream reached the end.
150    End,
151    /// Buffer itself failed.
152    BufferErr(B),
153    /// The underlying stream failed.
154    OtherErr(E),
155}
156
157/// Error that might occur when doing operation on `ExtendFromReader`
158#[derive(Debug)]
159pub enum ExtendError<R, E> {
160    /// Reader failed
161    ReadErr(R),
162    /// The type being extended failed.
163    ExtendErr(E),
164}
165
166/// Error indicating that provided buffer was too small
167#[derive(Debug)]
168pub struct BufferOverflow;
169
170impl fmt::Display for BufferOverflow {
171    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
172        write!(f, "provided buffer was too small")
173    }
174}