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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! Error types for packet wire sources, writers, transforms, and backends.
use std::fmt;
use std::io;
use crate::error::CrafterError;
use crate::net::NetError;
use crate::wire::backend::pcap::PcapError;
/// Convenient result alias used by wire packet I/O primitives.
pub type Result<T> = std::result::Result<T, WireError>;
/// Errors returned by packet wire sources, writers, transforms, and backends.
#[derive(Debug)]
pub enum WireError {
/// A backend or opened wire does not support the requested operation.
UnsupportedCapability {
/// Stable capability name, such as `read`, `write`, or `split`.
capability: &'static str,
/// Backend or interface identifier when available.
backend: Option<String>,
/// Stable diagnostic reason.
reason: &'static str,
},
/// A backend-specific operation failed before it became a packet, pcap, net, or I/O error.
Backend {
/// Backend name or identifier.
backend: String,
/// Stable operation name.
operation: &'static str,
/// Backend diagnostic reason.
reason: String,
},
/// Packet compilation or decode failed.
Packet(CrafterError),
/// Pcap read, write, filter, or capture failed.
Pcap(PcapError),
/// Network interface, routing, send, or send/receive failed.
Net(NetError),
/// A file, stream, socket, or other I/O operation failed.
Io {
/// Stable operation name.
operation: &'static str,
/// Underlying I/O error.
source: io::Error,
},
/// A packet transform failed.
Transform {
/// Transform name.
transform: String,
/// Transform diagnostic reason.
reason: String,
},
}
impl WireError {
/// Build an unsupported capability error.
pub fn unsupported_capability(
capability: &'static str,
backend: Option<impl Into<String>>,
reason: &'static str,
) -> Self {
Self::UnsupportedCapability {
capability,
backend: backend.map(Into::into),
reason,
}
}
/// Build a backend error.
pub fn backend(
backend: impl Into<String>,
operation: &'static str,
reason: impl Into<String>,
) -> Self {
Self::Backend {
backend: backend.into(),
operation,
reason: reason.into(),
}
}
/// Build an I/O error with operation context.
pub const fn io(operation: &'static str, source: io::Error) -> Self {
Self::Io { operation, source }
}
/// Build a transform error.
pub fn transform(transform: impl Into<String>, reason: impl Into<String>) -> Self {
Self::Transform {
transform: transform.into(),
reason: reason.into(),
}
}
}
impl fmt::Display for WireError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::UnsupportedCapability {
capability,
backend,
reason,
} => {
if let Some(backend) = backend {
write!(
f,
"wire backend '{backend}' does not support {capability}: {reason}"
)
} else {
write!(f, "wire capability '{capability}' is unsupported: {reason}")
}
}
Self::Backend {
backend,
operation,
reason,
} => write!(f, "wire backend '{backend}' {operation} failed: {reason}"),
Self::Packet(err) => write!(f, "{err}"),
Self::Pcap(err) => write!(f, "{err}"),
Self::Net(err) => write!(f, "{err}"),
Self::Io { operation, source } => write!(f, "{operation} failed: {source}"),
Self::Transform { transform, reason } => {
write!(f, "wire transform '{transform}' failed: {reason}")
}
}
}
}
impl std::error::Error for WireError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Packet(err) => Some(err),
Self::Pcap(err) => Some(err),
Self::Net(err) => Some(err),
Self::Io { source, .. } => Some(source),
_ => None,
}
}
}
impl From<CrafterError> for WireError {
fn from(value: CrafterError) -> Self {
Self::Packet(value)
}
}
impl From<PcapError> for WireError {
fn from(value: PcapError) -> Self {
Self::Pcap(value)
}
}
impl From<NetError> for WireError {
fn from(value: NetError) -> Self {
Self::Net(value)
}
}
impl From<io::Error> for WireError {
fn from(value: io::Error) -> Self {
Self::Io {
operation: "wire I/O",
source: value,
}
}
}