neli/
attr.rs

1//! Shared attribute code for all types of netlink attributes.
2//!  
3//! This module is relatively small right now and will eventually
4//! contain more code once type parameters in associated
5//! types defined in traits are stabilized. Due to `neli` being
6//! supported on stable and nightly, I cannot currently use
7//! this feature and have opted to define implementations of the
8//! trait separately for [`Rtattr`][crate::rtnl::Rtattr] and
9//! [`Nlattr`][crate::genl::Nlattr] types in the
10//! `rtnl.rs` and `genl.rs` modules respectively.
11
12use std::{io::Cursor, slice::Iter};
13
14use crate::{
15    FromBytes, FromBytesWithInput, FromBytesWithInputBorrowed, Size, ToBytes,
16    err::{DeError, SerError},
17    types::Buffer,
18};
19
20/// Trait that defines shared operations for netlink attributes.
21/// Currently, this applies to generic netlink and routing netlink
22/// attributes.
23pub trait Attribute<T> {
24    /// Get the payload of the given attribute.
25    ///
26    /// Due to Rust's requirement that all elements of a [`Vec`] are of
27    /// the same type, payloads are represented as a byte buffer so
28    /// that nested attributes that contain multiple types for the
29    /// payload can be type checked before serialization yet still
30    /// contained all in the same top level attribute.
31    fn payload(&self) -> &Buffer;
32
33    /// Set the payload to a data type that implements [`ToBytes`] -
34    /// this function will overwrite the current payload.
35    ///
36    /// This method serializes the `payload` parameter and stores
37    /// the resulting byte buffer as the payload.
38    fn set_payload<P>(&mut self, payload: &P) -> Result<(), SerError>
39    where
40        P: Size + ToBytes;
41
42    /// Get an [`Nlattr`][crate::genl::Nlattr] payload as the
43    /// provided type parameter, `R`.
44    fn get_payload_as<R>(&self) -> Result<R, DeError>
45    where
46        R: FromBytes,
47    {
48        R::from_bytes(&mut Cursor::new(self.payload().as_ref()))
49    }
50
51    /// Get an [`Nlattr`][crate::genl::Nlattr] payload as the
52    /// provided type parameter, `R`.
53    fn get_payload_as_with_len<R>(&self) -> Result<R, DeError>
54    where
55        R: FromBytesWithInput<Input = usize>,
56    {
57        R::from_bytes_with_input(
58            &mut Cursor::new(self.payload().as_ref()),
59            self.payload().len(),
60        )
61    }
62
63    /// Get an [`Nlattr`][crate::genl::Nlattr] payload as the
64    /// provided type parameter, `R`. This method borrows the data instead
65    /// of copying it.
66    fn get_payload_as_with_len_borrowed<'a, R>(&'a self) -> Result<R, DeError>
67    where
68        R: FromBytesWithInputBorrowed<'a, Input = usize>,
69    {
70        R::from_bytes_with_input(
71            &mut Cursor::new(self.payload().as_ref()),
72            self.payload().len(),
73        )
74    }
75}
76
77/// Handle returned for traversing nested attribute structures
78pub enum AttrHandle<'a, O, I> {
79    /// Owned vector
80    Owned(O),
81    /// Vector reference
82    Borrowed(&'a [I]),
83}
84
85impl<'a, O, I> AttrHandle<'a, O, I>
86where
87    O: AsRef<[I]>,
88{
89    /// Create new [`AttrHandle`]
90    pub fn new(owned: O) -> Self {
91        AttrHandle::Owned(owned)
92    }
93
94    /// Create new borrowed [`AttrHandle`]
95    pub fn new_borrowed(borrowed: &'a [I]) -> Self {
96        AttrHandle::Borrowed(borrowed)
97    }
98
99    /// Pass back iterator over attributes
100    pub fn iter(&self) -> Iter<I> {
101        self.get_attrs().iter()
102    }
103
104    /// Get the underlying owned value as a reference
105    pub fn get_attrs(&self) -> &[I] {
106        match *self {
107            AttrHandle::Owned(ref o) => o.as_ref(),
108            AttrHandle::Borrowed(b) => b,
109        }
110    }
111}