neli/
types.rs

1//! Module containing various types used across the various netlink
2//! structures used in `neli`.
3//!
4//! # Design decisions
5//! These structures are new types rather than type aliases in most
6//! cases to allow the internal representation to change without
7//! resulting in a breaking change.
8
9use crate as neli;
10
11use std::{
12    fmt::{self, Debug},
13    iter::FromIterator,
14    marker::PhantomData,
15    ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not},
16    slice::{Iter, IterMut},
17};
18
19use crate::{
20    attr::{AttrHandle, AttrHandleMut},
21    consts::{genl::NlAttrType, nl::NlType, rtnl::RtaType},
22    genl::Nlattr,
23    nl::Nlmsghdr,
24    rtnl::Rtattr,
25    FromBytes, FromBytesWithInput, Size, ToBytes, TypeSize,
26};
27
28/// A buffer of bytes.
29#[derive(PartialEq, Eq, Size, FromBytesWithInput, ToBytes)]
30pub struct Buffer(#[neli(input)] Vec<u8>);
31
32impl Debug for Buffer {
33    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34        write!(f, "Buffer")
35    }
36}
37
38impl AsRef<[u8]> for Buffer {
39    fn as_ref(&self) -> &[u8] {
40        self.0.as_slice()
41    }
42}
43
44impl AsMut<[u8]> for Buffer {
45    fn as_mut(&mut self) -> &mut [u8] {
46        self.0.as_mut_slice()
47    }
48}
49
50impl<'a> From<&'a [u8]> for Buffer {
51    fn from(slice: &'a [u8]) -> Self {
52        Buffer(Vec::from(slice))
53    }
54}
55
56impl From<Vec<u8>> for Buffer {
57    fn from(vec: Vec<u8>) -> Self {
58        Buffer(vec)
59    }
60}
61
62impl Buffer {
63    /// Create a new general purpose byte buffer.
64    pub fn new() -> Self {
65        Buffer(Vec::new())
66    }
67
68    /// Extend the given buffer with the contents of another slice.
69    pub fn extend_from_slice(&mut self, slice: &[u8]) {
70        self.0.extend_from_slice(slice)
71    }
72
73    /// Get the current length of the buffer.
74    pub fn len(&self) -> usize {
75        self.0.len()
76    }
77
78    /// Check whether the buffer is empty.
79    pub fn is_empty(&self) -> bool {
80        self.0.is_empty()
81    }
82}
83
84impl Default for Buffer {
85    fn default() -> Self {
86        Self::new()
87    }
88}
89
90/// A buffer of netlink messages.
91#[derive(Debug, PartialEq, Eq, Size, FromBytesWithInput, ToBytes)]
92#[neli(from_bytes_bound = "T: NlType")]
93#[neli(from_bytes_bound = "P: FromBytesWithInput<Input = usize>")]
94pub struct NlBuffer<T, P>(#[neli(input)] Vec<Nlmsghdr<T, P>>);
95
96impl<T, P> FromIterator<Nlmsghdr<T, P>> for NlBuffer<T, P> {
97    fn from_iter<I>(i: I) -> Self
98    where
99        I: IntoIterator<Item = Nlmsghdr<T, P>>,
100    {
101        NlBuffer(Vec::from_iter(i))
102    }
103}
104
105impl<T, P> AsRef<[Nlmsghdr<T, P>]> for NlBuffer<T, P> {
106    fn as_ref(&self) -> &[Nlmsghdr<T, P>] {
107        self.0.as_slice()
108    }
109}
110
111impl<T, P> NlBuffer<T, P> {
112    /// Create a new buffer of netlink messages.
113    pub fn new() -> Self {
114        NlBuffer(Vec::new())
115    }
116
117    /// Add a new netlink message to the end of the buffer.
118    pub fn push(&mut self, msg: Nlmsghdr<T, P>) {
119        self.0.push(msg);
120    }
121
122    /// Get a netlink message from the end of the buffer.
123    pub fn pop(&mut self) -> Option<Nlmsghdr<T, P>> {
124        self.0.pop()
125    }
126
127    /// Return an iterator over immutable references to the elements
128    /// in the buffer.
129    pub fn iter(&self) -> Iter<'_, Nlmsghdr<T, P>> {
130        self.0.iter()
131    }
132
133    /// Return an iterator over mutable references to the elements
134    /// in the buffer.
135    pub fn iter_mut(&mut self) -> IterMut<'_, Nlmsghdr<T, P>> {
136        self.0.iter_mut()
137    }
138
139    /// Returns the number of elements in the buffer.
140    pub fn len(&self) -> usize {
141        self.0.len()
142    }
143
144    /// Returns whether the number of elements in the buffer is 0.
145    pub fn is_empty(&self) -> bool {
146        self.0.is_empty()
147    }
148}
149
150impl<T, P> IntoIterator for NlBuffer<T, P> {
151    type Item = Nlmsghdr<T, P>;
152    type IntoIter = <Vec<Nlmsghdr<T, P>> as IntoIterator>::IntoIter;
153
154    fn into_iter(self) -> Self::IntoIter {
155        self.0.into_iter()
156    }
157}
158
159impl<T, P> Default for NlBuffer<T, P> {
160    fn default() -> Self {
161        Self::new()
162    }
163}
164
165/// A buffer of generic netlink attributes.
166#[derive(Debug, PartialEq, Eq, ToBytes, FromBytesWithInput)]
167#[neli(to_bytes_bound = "T: NlAttrType")]
168#[neli(from_bytes_bound = "T: NlAttrType")]
169#[neli(from_bytes_bound = "P: FromBytesWithInput<Input = usize>")]
170pub struct GenlBuffer<T, P>(#[neli(input)] Vec<Nlattr<T, P>>);
171
172impl<T, P> neli::Size for GenlBuffer<T, P>
173where
174    T: Size,
175    P: Size,
176{
177    fn unpadded_size(&self) -> usize {
178        self.0.iter().map(|attr| attr.padded_size()).sum()
179    }
180}
181
182impl<T> GenlBuffer<T, Buffer> {
183    /// Get a data structure with an immutable reference to the
184    /// underlying [`Nlattr`]s.
185    pub fn get_attr_handle(&self) -> AttrHandle<Self, Nlattr<T, Buffer>> {
186        AttrHandle::new_borrowed(self.0.as_ref())
187    }
188
189    /// Get a data structure with a mutable reference to the
190    /// underlying [`Nlattr`]s.
191    pub fn get_attr_handle_mut(&mut self) -> AttrHandleMut<Self, Nlattr<T, Buffer>> {
192        AttrHandleMut::new_borrowed(self.0.as_mut())
193    }
194}
195
196impl<T, P> AsRef<[Nlattr<T, P>]> for GenlBuffer<T, P> {
197    fn as_ref(&self) -> &[Nlattr<T, P>] {
198        self.0.as_slice()
199    }
200}
201
202impl<T, P> AsMut<[Nlattr<T, P>]> for GenlBuffer<T, P> {
203    fn as_mut(&mut self) -> &mut [Nlattr<T, P>] {
204        self.0.as_mut_slice()
205    }
206}
207
208impl<T, P> FromIterator<Nlattr<T, P>> for GenlBuffer<T, P> {
209    fn from_iter<I>(i: I) -> Self
210    where
211        I: IntoIterator<Item = Nlattr<T, P>>,
212    {
213        GenlBuffer(Vec::from_iter(i))
214    }
215}
216
217impl<T, P> IntoIterator for GenlBuffer<T, P> {
218    type Item = Nlattr<T, P>;
219    type IntoIter = <Vec<Nlattr<T, P>> as IntoIterator>::IntoIter;
220
221    fn into_iter(self) -> Self::IntoIter {
222        self.0.into_iter()
223    }
224}
225
226impl<T, P> GenlBuffer<T, P> {
227    /// Create a new buffer of generic netlink attributes.
228    pub fn new() -> Self {
229        GenlBuffer(Vec::new())
230    }
231
232    /// Add a new generic netlink attribute to the end of the buffer.
233    pub fn push(&mut self, attr: Nlattr<T, P>) {
234        self.0.push(attr)
235    }
236
237    /// Get a generic netlink attribute from the end of the buffer.
238    pub fn pop(&mut self) -> Option<Nlattr<T, P>> {
239        self.0.pop()
240    }
241
242    /// Return an iterator over immutable references to the elements
243    /// in the buffer.
244    pub fn iter(&self) -> Iter<'_, Nlattr<T, P>> {
245        self.0.iter()
246    }
247
248    /// Return an iterator over mutable references to the elements
249    /// in the buffer.
250    pub fn iter_mut(&mut self) -> IterMut<'_, Nlattr<T, P>> {
251        self.0.iter_mut()
252    }
253
254    /// Returns the number of elements in the buffer.
255    pub fn len(&self) -> usize {
256        self.0.len()
257    }
258
259    /// Returns whether the number of elements in the buffer is 0.
260    pub fn is_empty(&self) -> bool {
261        self.0.is_empty()
262    }
263}
264
265impl<T, P> Default for GenlBuffer<T, P> {
266    fn default() -> Self {
267        Self::new()
268    }
269}
270
271/// A buffer of rtnetlink attributes.
272#[derive(Debug, FromBytesWithInput, ToBytes)]
273#[neli(from_bytes_bound = "T: RtaType")]
274#[neli(from_bytes_bound = "P: FromBytesWithInput<Input = usize>")]
275pub struct RtBuffer<T, P>(#[neli(input)] Vec<Rtattr<T, P>>);
276
277impl<T, P> neli::Size for RtBuffer<T, P>
278where
279    T: Size,
280    P: Size,
281{
282    fn unpadded_size(&self) -> usize {
283        self.0.iter().map(|attr| attr.padded_size()).sum()
284    }
285}
286
287impl<T> RtBuffer<T, Buffer> {
288    /// Get a data structure with an immutable reference to the
289    /// underlying [`Rtattr`]s.
290    pub fn get_attr_handle(&self) -> AttrHandle<Self, Rtattr<T, Buffer>> {
291        AttrHandle::new_borrowed(self.0.as_ref())
292    }
293
294    /// Get a data structure with a mutable reference to the
295    /// underlying [`Rtattr`]s.
296    pub fn get_attr_handle_mut(&mut self) -> AttrHandleMut<Self, Rtattr<T, Buffer>> {
297        AttrHandleMut::new_borrowed(self.0.as_mut())
298    }
299}
300
301impl<T, P> FromIterator<Rtattr<T, P>> for RtBuffer<T, P> {
302    fn from_iter<I>(i: I) -> Self
303    where
304        I: IntoIterator<Item = Rtattr<T, P>>,
305    {
306        RtBuffer(Vec::from_iter(i))
307    }
308}
309
310impl<T, P> IntoIterator for RtBuffer<T, P> {
311    type Item = Rtattr<T, P>;
312    type IntoIter = <Vec<Rtattr<T, P>> as IntoIterator>::IntoIter;
313
314    fn into_iter(self) -> Self::IntoIter {
315        self.0.into_iter()
316    }
317}
318
319impl<T, P> AsRef<[Rtattr<T, P>]> for RtBuffer<T, P> {
320    fn as_ref(&self) -> &[Rtattr<T, P>] {
321        self.0.as_slice()
322    }
323}
324
325impl<T, P> AsMut<[Rtattr<T, P>]> for RtBuffer<T, P> {
326    fn as_mut(&mut self) -> &mut [Rtattr<T, P>] {
327        self.0.as_mut_slice()
328    }
329}
330
331impl<T, P> RtBuffer<T, P> {
332    /// Create a new buffer of routing netlink attributes.
333    pub fn new() -> Self {
334        RtBuffer(Vec::new())
335    }
336
337    /// Add a new routing netlink attribute to the end of the buffer.
338    pub fn push(&mut self, attr: Rtattr<T, P>) {
339        self.0.push(attr)
340    }
341
342    /// Get a routing netlink attribute from the end of the buffer.
343    pub fn pop(&mut self) -> Option<Rtattr<T, P>> {
344        self.0.pop()
345    }
346
347    /// Return an iterator over immutable references to the elements
348    /// in the buffer.
349    pub fn iter(&self) -> Iter<'_, Rtattr<T, P>> {
350        self.0.iter()
351    }
352
353    /// Return an iterator over mutable references to the elements
354    /// in the buffer.
355    pub fn iter_mut(&mut self) -> IterMut<'_, Rtattr<T, P>> {
356        self.0.iter_mut()
357    }
358
359    /// Returns the number of elements in the buffer.
360    pub fn len(&self) -> usize {
361        self.0.len()
362    }
363
364    /// Returns whether the number of elements in the buffer is 0.
365    pub fn is_empty(&self) -> bool {
366        self.0.is_empty()
367    }
368}
369
370impl<T, P> Default for RtBuffer<T, P> {
371    fn default() -> Self {
372        Self::new()
373    }
374}
375
376/// A buffer of flag constants.
377// FIXME: Fix the debug implementation for flags to actually display which flags
378// have been set.
379#[derive(Debug, PartialEq, Eq, Size, ToBytes, FromBytes)]
380#[neli(from_bytes_bound = "B: FromBytes + TypeSize + Debug")]
381pub struct FlagBuffer<B, T>(B, PhantomData<T>);
382
383impl<'a, B, T> From<&'a [T]> for FlagBuffer<B, T>
384where
385    B: Default + BitOr<B, Output = B> + From<&'a T>,
386{
387    fn from(slice: &'a [T]) -> Self {
388        FlagBuffer(
389            slice
390                .iter()
391                .fold(B::default(), |inner, flag| inner | B::from(flag)),
392            PhantomData,
393        )
394    }
395}
396
397impl<B, T> TypeSize for FlagBuffer<B, T>
398where
399    B: TypeSize,
400{
401    fn type_size() -> usize {
402        B::type_size()
403    }
404}
405
406impl<'a, B, T> FlagBuffer<B, T>
407where
408    B: Default
409        + BitAnd<B, Output = B>
410        + BitAndAssign<B>
411        + BitOr<B, Output = B>
412        + BitOrAssign<B>
413        + Not<Output = B>
414        + From<&'a T>
415        + PartialEq
416        + Copy,
417    T: 'a,
418{
419    /// Create an empty set of flags.
420    pub fn empty() -> Self {
421        FlagBuffer(B::default(), PhantomData)
422    }
423
424    /// Create a [`FlagBuffer`] from a bitmask.
425    pub fn from_bitmask(bitmask: B) -> Self {
426        FlagBuffer(bitmask, PhantomData)
427    }
428
429    /// Check whether the set of flags contains the given flag.
430    pub fn contains(&self, elem: &'a T) -> bool {
431        (self.0 & elem.into()) == elem.into()
432    }
433
434    /// Add a flag to the set of flags.
435    pub fn set(&mut self, flag: &'a T) {
436        self.0 |= B::from(flag)
437    }
438
439    /// Remove a flag from the set of flags.
440    pub fn unset(&mut self, flag: &'a T) {
441        self.0 &= !B::from(flag)
442    }
443}
444
445#[cfg(test)]
446mod test {
447    use super::*;
448
449    use crate::consts::{genl::Index, rtnl::Ifa};
450
451    #[test]
452    fn test_genlbuffer_align() {
453        assert_eq!(
454            vec![
455                Nlattr::new(false, false, Index::from(0), 0u8,).unwrap(),
456                Nlattr::new(false, false, Index::from(1), 1u8,).unwrap(),
457                Nlattr::new(false, false, Index::from(2), 2u8,).unwrap(),
458            ]
459            .into_iter()
460            .collect::<GenlBuffer<Index, Buffer>>()
461            .unpadded_size(),
462            24
463        )
464    }
465
466    #[test]
467    fn test_rtbuffer_align() {
468        assert_eq!(
469            vec![
470                Rtattr::new(None, Ifa::Unspec, 0u8,).unwrap(),
471                Rtattr::new(None, Ifa::Address, 1u8,).unwrap(),
472                Rtattr::new(None, Ifa::Local, 2u8,).unwrap(),
473            ]
474            .into_iter()
475            .collect::<RtBuffer<Ifa, Buffer>>()
476            .unpadded_size(),
477            24
478        )
479    }
480}