Skip to main content

bgpkit_parser/parser/bmp/
error.rs

1use crate::bmp::messages::headers::BmpPeerType;
2use crate::bmp::messages::peer_down_notification::PeerDownReason;
3use crate::bmp::messages::route_mirroring::RouteMirroringInfo;
4use crate::bmp::messages::termination_message::{TerminationReason, TerminationTlvType};
5use crate::bmp::messages::BmpMsgType;
6use crate::ParserError;
7use num_enum::TryFromPrimitiveError;
8use std::error::Error;
9use std::fmt::{Display, Formatter};
10
11#[derive(Debug, PartialEq, Clone, Eq)]
12#[non_exhaustive]
13pub enum ParserBmpError {
14    InvalidOpenBmpHeader,
15    UnsupportedOpenBmpMessage,
16    UnknownTlvType,
17    UnknownTlvValue,
18    CorruptedBmpMessage,
19    CorruptedBgpMessage(String),
20    TruncatedBmpMessage,
21    /// Reading BMP framing or a message body failed. Carries the `ErrorKind` and the
22    /// source message; the `io::Error` itself cannot be stored because this enum is
23    /// `Clone` and `Eq`, which `io::Error` is not.
24    IoError {
25        kind: std::io::ErrorKind,
26        message: String,
27    },
28    /// A message type value this crate does not know; carries the raw value.
29    UnknownMessageType(u8),
30}
31
32impl Display for ParserBmpError {
33    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
34        match self {
35            ParserBmpError::InvalidOpenBmpHeader => {
36                write!(f, "Invalid OpenBMP header")
37            }
38            ParserBmpError::UnsupportedOpenBmpMessage => {
39                write!(f, "Unsupported OpenBMP message")
40            }
41            ParserBmpError::CorruptedBmpMessage => {
42                write!(f, "Corrupted BMP message")
43            }
44            ParserBmpError::TruncatedBmpMessage => {
45                write!(f, "Truncated BMP message")
46            }
47            ParserBmpError::UnknownTlvType => {
48                write!(f, "Unknown TLV type")
49            }
50            ParserBmpError::UnknownTlvValue => {
51                write!(f, "Unknown TLV value")
52            }
53            ParserBmpError::CorruptedBgpMessage(s) => {
54                write!(f, "Corrupted BGP message: {}", s)
55            }
56            ParserBmpError::IoError { kind, message } => {
57                write!(f, "BMP read error ({:?}): {}", kind, message)
58            }
59            ParserBmpError::UnknownMessageType(value) => {
60                write!(f, "Unknown BMP message type: {}", value)
61            }
62        }
63    }
64}
65
66impl Error for ParserBmpError {}
67
68impl From<std::io::Error> for ParserBmpError {
69    fn from(e: std::io::Error) -> Self {
70        ParserBmpError::IoError {
71            kind: e.kind(),
72            message: e.to_string(),
73        }
74    }
75}
76
77impl From<ParserError> for ParserBmpError {
78    fn from(e: ParserError) -> Self {
79        ParserBmpError::CorruptedBgpMessage(e.to_string())
80    }
81}
82
83impl From<TryFromPrimitiveError<BmpMsgType>> for ParserBmpError {
84    fn from(e: TryFromPrimitiveError<BmpMsgType>) -> Self {
85        ParserBmpError::UnknownMessageType(e.number)
86    }
87}
88
89impl From<TryFromPrimitiveError<BmpPeerType>> for ParserBmpError {
90    fn from(_: TryFromPrimitiveError<BmpPeerType>) -> Self {
91        ParserBmpError::CorruptedBmpMessage
92    }
93}
94
95impl From<TryFromPrimitiveError<RouteMirroringInfo>> for ParserBmpError {
96    fn from(_: TryFromPrimitiveError<RouteMirroringInfo>) -> Self {
97        ParserBmpError::CorruptedBmpMessage
98    }
99}
100
101impl From<TryFromPrimitiveError<TerminationTlvType>> for ParserBmpError {
102    fn from(_: TryFromPrimitiveError<TerminationTlvType>) -> Self {
103        ParserBmpError::UnknownTlvType
104    }
105}
106
107impl From<TryFromPrimitiveError<TerminationReason>> for ParserBmpError {
108    fn from(_: TryFromPrimitiveError<TerminationReason>) -> Self {
109        ParserBmpError::UnknownTlvValue
110    }
111}
112
113impl From<TryFromPrimitiveError<PeerDownReason>> for ParserBmpError {
114    fn from(_: TryFromPrimitiveError<PeerDownReason>) -> Self {
115        ParserBmpError::UnknownTlvValue
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122
123    #[test]
124    fn test_parser_error_display() {
125        assert_eq!(
126            ParserBmpError::InvalidOpenBmpHeader.to_string(),
127            "Invalid OpenBMP header"
128        );
129        assert_eq!(
130            ParserBmpError::UnsupportedOpenBmpMessage.to_string(),
131            "Unsupported OpenBMP message"
132        );
133        assert_eq!(
134            ParserBmpError::CorruptedBmpMessage.to_string(),
135            "Corrupted BMP message"
136        );
137        assert_eq!(
138            ParserBmpError::CorruptedBgpMessage("test".to_string()).to_string(),
139            "Corrupted BGP message: test"
140        );
141        assert_eq!(
142            ParserBmpError::TruncatedBmpMessage.to_string(),
143            "Truncated BMP message"
144        );
145        assert_eq!(
146            ParserBmpError::UnknownTlvType.to_string(),
147            "Unknown TLV type"
148        );
149        assert_eq!(
150            ParserBmpError::UnknownTlvValue.to_string(),
151            "Unknown TLV value"
152        );
153        assert_eq!(
154            ParserBmpError::IoError {
155                kind: std::io::ErrorKind::UnexpectedEof,
156                message: "unexpected eof".to_string(),
157            }
158            .to_string(),
159            "BMP read error (UnexpectedEof): unexpected eof"
160        );
161        assert_eq!(
162            ParserBmpError::UnknownMessageType(7).to_string(),
163            "Unknown BMP message type: 7"
164        );
165    }
166
167    #[test]
168    fn test_error_conversions() {
169        assert_eq!(
170            ParserBmpError::from(std::io::Error::other("test")),
171            ParserBmpError::IoError {
172                kind: std::io::ErrorKind::Other,
173                message: "test".to_string(),
174            }
175        );
176        assert_eq!(
177            ParserBmpError::from(ParserError::ParseError("test".to_string())),
178            ParserBmpError::CorruptedBgpMessage("Error: test".to_string())
179        );
180        assert_eq!(
181            ParserBmpError::from(TryFromPrimitiveError::<BmpMsgType>::new(0)),
182            ParserBmpError::UnknownMessageType(0)
183        );
184        assert_eq!(
185            ParserBmpError::from(TryFromPrimitiveError::<BmpPeerType>::new(0)),
186            ParserBmpError::CorruptedBmpMessage
187        );
188        assert_eq!(
189            ParserBmpError::from(TryFromPrimitiveError::<RouteMirroringInfo>::new(0)),
190            ParserBmpError::CorruptedBmpMessage
191        );
192        assert_eq!(
193            ParserBmpError::from(TryFromPrimitiveError::<TerminationTlvType>::new(0)),
194            ParserBmpError::UnknownTlvType
195        );
196        assert_eq!(
197            ParserBmpError::from(TryFromPrimitiveError::<TerminationReason>::new(0)),
198            ParserBmpError::UnknownTlvValue
199        );
200        assert_eq!(
201            ParserBmpError::from(TryFromPrimitiveError::<PeerDownReason>::new(0)),
202            ParserBmpError::UnknownTlvValue
203        );
204    }
205}