p4_cmd/
error.rs

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    // Keeping around for future use.
15    #[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/// For programmatically processing failures.
95#[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    /// Programmtically process failure.
151    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}