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}