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