vmm_sys_util/
fam.rs

1// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2//
3// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
4//
5// SPDX-License-Identifier: BSD-3-Clause
6
7//! Trait and wrapper for working with C defined FAM structures.
8//!
9//! In C 99 an array of unknown size may appear within a struct definition as the last member
10//! (as long as there is at least one other named member).
11//! This is known as a flexible array member (FAM).
12//! Pre C99, the same behavior could be achieved using zero length arrays.
13//!
14//! Flexible Array Members are the go-to choice for working with large amounts of data
15//! prefixed by header values.
16//!
17//! For example the KVM API has many structures of this kind.
18
19#[cfg(feature = "with-serde")]
20use serde::de::{self, Deserialize, Deserializer, SeqAccess, Visitor};
21#[cfg(feature = "with-serde")]
22use serde::{ser::SerializeTuple, Serialize, Serializer};
23use std::fmt;
24#[cfg(feature = "with-serde")]
25use std::marker::PhantomData;
26use std::mem::{self, size_of};
27
28/// Errors associated with the [`FamStructWrapper`](struct.FamStructWrapper.html) struct.
29#[derive(Clone, Debug, PartialEq, Eq)]
30pub enum Error {
31    /// The max size has been exceeded
32    SizeLimitExceeded,
33}
34
35impl std::error::Error for Error {}
36
37impl fmt::Display for Error {
38    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39        match self {
40            Self::SizeLimitExceeded => write!(f, "The max size has been exceeded"),
41        }
42    }
43}
44
45/// Trait for accessing properties of C defined FAM structures.
46///
47/// # Safety
48///
49/// This is unsafe due to the number of constraints that aren't checked:
50/// * the implementer should be a POD
51/// * the implementor should contain a flexible array member of elements of type `Entry`
52/// * `Entry` should be a POD
53///
54/// Violating these may cause problems.
55///
56/// # Example
57///
58/// ```
59/// use vmm_sys_util::fam::*;
60///
61/// #[repr(C)]
62/// #[derive(Default)]
63/// pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
64/// impl<T> __IncompleteArrayField<T> {
65///     #[inline]
66///     pub fn new() -> Self {
67///         __IncompleteArrayField(::std::marker::PhantomData, [])
68///     }
69///     #[inline]
70///     pub unsafe fn as_ptr(&self) -> *const T {
71///         ::std::mem::transmute(self)
72///     }
73///     #[inline]
74///     pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
75///         ::std::mem::transmute(self)
76///     }
77///     #[inline]
78///     pub unsafe fn as_slice(&self, len: usize) -> &[T] {
79///         ::std::slice::from_raw_parts(self.as_ptr(), len)
80///     }
81///     #[inline]
82///     pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
83///         ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
84///     }
85/// }
86///
87/// #[repr(C)]
88/// #[derive(Default)]
89/// struct MockFamStruct {
90///     pub len: u32,
91///     pub padding: u32,
92///     pub entries: __IncompleteArrayField<u32>,
93/// }
94///
95/// unsafe impl FamStruct for MockFamStruct {
96///     type Entry = u32;
97///
98///     fn len(&self) -> usize {
99///         self.len as usize
100///     }
101///
102///     fn set_len(&mut self, len: usize) {
103///         self.len = len as u32
104///     }
105///
106///     fn max_len() -> usize {
107///         100
108///     }
109///
110///     fn as_slice(&self) -> &[u32] {
111///         let len = self.len();
112///         unsafe { self.entries.as_slice(len) }
113///     }
114///
115///     fn as_mut_slice(&mut self) -> &mut [u32] {
116///         let len = self.len();
117///         unsafe { self.entries.as_mut_slice(len) }
118///     }
119/// }
120///
121/// type MockFamStructWrapper = FamStructWrapper<MockFamStruct>;
122/// ```
123#[allow(clippy::len_without_is_empty)]
124pub unsafe trait FamStruct {
125    /// The type of the FAM entries
126    type Entry: PartialEq + Copy;
127
128    /// Get the FAM length
129    ///
130    /// These type of structures contain a member that holds the FAM length.
131    /// This method will return the value of that member.
132    fn len(&self) -> usize;
133
134    /// Set the FAM length
135    ///
136    /// These type of structures contain a member that holds the FAM length.
137    /// This method will set the value of that member.
138    fn set_len(&mut self, len: usize);
139
140    /// Get max allowed FAM length
141    ///
142    /// This depends on each structure.
143    /// For example a structure representing the cpuid can contain at most 80 entries.
144    fn max_len() -> usize;
145
146    /// Get the FAM entries as slice
147    fn as_slice(&self) -> &[Self::Entry];
148
149    /// Get the FAM entries as mut slice
150    fn as_mut_slice(&mut self) -> &mut [Self::Entry];
151}
152
153/// A wrapper for [`FamStruct`](trait.FamStruct.html).
154///
155/// It helps in treating a [`FamStruct`](trait.FamStruct.html) similarly to an actual `Vec`.
156#[derive(Debug)]
157pub struct FamStructWrapper<T: Default + FamStruct> {
158    // This variable holds the FamStruct structure. We use a `Vec<T>` to make the allocation
159    // large enough while still being aligned for `T`. Only the first element of `Vec<T>`
160    // will actually be used as a `T`. The remaining memory in the `Vec<T>` is for `entries`,
161    // which must be contiguous. Since the entries are of type `FamStruct::Entry` we must
162    // be careful to convert the desired capacity of the `FamStructWrapper`
163    // from `FamStruct::Entry` to `T` when reserving or releasing memory.
164    mem_allocator: Vec<T>,
165}
166
167impl<T: Default + FamStruct> FamStructWrapper<T> {
168    /// Convert FAM len to `mem_allocator` len.
169    ///
170    /// Get the capacity required by mem_allocator in order to hold
171    /// the provided number of [`FamStruct::Entry`](trait.FamStruct.html#associatedtype.Entry).
172    fn mem_allocator_len(fam_len: usize) -> usize {
173        let wrapper_size_in_bytes = size_of::<T>() + fam_len * size_of::<T::Entry>();
174        (wrapper_size_in_bytes + size_of::<T>() - 1) / size_of::<T>()
175    }
176
177    /// Convert `mem_allocator` len to FAM len.
178    ///
179    /// Get the number of elements of type
180    /// [`FamStruct::Entry`](trait.FamStruct.html#associatedtype.Entry)
181    /// that fit in a mem_allocator of provided len.
182    fn fam_len(mem_allocator_len: usize) -> usize {
183        if mem_allocator_len == 0 {
184            return 0;
185        }
186
187        let array_size_in_bytes = (mem_allocator_len - 1) * size_of::<T>();
188        array_size_in_bytes / size_of::<T::Entry>()
189    }
190
191    /// Create a new FamStructWrapper with `num_elements` elements.
192    ///
193    /// The elements will be zero-initialized. The type of the elements will be
194    /// [`FamStruct::Entry`](trait.FamStruct.html#associatedtype.Entry).
195    ///
196    /// # Arguments
197    ///
198    /// * `num_elements` - The number of elements in the FamStructWrapper.
199    ///
200    /// # Errors
201    ///
202    /// When `num_elements` is greater than the max possible len, it returns
203    /// `Error::SizeLimitExceeded`.
204    pub fn new(num_elements: usize) -> Result<FamStructWrapper<T>, Error> {
205        if num_elements > T::max_len() {
206            return Err(Error::SizeLimitExceeded);
207        }
208        let required_mem_allocator_capacity =
209            FamStructWrapper::<T>::mem_allocator_len(num_elements);
210
211        let mut mem_allocator = Vec::with_capacity(required_mem_allocator_capacity);
212        mem_allocator.push(T::default());
213        for _ in 1..required_mem_allocator_capacity {
214            // SAFETY: Safe as long T follows the requirements of being POD.
215            mem_allocator.push(unsafe { mem::zeroed() })
216        }
217        mem_allocator[0].set_len(num_elements);
218
219        Ok(FamStructWrapper { mem_allocator })
220    }
221
222    /// Create a new FamStructWrapper from a slice of elements.
223    ///
224    /// # Arguments
225    ///
226    /// * `entries` - The slice of [`FamStruct::Entry`](trait.FamStruct.html#associatedtype.Entry)
227    ///               entries.
228    ///
229    /// # Errors
230    ///
231    /// When the size of `entries` is greater than the max possible len, it returns
232    /// `Error::SizeLimitExceeded`.
233    pub fn from_entries(entries: &[T::Entry]) -> Result<FamStructWrapper<T>, Error> {
234        let mut adapter = FamStructWrapper::<T>::new(entries.len())?;
235
236        {
237            let wrapper_entries = adapter.as_mut_fam_struct().as_mut_slice();
238            wrapper_entries.copy_from_slice(entries);
239        }
240
241        Ok(adapter)
242    }
243
244    /// Create a new FamStructWrapper from the raw content represented as `Vec<T>`.
245    ///
246    /// Sometimes we already have the raw content of an FAM struct represented as `Vec<T>`,
247    /// and want to use the FamStructWrapper as accessors.
248    ///
249    /// # Arguments
250    ///
251    /// * `content` - The raw content represented as `Vec[T]`.
252    ///
253    /// # Safety
254    ///
255    /// This function is unsafe because the caller needs to ensure that the raw content is
256    /// correctly layed out.
257    pub unsafe fn from_raw(content: Vec<T>) -> Self {
258        FamStructWrapper {
259            mem_allocator: content,
260        }
261    }
262
263    /// Consume the FamStructWrapper and return the raw content as `Vec<T>`.
264    pub fn into_raw(self) -> Vec<T> {
265        self.mem_allocator
266    }
267
268    /// Get a reference to the actual [`FamStruct`](trait.FamStruct.html) instance.
269    pub fn as_fam_struct_ref(&self) -> &T {
270        &self.mem_allocator[0]
271    }
272
273    /// Get a mut reference to the actual [`FamStruct`](trait.FamStruct.html) instance.
274    pub fn as_mut_fam_struct(&mut self) -> &mut T {
275        &mut self.mem_allocator[0]
276    }
277
278    /// Get a pointer to the [`FamStruct`](trait.FamStruct.html) instance.
279    ///
280    /// The caller must ensure that the fam_struct outlives the pointer this
281    /// function returns, or else it will end up pointing to garbage.
282    ///
283    /// Modifying the container referenced by this pointer may cause its buffer
284    /// to be reallocated, which would also make any pointers to it invalid.
285    pub fn as_fam_struct_ptr(&self) -> *const T {
286        self.as_fam_struct_ref()
287    }
288
289    /// Get a mutable pointer to the [`FamStruct`](trait.FamStruct.html) instance.
290    ///
291    /// The caller must ensure that the fam_struct outlives the pointer this
292    /// function returns, or else it will end up pointing to garbage.
293    ///
294    /// Modifying the container referenced by this pointer may cause its buffer
295    /// to be reallocated, which would also make any pointers to it invalid.
296    pub fn as_mut_fam_struct_ptr(&mut self) -> *mut T {
297        self.as_mut_fam_struct()
298    }
299
300    /// Get the elements slice.
301    pub fn as_slice(&self) -> &[T::Entry] {
302        self.as_fam_struct_ref().as_slice()
303    }
304
305    /// Get the mutable elements slice.
306    pub fn as_mut_slice(&mut self) -> &mut [T::Entry] {
307        self.as_mut_fam_struct().as_mut_slice()
308    }
309
310    /// Get the number of elements of type `FamStruct::Entry` currently in the vec.
311    fn len(&self) -> usize {
312        self.as_fam_struct_ref().len()
313    }
314
315    /// Get the capacity of the `FamStructWrapper`
316    ///
317    /// The capacity is measured in elements of type `FamStruct::Entry`.
318    fn capacity(&self) -> usize {
319        FamStructWrapper::<T>::fam_len(self.mem_allocator.capacity())
320    }
321
322    /// Reserve additional capacity.
323    ///
324    /// Reserve capacity for at least `additional` more
325    /// [`FamStruct::Entry`](trait.FamStruct.html#associatedtype.Entry) elements.
326    ///
327    /// If the capacity is already reserved, this method doesn't do anything.
328    /// If not this will trigger a reallocation of the underlying buffer.
329    fn reserve(&mut self, additional: usize) {
330        let desired_capacity = self.len() + additional;
331        if desired_capacity <= self.capacity() {
332            return;
333        }
334
335        let current_mem_allocator_len = self.mem_allocator.len();
336        let required_mem_allocator_len = FamStructWrapper::<T>::mem_allocator_len(desired_capacity);
337        let additional_mem_allocator_len = required_mem_allocator_len - current_mem_allocator_len;
338
339        self.mem_allocator.reserve(additional_mem_allocator_len);
340    }
341
342    /// Update the length of the FamStructWrapper.
343    ///
344    /// The length of `self` will be updated to the specified value.
345    /// The length of the `T` structure and of `self.mem_allocator` will be updated accordingly.
346    /// If the len is increased additional capacity will be reserved.
347    /// If the len is decreased the unnecessary memory will be deallocated.
348    ///
349    /// This method might trigger reallocations of the underlying buffer.
350    ///
351    /// # Errors
352    ///
353    /// When len is greater than the max possible len it returns Error::SizeLimitExceeded.
354    fn set_len(&mut self, len: usize) -> Result<(), Error> {
355        let additional_elements: isize = len as isize - self.len() as isize;
356        // If len == self.len there's nothing to do.
357        if additional_elements == 0 {
358            return Ok(());
359        }
360
361        // If the len needs to be increased:
362        if additional_elements > 0 {
363            // Check if the new len is valid.
364            if len > T::max_len() {
365                return Err(Error::SizeLimitExceeded);
366            }
367            // Reserve additional capacity.
368            self.reserve(additional_elements as usize);
369        }
370
371        let current_mem_allocator_len = self.mem_allocator.len();
372        let required_mem_allocator_len = FamStructWrapper::<T>::mem_allocator_len(len);
373        // Update the len of the `mem_allocator`.
374        // SAFETY: This is safe since enough capacity has been reserved.
375        unsafe {
376            self.mem_allocator.set_len(required_mem_allocator_len);
377        }
378        // Zero-initialize the additional elements if any.
379        for i in current_mem_allocator_len..required_mem_allocator_len {
380            // SAFETY: Safe as long as the trait is only implemented for POD. This is a requirement
381            // for the trait implementation.
382            self.mem_allocator[i] = unsafe { mem::zeroed() }
383        }
384        // Update the len of the underlying `FamStruct`.
385        self.as_mut_fam_struct().set_len(len);
386
387        // If the len needs to be decreased, deallocate unnecessary memory
388        if additional_elements < 0 {
389            self.mem_allocator.shrink_to_fit();
390        }
391
392        Ok(())
393    }
394
395    /// Append an element.
396    ///
397    /// # Arguments
398    ///
399    /// * `entry` - The element that will be appended to the end of the collection.
400    ///
401    /// # Errors
402    ///
403    /// When len is already equal to max possible len it returns Error::SizeLimitExceeded.
404    pub fn push(&mut self, entry: T::Entry) -> Result<(), Error> {
405        let new_len = self.len() + 1;
406        self.set_len(new_len)?;
407        self.as_mut_slice()[new_len - 1] = entry;
408
409        Ok(())
410    }
411
412    /// Retain only the elements specified by the predicate.
413    ///
414    /// # Arguments
415    ///
416    /// * `f` - The function used to evaluate whether an entry will be kept or not.
417    ///         When `f` returns `true` the entry is kept.
418    pub fn retain<P>(&mut self, mut f: P)
419    where
420        P: FnMut(&T::Entry) -> bool,
421    {
422        let mut num_kept_entries = 0;
423        {
424            let entries = self.as_mut_slice();
425            for entry_idx in 0..entries.len() {
426                let keep = f(&entries[entry_idx]);
427                if keep {
428                    entries[num_kept_entries] = entries[entry_idx];
429                    num_kept_entries += 1;
430                }
431            }
432        }
433
434        // This is safe since this method is not increasing the len
435        self.set_len(num_kept_entries).expect("invalid length");
436    }
437}
438
439impl<T: Default + FamStruct + PartialEq> PartialEq for FamStructWrapper<T> {
440    fn eq(&self, other: &FamStructWrapper<T>) -> bool {
441        self.as_fam_struct_ref() == other.as_fam_struct_ref() && self.as_slice() == other.as_slice()
442    }
443}
444
445impl<T: Default + FamStruct> Clone for FamStructWrapper<T> {
446    fn clone(&self) -> Self {
447        // The number of entries (self.as_slice().len()) can't be > T::max_len() since `self` is a
448        // valid `FamStructWrapper`.
449        let required_mem_allocator_capacity =
450            FamStructWrapper::<T>::mem_allocator_len(self.as_slice().len());
451
452        let mut mem_allocator = Vec::with_capacity(required_mem_allocator_capacity);
453
454        // SAFETY: This is safe as long as the requirements for the `FamStruct` trait to be safe
455        // are met (the implementing type and the entries elements are POD, therefore `Copy`, so
456        // memory safety can't be violated by the ownership of `fam_struct`). It is also safe
457        // because we're trying to read a T from a `&T` that is pointing to a properly initialized
458        // and aligned T.
459        unsafe {
460            let fam_struct: T = std::ptr::read(self.as_fam_struct_ref());
461            mem_allocator.push(fam_struct);
462        }
463        for _ in 1..required_mem_allocator_capacity {
464            mem_allocator.push(
465                // SAFETY: This is safe as long as T respects the FamStruct trait and is a POD.
466                unsafe { mem::zeroed() },
467            )
468        }
469
470        let mut adapter = FamStructWrapper { mem_allocator };
471        {
472            let wrapper_entries = adapter.as_mut_fam_struct().as_mut_slice();
473            wrapper_entries.copy_from_slice(self.as_slice());
474        }
475        adapter
476    }
477}
478
479impl<T: Default + FamStruct> From<Vec<T>> for FamStructWrapper<T> {
480    fn from(vec: Vec<T>) -> Self {
481        FamStructWrapper { mem_allocator: vec }
482    }
483}
484
485#[cfg(feature = "with-serde")]
486impl<T: Default + FamStruct + Serialize> Serialize for FamStructWrapper<T>
487where
488    <T as FamStruct>::Entry: serde::Serialize,
489{
490    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
491    where
492        S: Serializer,
493    {
494        let mut s = serializer.serialize_tuple(2)?;
495        s.serialize_element(self.as_fam_struct_ref())?;
496        s.serialize_element(self.as_slice())?;
497        s.end()
498    }
499}
500
501#[cfg(feature = "with-serde")]
502impl<'de, T: Default + FamStruct + Deserialize<'de>> Deserialize<'de> for FamStructWrapper<T>
503where
504    <T as FamStruct>::Entry: std::marker::Copy + serde::Deserialize<'de>,
505{
506    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
507    where
508        D: Deserializer<'de>,
509    {
510        struct FamStructWrapperVisitor<X> {
511            dummy: PhantomData<X>,
512        }
513
514        impl<'de, X: Default + FamStruct + Deserialize<'de>> Visitor<'de> for FamStructWrapperVisitor<X>
515        where
516            <X as FamStruct>::Entry: std::marker::Copy + serde::Deserialize<'de>,
517        {
518            type Value = FamStructWrapper<X>;
519
520            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
521                formatter.write_str("FamStructWrapper")
522            }
523
524            fn visit_seq<V>(self, mut seq: V) -> Result<FamStructWrapper<X>, V::Error>
525            where
526                V: SeqAccess<'de>,
527            {
528                use serde::de::Error;
529
530                let header = seq
531                    .next_element()?
532                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
533                let entries: Vec<X::Entry> = seq
534                    .next_element()?
535                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
536
537                let mut result: Self::Value = FamStructWrapper::from_entries(entries.as_slice())
538                    .map_err(|e| V::Error::custom(format!("{:?}", e)))?;
539                result.mem_allocator[0] = header;
540                Ok(result)
541            }
542        }
543
544        deserializer.deserialize_tuple(2, FamStructWrapperVisitor { dummy: PhantomData })
545    }
546}
547
548/// Generate `FamStruct` implementation for structs with flexible array member.
549#[macro_export]
550macro_rules! generate_fam_struct_impl {
551    ($struct_type: ty, $entry_type: ty, $entries_name: ident,
552     $field_type: ty, $field_name: ident, $max: expr) => {
553        unsafe impl FamStruct for $struct_type {
554            type Entry = $entry_type;
555
556            fn len(&self) -> usize {
557                self.$field_name as usize
558            }
559
560            fn set_len(&mut self, len: usize) {
561                self.$field_name = len as $field_type;
562            }
563
564            fn max_len() -> usize {
565                $max
566            }
567
568            fn as_slice(&self) -> &[<Self as FamStruct>::Entry] {
569                let len = self.len();
570                unsafe { self.$entries_name.as_slice(len) }
571            }
572
573            fn as_mut_slice(&mut self) -> &mut [<Self as FamStruct>::Entry] {
574                let len = self.len();
575                unsafe { self.$entries_name.as_mut_slice(len) }
576            }
577        }
578    };
579}
580
581#[cfg(test)]
582mod tests {
583    #![allow(clippy::undocumented_unsafe_blocks)]
584    #[cfg(feature = "with-serde")]
585    use serde_derive::{Deserialize, Serialize};
586
587    use super::*;
588
589    const MAX_LEN: usize = 100;
590
591    #[repr(C)]
592    #[derive(Default, PartialEq, Eq)]
593    pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
594    impl<T> __IncompleteArrayField<T> {
595        #[inline]
596        pub fn new() -> Self {
597            __IncompleteArrayField(::std::marker::PhantomData, [])
598        }
599        #[inline]
600        pub unsafe fn as_ptr(&self) -> *const T {
601            self as *const __IncompleteArrayField<T> as *const T
602        }
603        #[inline]
604        pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
605            self as *mut __IncompleteArrayField<T> as *mut T
606        }
607        #[inline]
608        pub unsafe fn as_slice(&self, len: usize) -> &[T] {
609            ::std::slice::from_raw_parts(self.as_ptr(), len)
610        }
611        #[inline]
612        pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
613            ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
614        }
615    }
616
617    #[cfg(feature = "with-serde")]
618    impl<T> Serialize for __IncompleteArrayField<T> {
619        fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
620        where
621            S: Serializer,
622        {
623            [0u8; 0].serialize(serializer)
624        }
625    }
626
627    #[cfg(feature = "with-serde")]
628    impl<'de, T> Deserialize<'de> for __IncompleteArrayField<T> {
629        fn deserialize<D>(_: D) -> std::result::Result<Self, D::Error>
630        where
631            D: Deserializer<'de>,
632        {
633            Ok(__IncompleteArrayField::new())
634        }
635    }
636
637    #[repr(C)]
638    #[derive(Default, PartialEq)]
639    struct MockFamStruct {
640        pub len: u32,
641        pub padding: u32,
642        pub entries: __IncompleteArrayField<u32>,
643    }
644
645    generate_fam_struct_impl!(MockFamStruct, u32, entries, u32, len, 100);
646
647    type MockFamStructWrapper = FamStructWrapper<MockFamStruct>;
648
649    const ENTRIES_OFFSET: usize = 2;
650
651    const FAM_LEN_TO_MEM_ALLOCATOR_LEN: &[(usize, usize)] = &[
652        (0, 1),
653        (1, 2),
654        (2, 2),
655        (3, 3),
656        (4, 3),
657        (5, 4),
658        (10, 6),
659        (50, 26),
660        (100, 51),
661    ];
662
663    const MEM_ALLOCATOR_LEN_TO_FAM_LEN: &[(usize, usize)] = &[
664        (0, 0),
665        (1, 0),
666        (2, 2),
667        (3, 4),
668        (4, 6),
669        (5, 8),
670        (10, 18),
671        (50, 98),
672        (100, 198),
673    ];
674
675    #[test]
676    fn test_mem_allocator_len() {
677        for pair in FAM_LEN_TO_MEM_ALLOCATOR_LEN {
678            let fam_len = pair.0;
679            let mem_allocator_len = pair.1;
680            assert_eq!(
681                mem_allocator_len,
682                MockFamStructWrapper::mem_allocator_len(fam_len)
683            );
684        }
685    }
686
687    #[test]
688    fn test_wrapper_len() {
689        for pair in MEM_ALLOCATOR_LEN_TO_FAM_LEN {
690            let mem_allocator_len = pair.0;
691            let fam_len = pair.1;
692            assert_eq!(fam_len, MockFamStructWrapper::fam_len(mem_allocator_len));
693        }
694    }
695
696    #[test]
697    fn test_new() {
698        let num_entries = 10;
699
700        let adapter = MockFamStructWrapper::new(num_entries).unwrap();
701        assert_eq!(num_entries, adapter.capacity());
702
703        let u32_slice = unsafe {
704            std::slice::from_raw_parts(
705                adapter.as_fam_struct_ptr() as *const u32,
706                num_entries + ENTRIES_OFFSET,
707            )
708        };
709        assert_eq!(num_entries, u32_slice[0] as usize);
710        for entry in u32_slice[1..].iter() {
711            assert_eq!(*entry, 0);
712        }
713
714        // It's okay to create a `FamStructWrapper` with the maximum allowed number of entries.
715        let adapter = MockFamStructWrapper::new(MockFamStruct::max_len()).unwrap();
716        assert_eq!(MockFamStruct::max_len(), adapter.capacity());
717
718        assert!(matches!(
719            MockFamStructWrapper::new(MockFamStruct::max_len() + 1),
720            Err(Error::SizeLimitExceeded)
721        ));
722    }
723
724    #[test]
725    fn test_from_entries() {
726        let num_entries: usize = 10;
727
728        let mut entries = Vec::new();
729        for i in 0..num_entries {
730            entries.push(i as u32);
731        }
732
733        let adapter = MockFamStructWrapper::from_entries(entries.as_slice()).unwrap();
734        let u32_slice = unsafe {
735            std::slice::from_raw_parts(
736                adapter.as_fam_struct_ptr() as *const u32,
737                num_entries + ENTRIES_OFFSET,
738            )
739        };
740        assert_eq!(num_entries, u32_slice[0] as usize);
741        for (i, &value) in entries.iter().enumerate().take(num_entries) {
742            assert_eq!(adapter.as_slice()[i], value);
743        }
744
745        let mut entries = Vec::new();
746        for i in 0..MockFamStruct::max_len() + 1 {
747            entries.push(i as u32);
748        }
749
750        // Can't create a `FamStructWrapper` with a number of entries > MockFamStruct::max_len().
751        assert!(matches!(
752            MockFamStructWrapper::from_entries(entries.as_slice()),
753            Err(Error::SizeLimitExceeded)
754        ));
755    }
756
757    #[test]
758    fn test_entries_slice() {
759        let num_entries = 10;
760        let mut adapter = MockFamStructWrapper::new(num_entries).unwrap();
761
762        let expected_slice = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
763
764        {
765            let mut_entries_slice = adapter.as_mut_slice();
766            mut_entries_slice.copy_from_slice(expected_slice);
767        }
768
769        let u32_slice = unsafe {
770            std::slice::from_raw_parts(
771                adapter.as_fam_struct_ptr() as *const u32,
772                num_entries + ENTRIES_OFFSET,
773            )
774        };
775        assert_eq!(expected_slice, &u32_slice[ENTRIES_OFFSET..]);
776        assert_eq!(expected_slice, adapter.as_slice());
777    }
778
779    #[test]
780    fn test_reserve() {
781        let mut adapter = MockFamStructWrapper::new(0).unwrap();
782
783        // test that the right capacity is reserved
784        for pair in FAM_LEN_TO_MEM_ALLOCATOR_LEN {
785            let num_elements = pair.0;
786            let required_mem_allocator_len = pair.1;
787
788            adapter.reserve(num_elements);
789
790            assert!(adapter.mem_allocator.capacity() >= required_mem_allocator_len);
791            assert_eq!(0, adapter.len());
792            assert!(adapter.capacity() >= num_elements);
793        }
794
795        // test that when the capacity is already reserved, the method doesn't do anything
796        let current_capacity = adapter.capacity();
797        adapter.reserve(current_capacity - 1);
798        assert_eq!(current_capacity, adapter.capacity());
799    }
800
801    #[test]
802    fn test_set_len() {
803        let mut desired_len = 0;
804        let mut adapter = MockFamStructWrapper::new(desired_len).unwrap();
805
806        // keep initial len
807        assert!(adapter.set_len(desired_len).is_ok());
808        assert_eq!(adapter.len(), desired_len);
809
810        // increase len
811        desired_len = 10;
812        assert!(adapter.set_len(desired_len).is_ok());
813        // check that the len has been increased and zero-initialized elements have been added
814        assert_eq!(adapter.len(), desired_len);
815        for element in adapter.as_slice() {
816            assert_eq!(*element, 0_u32);
817        }
818
819        // decrease len
820        desired_len = 5;
821        assert!(adapter.set_len(desired_len).is_ok());
822        assert_eq!(adapter.len(), desired_len);
823    }
824
825    #[test]
826    fn test_push() {
827        let mut adapter = MockFamStructWrapper::new(0).unwrap();
828
829        for i in 0..MAX_LEN {
830            assert!(adapter.push(i as u32).is_ok());
831            assert_eq!(adapter.as_slice()[i], i as u32);
832            assert_eq!(adapter.len(), i + 1);
833            assert!(
834                adapter.mem_allocator.capacity() >= MockFamStructWrapper::mem_allocator_len(i + 1)
835            );
836        }
837
838        assert!(adapter.push(0).is_err());
839    }
840
841    #[test]
842    fn test_retain() {
843        let mut adapter = MockFamStructWrapper::new(0).unwrap();
844
845        let mut num_retained_entries = 0;
846        for i in 0..MAX_LEN {
847            assert!(adapter.push(i as u32).is_ok());
848            if i % 2 == 0 {
849                num_retained_entries += 1;
850            }
851        }
852
853        adapter.retain(|entry| entry % 2 == 0);
854
855        for entry in adapter.as_slice().iter() {
856            assert_eq!(0, entry % 2);
857        }
858        assert_eq!(adapter.len(), num_retained_entries);
859        assert!(
860            adapter.mem_allocator.capacity()
861                >= MockFamStructWrapper::mem_allocator_len(num_retained_entries)
862        );
863    }
864
865    #[test]
866    fn test_partial_eq() {
867        let mut wrapper_1 = MockFamStructWrapper::new(0).unwrap();
868        let mut wrapper_2 = MockFamStructWrapper::new(0).unwrap();
869        let mut wrapper_3 = MockFamStructWrapper::new(0).unwrap();
870
871        for i in 0..MAX_LEN {
872            assert!(wrapper_1.push(i as u32).is_ok());
873            assert!(wrapper_2.push(i as u32).is_ok());
874            assert!(wrapper_3.push(0).is_ok());
875        }
876
877        assert!(wrapper_1 == wrapper_2);
878        assert!(wrapper_1 != wrapper_3);
879    }
880
881    #[test]
882    fn test_clone() {
883        let mut adapter = MockFamStructWrapper::new(0).unwrap();
884
885        for i in 0..MAX_LEN {
886            assert!(adapter.push(i as u32).is_ok());
887        }
888
889        assert!(adapter == adapter.clone());
890    }
891
892    #[test]
893    fn test_raw_content() {
894        let data = vec![
895            MockFamStruct {
896                len: 2,
897                padding: 5,
898                entries: __IncompleteArrayField::new(),
899            },
900            MockFamStruct {
901                len: 0xA5,
902                padding: 0x1e,
903                entries: __IncompleteArrayField::new(),
904            },
905        ];
906
907        let mut wrapper = unsafe { MockFamStructWrapper::from_raw(data) };
908        {
909            let payload = wrapper.as_slice();
910            assert_eq!(payload[0], 0xA5);
911            assert_eq!(payload[1], 0x1e);
912        }
913        assert_eq!(wrapper.as_mut_fam_struct().padding, 5);
914        let data = wrapper.into_raw();
915        assert_eq!(data[0].len, 2);
916        assert_eq!(data[0].padding, 5);
917    }
918
919    #[cfg(feature = "with-serde")]
920    #[test]
921    fn test_ser_deser() {
922        #[repr(C)]
923        #[derive(Default, PartialEq)]
924        #[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
925        struct Message {
926            pub len: u32,
927            pub padding: u32,
928            pub value: u32,
929            #[cfg_attr(feature = "with-serde", serde(skip))]
930            pub entries: __IncompleteArrayField<u32>,
931        }
932
933        generate_fam_struct_impl!(Message, u32, entries, u32, len, 100);
934
935        type MessageFamStructWrapper = FamStructWrapper<Message>;
936
937        let data = vec![
938            Message {
939                len: 2,
940                padding: 0,
941                value: 42,
942                entries: __IncompleteArrayField::new(),
943            },
944            Message {
945                len: 0xA5,
946                padding: 0x1e,
947                value: 0,
948                entries: __IncompleteArrayField::new(),
949            },
950        ];
951
952        let wrapper = unsafe { MessageFamStructWrapper::from_raw(data) };
953        let data_ser = serde_json::to_string(&wrapper).unwrap();
954        assert_eq!(
955            data_ser,
956            "[{\"len\":2,\"padding\":0,\"value\":42},[165,30]]"
957        );
958        let data_deser =
959            serde_json::from_str::<MessageFamStructWrapper>(data_ser.as_str()).unwrap();
960        assert!(wrapper.eq(&data_deser));
961
962        let bad_data_ser = r#"{"foo": "bar"}"#;
963        assert!(serde_json::from_str::<MessageFamStructWrapper>(bad_data_ser).is_err());
964
965        #[repr(C)]
966        #[derive(Default)]
967        #[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
968        struct Message2 {
969            pub len: u32,
970            pub padding: u32,
971            pub value: u32,
972            #[cfg_attr(feature = "with-serde", serde(skip))]
973            pub entries: __IncompleteArrayField<u32>,
974        }
975
976        // Maximum number of entries = 1, so the deserialization should fail because of this reason.
977        generate_fam_struct_impl!(Message2, u32, entries, u32, len, 1);
978
979        type Message2FamStructWrapper = FamStructWrapper<Message2>;
980        assert!(serde_json::from_str::<Message2FamStructWrapper>(data_ser.as_str()).is_err());
981    }
982
983    #[test]
984    fn test_clone_multiple_fields() {
985        #[derive(Default, PartialEq)]
986        #[repr(C)]
987        struct Foo {
988            index: u32,
989            length: u16,
990            flags: u32,
991            entries: __IncompleteArrayField<u32>,
992        }
993
994        generate_fam_struct_impl!(Foo, u32, entries, u16, length, 100);
995
996        type FooFamStructWrapper = FamStructWrapper<Foo>;
997
998        let mut wrapper = FooFamStructWrapper::new(0).unwrap();
999        wrapper.as_mut_fam_struct().index = 1;
1000        wrapper.as_mut_fam_struct().flags = 2;
1001        wrapper.as_mut_fam_struct().length = 3;
1002        wrapper.push(3).unwrap();
1003        wrapper.push(14).unwrap();
1004        assert_eq!(wrapper.as_slice().len(), 3 + 2);
1005        assert_eq!(wrapper.as_slice()[3], 3);
1006        assert_eq!(wrapper.as_slice()[3 + 1], 14);
1007
1008        let mut wrapper2 = wrapper.clone();
1009        assert_eq!(
1010            wrapper.as_mut_fam_struct().index,
1011            wrapper2.as_mut_fam_struct().index
1012        );
1013        assert_eq!(
1014            wrapper.as_mut_fam_struct().length,
1015            wrapper2.as_mut_fam_struct().length
1016        );
1017        assert_eq!(
1018            wrapper.as_mut_fam_struct().flags,
1019            wrapper2.as_mut_fam_struct().flags
1020        );
1021        assert_eq!(wrapper.as_slice(), wrapper2.as_slice());
1022        assert_eq!(
1023            wrapper2.as_slice().len(),
1024            wrapper2.as_mut_fam_struct().length as usize
1025        );
1026        assert!(wrapper == wrapper2);
1027
1028        wrapper.as_mut_fam_struct().index = 3;
1029        assert!(wrapper != wrapper2);
1030
1031        wrapper.as_mut_fam_struct().length = 7;
1032        assert!(wrapper != wrapper2);
1033
1034        wrapper.push(1).unwrap();
1035        assert_eq!(wrapper.as_mut_fam_struct().length, 8);
1036        assert!(wrapper != wrapper2);
1037
1038        let mut wrapper2 = wrapper.clone();
1039        assert!(wrapper == wrapper2);
1040
1041        // Dropping the original variable should not affect its clone.
1042        drop(wrapper);
1043        assert_eq!(wrapper2.as_mut_fam_struct().index, 3);
1044        assert_eq!(wrapper2.as_mut_fam_struct().length, 8);
1045        assert_eq!(wrapper2.as_mut_fam_struct().flags, 2);
1046        assert_eq!(wrapper2.as_slice(), [0, 0, 0, 3, 14, 0, 0, 1]);
1047    }
1048}