1use std::fmt;
2
3pub use crate::primitives::*;
4pub use std::{ffi::CStr, fmt::Debug, iter::Iterator};
5
6pub fn dump_hex(buf: &[u8]) {
7 let mut len = 0;
8 for chunk in buf.chunks(16) {
9 print!("{len:04x?}: ");
10 print!("{chunk:02x?} ");
11 for b in chunk {
12 if b.is_ascii() && !b.is_ascii_control() {
13 print!("{}", char::from_u32(*b as u32).unwrap());
14 } else {
15 print!(".");
16 }
17 }
18 println!(".");
19 len += chunk.len();
20 }
21}
22
23pub fn dump_assert_eq(left: &[u8], right: &[u8]) {
24 if left.len() != right.len() {
25 dump_hex(left);
26 dump_hex(right);
27 panic!("Length mismatched");
28 }
29 if let Some(pos) = left.iter().zip(right.iter()).position(|(l, r)| *l != *r) {
30 println!();
31 println!("Left:");
32 dump_hex(left);
33 println!();
34 println!("Right:");
35 dump_hex(right);
36 panic!("Differ at byte {pos} (0x{pos:x?})");
37 }
38}
39
40pub struct FormatHex<'a>(pub &'a [u8]);
41
42impl Debug for FormatHex<'_> {
43 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
44 write!(fmt, "\"")?;
45 for i in self.0 {
46 write!(fmt, "{i:02x}")?
47 }
48 write!(fmt, "\"")?;
49 Ok(())
50 }
51}
52
53pub struct FormatEnum<T: Debug>(pub u64, pub fn(u64) -> Option<T>);
54
55impl<T: Debug> Debug for FormatEnum<T> {
56 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
57 write!(fmt, "{} ", self.0)?;
58
59 if let Some(var) = (self.1)(self.0) {
60 write!(fmt, "[{var:?}]")?;
61 } else {
62 write!(fmt, "(unknown variant)")?;
63 }
64
65 Ok(())
66 }
67}
68
69pub struct FormatFlags<T: Debug>(pub u64, pub fn(u64) -> Option<T>);
70
71impl<T: Debug> Debug for FormatFlags<T> {
72 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
73 write!(fmt, "{} ", self.0)?;
74
75 if self.0 == 0 {
76 write!(fmt, "(empty)")?;
77 return Ok(());
78 }
79
80 let mut seen_variant = false;
81 for i in 0..u64::BITS {
82 let bit = self.0 & (1 << i);
83 if bit == 0 {
84 continue;
85 }
86
87 if !seen_variant {
88 seen_variant = true;
89 write!(fmt, "[")?;
90 } else {
91 write!(fmt, ",")?;
92 }
93
94 if let Some(var) = (self.1)(bit) {
95 write!(fmt, "{var:?}")?;
96 } else {
97 write!(fmt, "(unknown bit {i})")?;
98 }
99 }
100
101 if seen_variant {
102 write!(fmt, "]")?;
103 }
104
105 Ok(())
106 }
107}
108
109pub struct DisplayAsDebug<T>(T);
110
111impl<T: fmt::Display> fmt::Debug for DisplayAsDebug<T> {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 write!(f, "{}", self.0)
114 }
115}
116
117pub struct FlattenErrorContext<T: fmt::Debug>(pub Result<T, ErrorContext>);
118
119impl<T: Debug> fmt::Debug for FlattenErrorContext<T> {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 match &self.0 {
122 Ok(ok) => ok.fmt(f),
123 Err(err) => {
124 f.write_str("Err(")?;
125 err.fmt(f)?;
126 f.write_str(")")
127 }
128 }
129 }
130}
131
132pub const NLA_F_NESTED: u16 = 1 << 15;
133pub const NLA_F_NET_BYTEORDER: u16 = 1 << 14;
134
135pub const fn nla_type(r#type: u16) -> u16 {
136 r#type & (!(NLA_F_NESTED | NLA_F_NET_BYTEORDER))
137}
138
139pub const NLA_ALIGNTO: usize = 4;
140
141pub const fn nla_align_up(len: usize) -> usize {
142 ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1)
143}
144
145pub fn align(buf: &mut Vec<u8>) {
146 let len = buf.len();
147 buf.extend(std::iter::repeat_n(0u8, nla_align_up(len) - len));
148}
149
150pub fn push_nested_header(buf: &mut Vec<u8>, r#type: u16) -> usize {
152 push_header_type(buf, r#type, 0, true)
153}
154
155pub fn push_header(buf: &mut Vec<u8>, r#type: u16, len: u16) -> usize {
157 push_header_type(buf, r#type, len, false)
158}
159
160fn push_header_type(buf: &mut Vec<u8>, mut r#type: u16, len: u16, is_nested: bool) -> usize {
163 align(buf);
164
165 let header_offset = buf.len();
166
167 if is_nested {
168 r#type |= NLA_F_NESTED;
169 }
170
171 buf.extend((len + 4).to_ne_bytes());
173 buf.extend(r#type.to_ne_bytes());
174
175 align(buf);
176
177 header_offset
178}
179
180pub fn finalize_nested_header(buf: &mut Vec<u8>, offset: usize) {
181 align(buf);
182
183 let len = (buf.len() - offset) as u16;
184 buf[offset..(offset + 2)].copy_from_slice(&len.to_ne_bytes());
185}
186
187#[derive(Debug, Clone, Copy)]
188pub struct Header {
189 pub r#type: u16,
190 pub is_nested: bool,
191}
192
193pub fn chop_header<'a>(buf: &'a [u8], pos: &mut usize) -> Option<(Header, &'a [u8])> {
194 let buf = &buf[*pos..];
195
196 if buf.len() < 4 {
197 return None;
198 }
199
200 let len = parse_u16(&buf[0..2]).unwrap();
201 let r#type = parse_u16(&buf[2..4]).unwrap();
202
203 let next_len = nla_align_up(len as usize);
204
205 if len < 4 || buf.len() < len as usize {
206 return None;
207 }
208
209 let next = &buf[4..len as usize];
210 *pos += next_len.min(buf.len());
211
212 Some((
213 Header {
214 r#type: nla_type(r#type),
215 is_nested: r#type & NLA_F_NESTED != 0,
216 },
217 next,
218 ))
219}
220
221pub trait Rec {
222 fn as_rec_mut(&mut self) -> &mut Vec<u8>;
223}
224
225impl Rec for &mut Vec<u8> {
226 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
227 self
228 }
229}
230
231#[derive(Debug, Clone, PartialEq, Eq)]
232pub enum ErrorReason {
233 AttrMissing,
235 ParsingError,
237 UnknownAttr,
239}
240
241#[derive(Clone, PartialEq, Eq)]
242pub struct ErrorContext {
243 pub attrs: &'static str,
244 pub attr: Option<&'static str>,
245 pub offset: usize,
246 pub reason: ErrorReason,
247}
248
249impl std::error::Error for ErrorContext {}
250
251impl From<ErrorContext> for std::io::Error {
252 fn from(value: ErrorContext) -> Self {
253 Self::other(value)
254 }
255}
256
257impl fmt::Debug for ErrorContext {
258 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259 f.debug_struct("ErrorContext")
260 .field("message", &DisplayAsDebug(&self))
261 .field("reason", &self.reason)
262 .field("attrs", &self.attrs)
263 .field("attr", &self.attr)
264 .field("offset", &self.offset)
265 .finish()
266 }
267}
268
269impl fmt::Display for ErrorContext {
270 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271 let attrs = self.attrs;
272 if matches!(self.reason, ErrorReason::AttrMissing) {
273 let attr = self.attr.unwrap();
274 write!(f, "Missing attribute {attr:?} in {attrs:?}")?;
275 return Ok(());
276 } else {
277 write!(f, "Error parsing ")?;
278 if let Some(attr) = self.attr {
279 write!(f, "attribute {attr:?} of {attrs:?}")?;
280 } else {
281 write!(f, "header of {attrs:?}")?;
282 if matches!(self.reason, ErrorReason::UnknownAttr) {
283 write!(f, " (unknown attribute)")?;
284 }
285 }
286 }
287 write!(f, " at offset {}", self.offset)?;
288 Ok(())
289 }
290}
291
292impl ErrorContext {
293 #[cold]
294 pub(crate) fn new(
295 attrs: &'static str,
296 attr: Option<&'static str>,
297 orig_loc: usize,
298 loc: usize,
299 ) -> ErrorContext {
300 let ctx = ErrorContext {
301 attrs,
302 attr,
303 offset: Self::calc_offset(orig_loc, loc),
304 reason: if attr.is_some() {
305 ErrorReason::ParsingError
306 } else {
307 ErrorReason::UnknownAttr
308 },
309 };
310
311 if cfg!(test) {
312 panic!("{ctx}")
313 } else {
314 ctx
315 }
316 }
317
318 #[cold]
319 pub(crate) fn new_missing(
320 attrs: &'static str,
321 attr: &'static str,
322 orig_loc: usize,
323 loc: usize,
324 ) -> ErrorContext {
325 let ctx = ErrorContext {
326 attrs,
327 attr: Some(attr),
328 offset: Self::calc_offset(orig_loc, loc),
329 reason: ErrorReason::AttrMissing,
330 };
331
332 if cfg!(test) {
333 panic!("{ctx}")
334 } else {
335 ctx
336 }
337 }
338
339 pub(crate) fn calc_offset(orig_loc: usize, loc: usize) -> usize {
340 if orig_loc <= loc && loc - orig_loc <= u16::MAX as usize {
341 loc - orig_loc
342 } else {
343 0
344 }
345 }
346}
347
348#[derive(Clone)]
349pub struct MultiAttrIterable<I, T, V>
350where
351 I: Iterator<Item = Result<T, ErrorContext>>,
352{
353 pub(crate) inner: I,
354 pub(crate) f: fn(T) -> Option<V>,
355}
356
357impl<I, T, V> MultiAttrIterable<I, T, V>
358where
359 I: Iterator<Item = Result<T, ErrorContext>>,
360{
361 pub fn new(inner: I, f: fn(T) -> Option<V>) -> Self {
362 Self { inner, f }
363 }
364}
365
366impl<I, T, V> Iterator for MultiAttrIterable<I, T, V>
367where
368 I: Iterator<Item = Result<T, ErrorContext>>,
369{
370 type Item = V;
371 fn next(&mut self) -> Option<Self::Item> {
372 match self.inner.next() {
373 Some(Ok(val)) => (self.f)(val),
374 _ => None,
375 }
376 }
377}
378
379#[derive(Clone)]
380pub struct ArrayIterable<I, T>
381where
382 I: Iterator<Item = Result<T, ErrorContext>>,
383{
384 pub(crate) inner: I,
385}
386
387impl<I, T> ArrayIterable<I, T>
388where
389 I: Iterator<Item = Result<T, ErrorContext>>,
390{
391 pub fn new(inner: I) -> Self {
392 Self { inner }
393 }
394}
395
396impl<I, T> Iterator for ArrayIterable<I, T>
397where
398 I: Iterator<Item = Result<T, ErrorContext>>,
399{
400 type Item = T;
401 fn next(&mut self) -> Option<Self::Item> {
402 match self.inner.next() {
403 Some(Ok(val)) => Some(val),
404 _ => None,
405 }
406 }
407}
408
409#[derive(Debug)]
410pub enum RequestBuf<'a> {
411 Ref(&'a mut Vec<u8>),
412 Own(Vec<u8>),
413}
414
415impl RequestBuf<'_> {
416 pub fn buf(&self) -> &Vec<u8> {
417 match self {
418 RequestBuf::Ref(buf) => buf,
419 RequestBuf::Own(buf) => buf,
420 }
421 }
422
423 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
424 match self {
425 RequestBuf::Ref(buf) => buf,
426 RequestBuf::Own(buf) => buf,
427 }
428 }
429}
430
431impl Rec for RequestBuf<'_> {
432 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
433 self.buf_mut()
434 }
435}