1use std::error::Error;
2use std::fmt;
3
4#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5pub struct OperationError {
6 code: i32,
7}
8
9impl OperationError {
10 pub(crate) fn new(code: i32) -> Self {
11 Self { code }
12 }
13
14 #[allow(dead_code)]
16 pub(crate) fn code(&self) -> i32 {
17 self.code
18 }
19}
20
21impl Error for OperationError {
22 fn description(&self) -> &str {
23 "Operation failed."
24 }
25
26 fn cause(&self) -> Option<&Error> {
27 None
28 }
29}
30
31impl fmt::Display for OperationError {
32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33 writeln!(f, "Operation failed")
34 }
35}
36
37#[derive(Debug, Copy, Clone, PartialEq, Eq)]
38pub enum MessageLevel {
39 Error,
40 Warning,
41 Info,
42
43 #[doc(hidden)]
44 __Nonexhaustive,
45}
46
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct Message {
49 level: MessageLevel,
50 msg: String,
51}
52
53impl Message {
54 pub(crate) fn new(level: MessageLevel, msg: String) -> Self {
55 Self { level, msg }
56 }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq)]
60pub enum Item<T> {
61 Data(T),
62 Message(Message),
63 Error(OperationError),
64
65 #[doc(hidden)]
66 __Nonexhaustive,
67}
68
69impl<T> Item<T> {
70 pub fn as_data(&self) -> Option<&T> {
71 match self {
72 Item::Data(t) => Some(t),
73 _ => None,
74 }
75 }
76
77 pub fn as_message(&self) -> Option<&Message> {
78 match self {
79 Item::Message(m) => Some(m),
80 _ => None,
81 }
82 }
83
84 pub fn as_error(&self) -> Option<&OperationError> {
85 match self {
86 Item::Error(e) => Some(e),
87 _ => None,
88 }
89 }
90}
91
92type ErrorCause = Error + Send + Sync + 'static;
93
94#[derive(Debug, Copy, Clone, PartialEq, Eq)]
96pub enum ErrorKind {
97 SpawnFailed,
98 ParseFailed,
99}
100
101impl ErrorKind {
102 pub(crate) fn error(self) -> P4Error {
103 P4Error::new(self)
104 }
105}
106
107impl fmt::Display for ErrorKind {
108 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109 match *self {
110 ErrorKind::SpawnFailed => write!(f, "Failed to launch P4 command."),
111 ErrorKind::ParseFailed => write!(f, "Failed to parse P4 output."),
112 }
113 }
114}
115
116#[derive(Debug)]
117pub struct P4Error {
118 kind: ErrorKind,
119 context: Option<String>,
120 cause: Option<Box<ErrorCause>>,
121}
122
123impl P4Error {
124 pub(crate) fn new(kind: ErrorKind) -> Self {
125 Self {
126 kind,
127 context: None,
128 cause: None,
129 }
130 }
131
132 pub(crate) fn set_context<S>(mut self, context: S) -> Self
133 where
134 S: Into<String>,
135 {
136 let context = context.into();
137 self.context = Some(context);
138 self
139 }
140
141 pub(crate) fn set_cause<E>(mut self, cause: E) -> Self
142 where
143 E: Error + Send + Sync + 'static,
144 {
145 let cause = Box::new(cause);
146 self.cause = Some(cause);
147 self
148 }
149
150 pub fn kind(&self) -> ErrorKind {
152 self.kind
153 }
154}
155
156impl Error for P4Error {
157 fn description(&self) -> &str {
158 "Staging failed."
159 }
160
161 fn cause(&self) -> Option<&Error> {
162 self.cause.as_ref().map(|c| {
163 let c: &Error = c.as_ref();
164 c
165 })
166 }
167}
168
169impl fmt::Display for P4Error {
170 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171 writeln!(f, "Operation failed: {}", self.kind)?;
172 if let Some(ref context) = self.context {
173 writeln!(f, "{}", context)?;
174 }
175 if let Some(ref cause) = self.cause {
176 writeln!(f, "Cause: {}", cause)?;
177 }
178 Ok(())
179 }
180}