netlink_packet_core/
done.rs

1// SPDX-License-Identifier: MIT
2
3use std::mem::size_of;
4
5use byteorder::{ByteOrder, NativeEndian};
6use netlink_packet_utils::DecodeError;
7
8use crate::{Emitable, Field, Parseable, Rest};
9
10const CODE: Field = 0..4;
11const EXTENDED_ACK: Rest = 4..;
12const DONE_HEADER_LEN: usize = EXTENDED_ACK.start;
13
14#[derive(Debug, PartialEq, Eq, Clone)]
15#[non_exhaustive]
16pub struct DoneBuffer<T> {
17    buffer: T,
18}
19
20impl<T: AsRef<[u8]>> DoneBuffer<T> {
21    pub fn new(buffer: T) -> DoneBuffer<T> {
22        DoneBuffer { buffer }
23    }
24
25    /// Consume the packet, returning the underlying buffer.
26    pub fn into_inner(self) -> T {
27        self.buffer
28    }
29
30    pub fn new_checked(buffer: T) -> Result<Self, DecodeError> {
31        let packet = Self::new(buffer);
32        packet.check_buffer_length()?;
33        Ok(packet)
34    }
35
36    fn check_buffer_length(&self) -> Result<(), DecodeError> {
37        let len = self.buffer.as_ref().len();
38        if len < DONE_HEADER_LEN {
39            Err(format!(
40                "invalid DoneBuffer: length is {len} but DoneBuffer are \
41                at least {DONE_HEADER_LEN} bytes"
42            )
43            .into())
44        } else {
45            Ok(())
46        }
47    }
48
49    /// Return the error code
50    pub fn code(&self) -> i32 {
51        let data = self.buffer.as_ref();
52        NativeEndian::read_i32(&data[CODE])
53    }
54}
55
56impl<'a, T: AsRef<[u8]> + ?Sized> DoneBuffer<&'a T> {
57    /// Return a pointer to the extended ack attributes.
58    pub fn extended_ack(&self) -> &'a [u8] {
59        let data = self.buffer.as_ref();
60        &data[EXTENDED_ACK]
61    }
62}
63
64impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> DoneBuffer<&'a mut T> {
65    /// Return a mutable pointer to the extended ack attributes.
66    pub fn extended_ack_mut(&mut self) -> &mut [u8] {
67        let data = self.buffer.as_mut();
68        &mut data[EXTENDED_ACK]
69    }
70}
71
72impl<T: AsRef<[u8]> + AsMut<[u8]>> DoneBuffer<T> {
73    /// set the error code field
74    pub fn set_code(&mut self, value: i32) {
75        let data = self.buffer.as_mut();
76        NativeEndian::write_i32(&mut data[CODE], value)
77    }
78}
79
80#[derive(Debug, Default, Clone, PartialEq, Eq)]
81#[non_exhaustive]
82pub struct DoneMessage {
83    pub code: i32,
84    pub extended_ack: Vec<u8>,
85}
86
87impl Emitable for DoneMessage {
88    fn buffer_len(&self) -> usize {
89        size_of::<i32>() + self.extended_ack.len()
90    }
91    fn emit(&self, buffer: &mut [u8]) {
92        let mut buffer = DoneBuffer::new(buffer);
93        buffer.set_code(self.code);
94        buffer.extended_ack_mut().copy_from_slice(&self.extended_ack);
95    }
96}
97
98impl<'buffer, T: AsRef<[u8]> + 'buffer> Parseable<DoneBuffer<&'buffer T>> for DoneMessage {
99    type Error = DecodeError;
100    fn parse(buf: &DoneBuffer<&'buffer T>) -> Result<DoneMessage, DecodeError> {
101        Ok(DoneMessage { code: buf.code(), extended_ack: buf.extended_ack().to_vec() })
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108
109    #[test]
110    fn serialize_and_parse() {
111        let expected = DoneMessage { code: 5, extended_ack: vec![1, 2, 3] };
112
113        let len = expected.buffer_len();
114        assert_eq!(len, size_of::<i32>() + expected.extended_ack.len());
115
116        let mut buf = vec![0; len];
117        expected.emit(&mut buf);
118
119        let done_buf = DoneBuffer::new(&buf);
120        assert_eq!(done_buf.code(), expected.code);
121        assert_eq!(done_buf.extended_ack(), &expected.extended_ack);
122
123        let got = DoneMessage::parse(&done_buf).unwrap();
124        assert_eq!(got, expected);
125    }
126}