1use serde::de::{self, Visitor};
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use std::fmt;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7pub enum ParseContext {
8 DatagramHeader,
9 DatagramHeaderVersion,
10 AgentAddress,
11 SubAgentId,
12 SequenceNumber,
13 Uptime,
14 NumSamples,
15 SampleDataFormat,
16 SampleLength,
17 SampleData,
18 FlowSample,
19 CounterSample,
20 ExpandedFlowSample,
21 ExpandedCounterSample,
22 DiscardedPacket,
23}
24
25impl fmt::Display for ParseContext {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 let s = match self {
28 ParseContext::DatagramHeader => "datagram header",
29 ParseContext::DatagramHeaderVersion => "datagram header version",
30 ParseContext::AgentAddress => "agent address",
31 ParseContext::SubAgentId => "sub_agent_id",
32 ParseContext::SequenceNumber => "sequence_number",
33 ParseContext::Uptime => "uptime",
34 ParseContext::NumSamples => "num_samples",
35 ParseContext::SampleDataFormat => "sample data_format",
36 ParseContext::SampleLength => "sample length",
37 ParseContext::SampleData => "sample data",
38 ParseContext::FlowSample => "flow sample",
39 ParseContext::CounterSample => "counter sample",
40 ParseContext::ExpandedFlowSample => "expanded flow sample",
41 ParseContext::ExpandedCounterSample => "expanded counter sample",
42 ParseContext::DiscardedPacket => "discarded packet",
43 };
44 f.write_str(s)
45 }
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum ParseErrorKind {
51 InvalidAddressType,
52 NomError(nom::error::ErrorKind),
53}
54
55impl fmt::Display for ParseErrorKind {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 match self {
58 ParseErrorKind::InvalidAddressType => f.write_str("InvalidAddressType"),
59 ParseErrorKind::NomError(kind) => write!(f, "{kind:?}"),
60 }
61 }
62}
63
64impl Serialize for ParseErrorKind {
65 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
66 serializer.serialize_str(&self.to_string())
67 }
68}
69
70impl<'de> Deserialize<'de> for ParseErrorKind {
71 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
72 struct ParseErrorKindVisitor;
73
74 impl<'de> Visitor<'de> for ParseErrorKindVisitor {
75 type Value = ParseErrorKind;
76
77 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
78 formatter.write_str("a ParseErrorKind string")
79 }
80
81 fn visit_str<E: de::Error>(self, value: &str) -> Result<ParseErrorKind, E> {
82 if value == "InvalidAddressType" {
83 return Ok(ParseErrorKind::InvalidAddressType);
84 }
85 let kind = match value {
87 "Tag" => nom::error::ErrorKind::Tag,
88 "MapRes" => nom::error::ErrorKind::MapRes,
89 "MapOpt" => nom::error::ErrorKind::MapOpt,
90 "Alt" => nom::error::ErrorKind::Alt,
91 "IsNot" => nom::error::ErrorKind::IsNot,
92 "IsA" => nom::error::ErrorKind::IsA,
93 "SeparatedList" => nom::error::ErrorKind::SeparatedList,
94 "SeparatedNonEmptyList" => nom::error::ErrorKind::SeparatedNonEmptyList,
95 "Many0" => nom::error::ErrorKind::Many0,
96 "Many1" => nom::error::ErrorKind::Many1,
97 "ManyTill" => nom::error::ErrorKind::ManyTill,
98 "Count" => nom::error::ErrorKind::Count,
99 "TakeUntil" => nom::error::ErrorKind::TakeUntil,
100 "LengthValue" => nom::error::ErrorKind::LengthValue,
101 "TagClosure" => nom::error::ErrorKind::TagClosure,
102 "Alpha" => nom::error::ErrorKind::Alpha,
103 "Digit" => nom::error::ErrorKind::Digit,
104 "HexDigit" => nom::error::ErrorKind::HexDigit,
105 "OctDigit" => nom::error::ErrorKind::OctDigit,
106 "AlphaNumeric" => nom::error::ErrorKind::AlphaNumeric,
107 "Space" => nom::error::ErrorKind::Space,
108 "MultiSpace" => nom::error::ErrorKind::MultiSpace,
109 "LengthValueFn" => nom::error::ErrorKind::LengthValueFn,
110 "Eof" => nom::error::ErrorKind::Eof,
111 "Switch" => nom::error::ErrorKind::Switch,
112 "TagBits" => nom::error::ErrorKind::TagBits,
113 "OneOf" => nom::error::ErrorKind::OneOf,
114 "NoneOf" => nom::error::ErrorKind::NoneOf,
115 "Char" => nom::error::ErrorKind::Char,
116 "CrLf" => nom::error::ErrorKind::CrLf,
117 "RegexpMatch" => nom::error::ErrorKind::RegexpMatch,
118 "RegexpMatches" => nom::error::ErrorKind::RegexpMatches,
119 "RegexpFind" => nom::error::ErrorKind::RegexpFind,
120 "RegexpCapture" => nom::error::ErrorKind::RegexpCapture,
121 "RegexpCaptures" => nom::error::ErrorKind::RegexpCaptures,
122 "TakeWhile1" => nom::error::ErrorKind::TakeWhile1,
123 "Complete" => nom::error::ErrorKind::Complete,
124 "Fix" => nom::error::ErrorKind::Fix,
125 "Escaped" => nom::error::ErrorKind::Escaped,
126 "EscapedTransform" => nom::error::ErrorKind::EscapedTransform,
127 "NonEmpty" => nom::error::ErrorKind::NonEmpty,
128 "ManyMN" => nom::error::ErrorKind::ManyMN,
129 "Not" => nom::error::ErrorKind::Not,
130 "Permutation" => nom::error::ErrorKind::Permutation,
131 "Verify" => nom::error::ErrorKind::Verify,
132 "TakeTill1" => nom::error::ErrorKind::TakeTill1,
133 "TakeWhileMN" => nom::error::ErrorKind::TakeWhileMN,
134 "TooLarge" => nom::error::ErrorKind::TooLarge,
135 "Many0Count" => nom::error::ErrorKind::Many0Count,
136 "Many1Count" => nom::error::ErrorKind::Many1Count,
137 "Float" => nom::error::ErrorKind::Float,
138 "Satisfy" => nom::error::ErrorKind::Satisfy,
139 "Fail" => nom::error::ErrorKind::Fail,
140 _ => {
141 return Err(de::Error::unknown_variant(
142 value,
143 &["InvalidAddressType", "<nom ErrorKind variant>"],
144 ));
145 }
146 };
147 Ok(ParseErrorKind::NomError(kind))
148 }
149 }
150
151 deserializer.deserialize_str(ParseErrorKindVisitor)
152 }
153}
154
155#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
157pub enum SflowError {
158 Incomplete {
160 available: usize,
162 expected: Option<usize>,
164 context: ParseContext,
166 },
167 UnsupportedVersion {
169 version: u32,
171 },
172 ParseError {
174 offset: usize,
176 context: ParseContext,
178 kind: ParseErrorKind,
180 },
181 TooManySamples {
183 count: u32,
185 max: u32,
187 },
188}
189
190impl fmt::Display for SflowError {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 match self {
193 SflowError::Incomplete {
194 available,
195 expected: None,
196 context,
197 } => {
198 write!(
199 f,
200 "Incomplete data: only {available} bytes available ({context})"
201 )
202 }
203 SflowError::Incomplete {
204 available,
205 expected: Some(exp),
206 context,
207 } => {
208 write!(
209 f,
210 "Incomplete data: only {available} bytes available, expected {exp} ({context})"
211 )
212 }
213 SflowError::UnsupportedVersion { version } => {
214 write!(f, "Unsupported sFlow version: {version} (expected 5)")
215 }
216 SflowError::ParseError {
217 offset,
218 context,
219 kind,
220 } => {
221 write!(f, "Parse error at offset {offset}: {kind} ({context})")
222 }
223 SflowError::TooManySamples { count, max } => {
224 write!(f, "Too many samples: {count} exceeds maximum of {max}")
225 }
226 }
227 }
228}
229
230impl std::error::Error for SflowError {}