1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! The errors of the library: the exceptions the upstream code throws or
//! lets through, as one value that can be handed to the exception event of a
//! connection and to every handler subscribed to it.
use std::fmt;
use std::io;
use std::sync::Arc;
use crate::metsys_bson::BsonException;
/// What a serializer, a resolver or a transport reports. Each variant is the
/// exception of the same name in the upstream code.
#[derive(Clone, Debug)]
pub enum Error {
/// `BsonException`: what the BSON serializer itself rejects.
Bson(BsonException),
/// `EndOfStreamException`: the document or the stream ended inside a
/// value.
EndOfStream,
/// `InvalidOperationException`.
InvalidOperation(String),
/// `InvalidCastException`: a deserialized value is not of the type of
/// the property it belongs to.
InvalidCast(String),
/// `KeyNotFoundException`: an identifier or a type the resolver does not
/// know, or an element type the reader has no type for.
KeyNotFound(String),
/// `ArgumentException` and `ArgumentOutOfRangeException`.
Argument(String),
/// `OverflowException`.
Overflow(String),
/// `FormatException`.
Format(String),
/// `NullReferenceException`.
NullReference,
/// `IOException` and `SocketException`: what a stream or a socket
/// reported.
Io(Arc<io::Error>),
/// A handler of an event panicked: the port's form of an exception
/// thrown by a handler, with the message of the panic.
Handler(String),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Bson(e) => e.fmt(f),
Error::EndOfStream => f.write_str("Unable to read beyond the end of the stream."),
Error::InvalidOperation(message)
| Error::InvalidCast(message)
| Error::KeyNotFound(message)
| Error::Argument(message)
| Error::Overflow(message)
| Error::Format(message)
| Error::Handler(message) => f.write_str(message),
Error::NullReference => f.write_str("Object reference not set to an instance of an object."),
Error::Io(e) => e.fmt(f),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::Bson(e) => Some(e),
Error::Io(e) => Some(&**e),
_ => None,
}
}
}
impl From<BsonException> for Error {
fn from(e: BsonException) -> Self {
Error::Bson(e)
}
}
impl From<io::Error> for Error {
fn from(e: io::Error) -> Self {
if e.kind() == io::ErrorKind::UnexpectedEof {
Error::EndOfStream
} else {
Error::Io(Arc::new(e))
}
}
}
/// Runs a handler and turns a panic of it into [`Error::Handler`]: the `try`
/// and `catch` around a delegate invocation in the upstream code.
pub(crate) fn catch_handler(f: impl FnOnce()) -> Result<(), Error> {
std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)).map_err(|payload| {
let message = if let Some(text) = payload.downcast_ref::<&str>() {
(*text).to_string()
} else if let Some(text) = payload.downcast_ref::<String>() {
text.clone()
} else {
"A handler panicked.".to_string()
};
Error::Handler(message)
})
}