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}