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::{
13    io::Cursor,
14    slice::{Iter, IterMut},
15};
16
17use crate::{
18    err::{DeError, SerError},
19    types::Buffer,
20    FromBytes, FromBytesWithInput, Size, ToBytes,
21};
22
23/// Trait that defines shared operations for netlink attributes.
24/// Currently, this applies to generic netlink and routing netlink
25/// attributes.
26pub trait Attribute<T> {
27    /// Get the payload of the given attribute.
28    ///
29    /// Due to Rust's requirement that all elements of a [`Vec`] are of
30    /// the same type, payloads are represented as a byte buffer so
31    /// that nested attributes that contain multiple types for the
32    /// payload can be type checked before serialization yet still
33    /// contained all in the same top level attribute.
34    fn payload(&self) -> &Buffer;
35
36    /// Set the payload to a data type that implements [`ToBytes`] -
37    /// this function will overwrite the current payload.
38    ///
39    /// This method serializes the `payload` parameter and stores
40    /// the resulting byte buffer as the payload.
41    fn set_payload<P>(&mut self, payload: &P) -> Result<(), SerError>
42    where
43        P: Size + ToBytes;
44
45    /// Get an [`Nlattr`][crate::genl::Nlattr] payload as the
46    /// provided type parameter, `R`.
47    fn get_payload_as<'a, R>(&'a self) -> Result<R, DeError>
48    where
49        R: FromBytes<'a>,
50    {
51        R::from_bytes(&mut Cursor::new(self.payload().as_ref()))
52    }
53
54    /// Get an [`Nlattr`][crate::genl::Nlattr] payload as the
55    /// provided type parameter, `R`.
56    fn get_payload_as_with_len<'a, R>(&'a self) -> Result<R, DeError>
57    where
58        R: FromBytesWithInput<'a, Input = usize>,
59    {
60        R::from_bytes_with_input(
61            &mut Cursor::new(self.payload().as_ref()),
62            self.payload().len(),
63        )
64    }
65}
66
67/// Handle returned for traversing nested attribute structures
68pub enum AttrHandle<'a, O, I> {
69    /// Owned vector
70    Owned(O),
71    /// Vector reference
72    Borrowed(&'a [I]),
73}
74
75impl<'a, O, I> AttrHandle<'a, O, I>
76where
77    O: AsRef<[I]>,
78{
79    /// Create new [`AttrHandle`]
80    pub fn new(owned: O) -> Self {
81        AttrHandle::Owned(owned)
82    }
83
84    /// Create new borrowed [`AttrHandle`]
85    pub fn new_borrowed(borrowed: &'a [I]) -> Self {
86        AttrHandle::Borrowed(borrowed)
87    }
88
89    /// Pass back iterator over attributes
90    pub fn iter(&self) -> Iter<I> {
91        self.get_attrs().iter()
92    }
93
94    /// Get the underlying owned value as a reference
95    pub fn get_attrs(&self) -> &[I] {
96        match *self {
97            AttrHandle::Owned(ref o) => o.as_ref(),
98            AttrHandle::Borrowed(b) => b,
99        }
100    }
101}
102
103/// Handle for traversing nested attribute structures mutably
104pub enum AttrHandleMut<'a, O, I> {
105    /// Owned vector
106    Owned(O),
107    /// Vector reference
108    Borrowed(&'a mut [I]),
109}
110
111impl<'a, O, I> AttrHandleMut<'a, O, I>
112where
113    O: AsRef<[I]> + AsMut<[I]>,
114{
115    /// Create new `AttrHandle`
116    pub fn new(owned: O) -> Self {
117        AttrHandleMut::Owned(owned)
118    }
119
120    /// Create new borrowed [`AttrHandleMut`]
121    pub fn new_borrowed(borrowed: &'a mut [I]) -> Self {
122        AttrHandleMut::Borrowed(borrowed)
123    }
124
125    /// Pass back iterator over attributes
126    pub fn iter_mut(&mut self) -> IterMut<I> {
127        self.get_mut_attrs().iter_mut()
128    }
129
130    /// Get the underlying owned value as a mutable reference or
131    /// return [`None`].
132    pub fn get_mut_attrs(&mut self) -> &mut [I] {
133        match self {
134            AttrHandleMut::Owned(ref mut o) => o.as_mut(),
135            AttrHandleMut::Borrowed(b) => b,
136        }
137    }
138}