1use std::fmt;
2
3pub use crate::primitives::*;
4pub use crate::traits::Pusher;
5pub use std::{ffi::CStr, fmt::Debug, iter::Iterator};
6
7pub fn dump_hex(buf: &[u8]) {
8 let mut len = 0;
9 for chunk in buf.chunks(16) {
10 print!("{len:04x?}: ");
11 print!("{chunk:02x?} ");
12 for b in chunk {
13 if b.is_ascii() && !b.is_ascii_control() {
14 print!("{}", char::from_u32(*b as u32).unwrap());
15 } else {
16 print!(".");
17 }
18 }
19 println!();
20 len += chunk.len();
21 }
22}
23
24pub fn dump_assert_eq(left: &[u8], right: &[u8]) {
25 if left.len() != right.len() {
26 dump_hex(left);
27 dump_hex(right);
28 panic!("Length mismatched");
29 }
30 if let Some(pos) = left.iter().zip(right.iter()).position(|(l, r)| *l != *r) {
31 println!();
32 println!("Left:");
33 dump_hex(left);
34 println!();
35 println!("Right:");
36 dump_hex(right);
37 panic!("Differ at byte {pos} (0x{pos:x?})");
38 }
39}
40
41pub struct FormatBinStr<T: AsRef<[u8]>>(pub T);
42impl<T: AsRef<[u8]>> Debug for FormatBinStr<T> {
43 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
44 let bstr = self.0.as_ref();
46 if let Ok(cstr) = CStr::from_bytes_with_nul(bstr) {
47 write!(fmt, "{cstr:?}")?;
48 } else {
49 for c in bstr.chunks(127) {
50 let mut buf = [0u8; 128];
51 buf[..c.len()].clone_from_slice(c);
52 write!(fmt, "{:?}", CStr::from_bytes_until_nul(&buf).unwrap())?;
53 }
54 };
55 Ok(())
56 }
57}
58
59pub struct FormatIter<I: Iterator<Item = T> + Clone, T: Debug>(pub I);
60
61impl<I: Iterator<Item = T> + Clone, T: Debug> Debug for FormatIter<I, T> {
62 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
63 let mut f = fmt.debug_list();
64 for item in self.0.clone() {
65 f.entry(&item);
66 }
67 f.finish()
68 }
69}
70
71pub struct FormatHex<T: AsRef<[u8]>>(pub T);
72
73impl<T: AsRef<[u8]>> Debug for FormatHex<T> {
74 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(fmt, "\"")?;
76 for i in self.0.as_ref() {
77 write!(fmt, "{i:02x}")?
78 }
79 write!(fmt, "\"")?;
80 Ok(())
81 }
82}
83
84pub struct FormatMac<T: AsRef<[u8]>>(pub T);
85
86impl<T: AsRef<[u8]>> Debug for FormatMac<T> {
87 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
88 let mut first = true;
89 for i in self.0.as_ref() {
90 if !first {
91 write!(fmt, ":")?;
92 }
93 first = false;
94 write!(fmt, "{i:02x}")?;
95 }
96 Ok(())
97 }
98}
99
100pub struct FormatEnum<T: Debug>(pub u64, pub fn(u64) -> Option<T>);
101
102impl<T: Debug> Debug for FormatEnum<T> {
103 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
104 write!(fmt, "{} ", self.0)?;
105
106 if let Some(var) = (self.1)(self.0) {
107 write!(fmt, "[{var:?}]")?;
108 } else {
109 write!(fmt, "(unknown variant)")?;
110 }
111
112 Ok(())
113 }
114}
115
116pub struct FormatFlags<T: Debug>(pub u64, pub fn(u64) -> Option<T>);
117
118impl<T: Debug> Debug for FormatFlags<T> {
119 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
120 write!(fmt, "{} ", self.0)?;
121
122 if self.0 == 0 {
123 write!(fmt, "(empty)")?;
124 return Ok(());
125 }
126
127 let mut seen_variant = false;
128 for i in 0..u64::BITS {
129 let bit = self.0 & (1 << i);
130 if bit == 0 {
131 continue;
132 }
133
134 if !seen_variant {
135 seen_variant = true;
136 write!(fmt, "[")?;
137 } else {
138 write!(fmt, ",")?;
139 }
140
141 if let Some(var) = (self.1)(bit) {
142 write!(fmt, "{var:?}")?;
143 } else {
144 write!(fmt, "(unknown bit {i})")?;
145 }
146 }
147
148 if seen_variant {
149 write!(fmt, "]")?;
150 }
151
152 Ok(())
153 }
154}
155
156pub struct DisplayAsDebug<T>(T);
157
158impl<T: fmt::Display> fmt::Debug for DisplayAsDebug<T> {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 write!(f, "{}", self.0)
161 }
162}
163
164pub struct FlattenErrorContext<T: fmt::Debug>(pub Result<T, ErrorContext>);
165
166impl<T: Debug> fmt::Debug for FlattenErrorContext<T> {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 match &self.0 {
169 Ok(ok) => ok.fmt(f),
170 Err(err) => {
171 f.write_str("Err(")?;
172 err.fmt(f)?;
173 f.write_str(")")
174 }
175 }
176 }
177}
178
179pub struct MapFormatArray<I, T, M, D>(pub T, pub M)
180where
181 T: Clone + Iterator<Item = Result<I, ErrorContext>>,
182 M: Clone + FnMut(I) -> D,
183 D: fmt::Debug;
184
185impl<I, T, M, D> fmt::Debug for MapFormatArray<I, T, M, D>
186where
187 T: Clone + Iterator<Item = Result<I, ErrorContext>>,
188 M: Clone + FnMut(I) -> D,
189 D: fmt::Debug,
190{
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 let mut f = f.debug_list();
193 for item in self.0.clone() {
194 f.entry(&FlattenErrorContext(item.map(self.1.clone())));
195 }
196 f.finish()
197 }
198}
199
200pub const NLA_F_NESTED: u16 = 1 << 15;
201pub const NLA_F_NET_BYTEORDER: u16 = 1 << 14;
202
203pub const fn nla_type(r#type: u16) -> u16 {
204 r#type & (!(NLA_F_NESTED | NLA_F_NET_BYTEORDER))
205}
206
207pub const NLA_ALIGNTO: usize = 4;
208
209pub const fn align_up(len: usize, alignment: usize) -> usize {
210 ((len) + alignment - 1) & !(alignment - 1)
211}
212
213pub const fn nla_align_up(len: usize) -> usize {
214 ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1)
215}
216
217pub fn align(buf: &mut Vec<u8>) {
218 let len = buf.len();
219 buf.extend(std::iter::repeat_n(0u8, nla_align_up(len) - len));
220}
221
222pub fn push_nested_header(buf: &mut Vec<u8>, r#type: u16) -> usize {
224 push_header_type(buf, r#type, 0, true)
225}
226
227pub fn push_header(buf: &mut Vec<u8>, r#type: u16, len: u16) -> usize {
229 push_header_type(buf, r#type, len, false)
230}
231
232pub fn write_header(buf: &mut Vec<u8>, r#type: u16) -> usize {
234 push_header_type(buf, r#type, 0, false)
235}
236
237fn push_header_type(buf: &mut Vec<u8>, mut r#type: u16, len: u16, is_nested: bool) -> usize {
240 align(buf);
241
242 let header_offset = buf.len();
243
244 if is_nested {
245 r#type |= NLA_F_NESTED;
246 }
247
248 buf.extend((len + 4).to_ne_bytes());
250 buf.extend(r#type.to_ne_bytes());
251
252 header_offset
253}
254
255pub fn push_pad(buf: &mut Vec<u8>, pad_type: u16, alignment: usize) {
256 assert!(alignment.is_power_of_two());
257 if alignment <= 4 {
258 return;
259 }
260
261 align(buf);
262
263 let needed = align_up(buf.len(), alignment) - buf.len();
264
265 if needed == 0 {
266 return;
267 }
268
269 push_header(buf, pad_type, (needed - 4) as u16);
270 buf.extend(std::iter::repeat_n(0, needed - 4));
271}
272
273pub fn finalize_nested_header(buf: &mut Vec<u8>, offset: usize) {
274 align(buf);
275
276 let len = (buf.len() - offset) as u16;
277 buf[offset..(offset + 2)].copy_from_slice(&len.to_ne_bytes());
278}
279
280#[derive(Debug, Clone, Copy, Default)]
282pub struct IterableChunks<'buf> {
283 pub buf: &'buf [u8],
285 pub pos: usize,
287}
288
289impl<'buf> IterableChunks<'buf> {
290 pub fn new(buf: &'buf [u8]) -> Self {
291 Self { buf, pos: 0 }
292 }
293 pub fn is_empty(&self) -> bool {
294 self.buf.len() == self.pos
295 }
296}
297
298impl<'buf> Iterator for IterableChunks<'buf> {
299 type Item = (Header, &'buf [u8]);
300 fn next(&mut self) -> Option<Self::Item> {
301 chop_header(self.buf, &mut self.pos)
302 }
303}
304
305#[derive(Debug, Clone, Copy)]
306pub struct Header {
307 pub r#type: u16,
308 pub is_nested: bool,
309}
310
311pub fn chop_header<'a>(buf: &'a [u8], pos: &mut usize) -> Option<(Header, &'a [u8])> {
312 let buf = &buf[*pos..];
313
314 if buf.len() < 4 {
315 return None;
316 }
317
318 let len = parse_u16(&buf[0..2]).unwrap();
319 let r#type = parse_u16(&buf[2..4]).unwrap();
320
321 let next_len = nla_align_up(len as usize);
322
323 if len < 4 || buf.len() < len as usize {
324 return None;
325 }
326
327 let next = &buf[4..len as usize];
328 *pos += next_len.min(buf.len());
329
330 Some((
331 Header {
332 r#type: nla_type(r#type),
333 is_nested: r#type & NLA_F_NESTED != 0,
334 },
335 next,
336 ))
337}
338
339#[deprecated = "Use netlink_bindings::traits::Pusher instead"]
341pub use crate::traits::Pusher as Rec;
342
343#[derive(Debug, Clone, PartialEq, Eq)]
344pub enum ErrorReason {
345 AttrMissing,
347 ParsingError,
349 UnknownAttr,
351}
352
353#[derive(Clone, PartialEq, Eq)]
354pub struct ErrorContext {
355 pub attrs: &'static str,
356 pub attr: Option<&'static str>,
357 pub offset: usize,
358 pub reason: ErrorReason,
359}
360
361impl std::error::Error for ErrorContext {}
362
363impl From<ErrorContext> for std::io::Error {
364 fn from(value: ErrorContext) -> Self {
365 Self::other(value)
366 }
367}
368
369impl fmt::Debug for ErrorContext {
370 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371 f.debug_struct("ErrorContext")
372 .field("message", &DisplayAsDebug(&self))
373 .field("reason", &self.reason)
374 .field("attrs", &self.attrs)
375 .field("attr", &self.attr)
376 .field("offset", &self.offset)
377 .finish()
378 }
379}
380
381impl fmt::Display for ErrorContext {
382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383 let attrs = self.attrs;
384 if matches!(self.reason, ErrorReason::AttrMissing) {
385 let attr = self.attr.unwrap();
386 write!(f, "Missing attribute {attr:?} in {attrs:?}")?;
387 return Ok(());
388 } else {
389 write!(f, "Error parsing ")?;
390 if let Some(attr) = self.attr {
391 write!(f, "attribute {attr:?} of {attrs:?}")?;
392 } else {
393 write!(f, "header of {attrs:?}")?;
394 if matches!(self.reason, ErrorReason::UnknownAttr) {
395 write!(f, " (unknown attribute)")?;
396 }
397 }
398 }
399 write!(f, " at offset {} (0x{:02x})", self.offset, self.offset)?;
400 Ok(())
401 }
402}
403
404impl ErrorContext {
405 #[cold]
406 pub(crate) fn new(
407 attrs: &'static str,
408 attr: Option<&'static str>,
409 orig_loc: usize,
410 loc: usize,
411 ) -> ErrorContext {
412 let ctx = ErrorContext {
413 attrs,
414 attr,
415 offset: Self::calc_offset(orig_loc, loc),
416 reason: if attr.is_some() {
417 ErrorReason::ParsingError
418 } else {
419 ErrorReason::UnknownAttr
420 },
421 };
422
423 if cfg!(test) {
424 panic!("{ctx}")
425 } else {
426 ctx
427 }
428 }
429
430 #[cold]
431 pub(crate) fn new_missing(
432 attrs: &'static str,
433 attr: &'static str,
434 orig_loc: usize,
435 loc: usize,
436 ) -> ErrorContext {
437 let ctx = ErrorContext {
438 attrs,
439 attr: Some(attr),
440 offset: Self::calc_offset(orig_loc, loc),
441 reason: ErrorReason::AttrMissing,
442 };
443
444 if cfg!(test) {
445 panic!("{ctx}")
446 } else {
447 ctx
448 }
449 }
450
451 pub(crate) fn calc_offset(orig_loc: usize, loc: usize) -> usize {
452 if orig_loc <= loc && loc - orig_loc <= u16::MAX as usize {
453 loc - orig_loc
454 } else {
455 0
456 }
457 }
458}
459
460#[derive(Clone, Copy)]
461pub struct MultiAttrIterable<I, T, V>
462where
463 I: Iterator<Item = Result<T, ErrorContext>>,
464{
465 pub(crate) inner: I,
466 pub(crate) f: fn(T) -> Option<V>,
467}
468
469impl<I, T, V> MultiAttrIterable<I, T, V>
470where
471 I: Iterator<Item = Result<T, ErrorContext>>,
472{
473 pub fn new(inner: I, f: fn(T) -> Option<V>) -> Self {
474 Self { inner, f }
475 }
476}
477
478impl<I, T, V> Iterator for MultiAttrIterable<I, T, V>
479where
480 I: Iterator<Item = Result<T, ErrorContext>>,
481{
482 type Item = V;
483 fn next(&mut self) -> Option<Self::Item> {
484 match self.inner.next() {
485 Some(Ok(val)) => (self.f)(val),
486 _ => None,
487 }
488 }
489}
490
491#[derive(Clone, Copy, Default)]
492pub struct ArrayIterable<I, T>
493where
494 I: Iterator<Item = Result<T, ErrorContext>>,
495{
496 pub(crate) inner: I,
497}
498
499impl<I, T> ArrayIterable<I, T>
500where
501 I: Iterator<Item = Result<T, ErrorContext>>,
502{
503 pub fn new(inner: I) -> Self {
504 Self { inner }
505 }
506}
507
508impl<I, T> Iterator for ArrayIterable<I, T>
509where
510 I: Iterator<Item = Result<T, ErrorContext>>,
511{
512 type Item = T;
513 fn next(&mut self) -> Option<Self::Item> {
514 match self.inner.next() {
515 Some(Ok(val)) => Some(val),
516 _ => None,
517 }
518 }
519}
520
521#[derive(Debug)]
522pub enum RequestBuf<'a> {
523 Ref(&'a mut Vec<u8>),
524 Own(Vec<u8>),
525}
526
527impl RequestBuf<'_> {
528 pub fn buf(&self) -> &Vec<u8> {
529 match self {
530 RequestBuf::Ref(buf) => buf,
531 RequestBuf::Own(buf) => buf,
532 }
533 }
534
535 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
536 match self {
537 RequestBuf::Ref(buf) => buf,
538 RequestBuf::Own(buf) => buf,
539 }
540 }
541}
542
543impl Pusher for RequestBuf<'_> {
544 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
545 self.buf_mut()
546 }
547 fn as_vec(&self) -> &Vec<u8> {
548 self.buf()
549 }
550}
551
552pub struct PushWriter<Prev: Pusher> {
553 pub(crate) prev: Option<Prev>,
554 pub(crate) header_offset: Option<usize>,
555}
556
557impl<Prev: Pusher> std::ops::Deref for PushWriter<Prev> {
558 type Target = Vec<u8>;
559 fn deref(&self) -> &Self::Target {
560 self.as_vec()
561 }
562}
563
564impl<Prev: Pusher> std::ops::DerefMut for PushWriter<Prev> {
565 fn deref_mut(&mut self) -> &mut Self::Target {
566 self.as_vec_mut()
567 }
568}
569
570impl<Prev: Pusher> std::io::Write for PushWriter<Prev> {
571 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
572 self.as_vec_mut().write(buf)
573 }
574 fn flush(&mut self) -> std::io::Result<()> {
575 self.as_vec_mut().flush()
576 }
577}
578
579impl<Prev: Pusher> Pusher for PushWriter<Prev> {
580 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
581 self.prev.as_mut().unwrap().as_vec_mut()
582 }
583 fn as_vec(&self) -> &Vec<u8> {
584 self.prev.as_ref().unwrap().as_vec()
585 }
586}
587
588impl<Prev: Pusher> PushWriter<Prev> {
589 pub fn new(prev: Prev) -> Self {
590 Self {
591 prev: Some(prev),
592 header_offset: None,
593 }
594 }
595 pub fn end_nested(mut self) -> Prev {
596 let mut prev = self.prev.take().unwrap();
597 if let Some(header_offset) = &self.header_offset {
598 finalize_nested_header(prev.as_vec_mut(), *header_offset);
599 }
600 prev
601 }
602}
603
604impl<Prev: Pusher> Drop for PushWriter<Prev> {
605 fn drop(&mut self) {
606 if let Some(prev) = &mut self.prev {
607 if let Some(header_offset) = &self.header_offset {
608 finalize_nested_header(prev.as_vec_mut(), *header_offset);
609 }
610 }
611 }
612}
613
614pub fn get_bits(buf: &[u8], byte_off: usize, bit_off: usize, bits: usize) -> u32 {
615 assert!(bit_off < 8);
616 assert!(bits <= 32);
617
618 let max_bytes = (bit_off + bits).div_ceil(8);
619 let first = byte_off;
620 let last = byte_off + max_bytes;
621
622 let mut reg_buf = [0u8; 8];
623 reg_buf[..max_bytes].copy_from_slice(&buf[first..last]);
624 let reg = u64::from_le_bytes(reg_buf) << (64 - bit_off - bits) >> (64 - bits);
625 reg.to_le() as u32
626}
627
628pub fn set_bits(buf: &mut [u8], byte_off: usize, bit_off: usize, bits: usize, val: u32) {
629 assert!(bit_off < 8);
630 assert!(bits <= 32);
631
632 let max_bytes = (bit_off + bits).div_ceil(8);
633 let first = byte_off;
634 let last = byte_off + max_bytes;
635
636 let mask = !(((1 << bits) - 1) << bit_off);
637 let reg = (val as u64) << bit_off;
638 let mut reg_buf = [0u8; 8];
639 reg_buf[..max_bytes].copy_from_slice(&buf[first..last]);
640 let reg = (u64::from_le_bytes(reg_buf) & mask) | reg;
641 let reg_buf = reg.to_le_bytes();
642 buf[first..last].copy_from_slice(®_buf[..max_bytes])
643}
644
645#[cfg(test)]
646mod tests {
647 use super::*;
648
649 #[test]
650 fn test_get_bits_basic() {
651 let buf = &[0b1010_0110u8, 0b0000_1100];
652
653 assert_eq!(get_bits(buf, 0, 0, 4), 0b0110);
654 assert_eq!(get_bits(buf, 0, 4, 4), 0b1010);
655 assert_eq!(get_bits(buf, 0, 4, 8), 0b1100_1010);
656 }
657
658 #[test]
659 fn test_set_bits_basic() {
660 let buf = &mut [0u8; 2];
661
662 set_bits(buf, 0, 0, 4, 0b0110);
663 assert_eq!(buf[0], 0b0110);
664
665 set_bits(buf, 0, 4, 4, 0b1111);
666 assert_eq!(buf[0], 0b1111_0110);
667
668 set_bits(buf, 0, 4, 8, 0b1100_1010);
669 assert_eq!(buf, &[0b1010_0110, 0b0000_1100]);
670 }
671}