Coverage Report

Created: 2026-01-22 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/vfio-ioctls-0.5.1/src/fam.rs
Line
Count
Source
1
// Copyright © 2019 Intel Corporation
2
//
3
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
4
5
// This is a private version of vmm-sys-util::FamStruct. As it works smoothly, we keep it for
6
// simplicity.
7
8
use std::mem::size_of;
9
10
/// Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`.
11
0
fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> {
12
0
    let rounded_size = size_in_bytes.div_ceil(size_of::<T>());
13
0
    let mut v = Vec::with_capacity(rounded_size);
14
0
    for _ in 0..rounded_size {
15
0
        v.push(T::default())
16
    }
17
0
    v
18
0
}
Unexecuted instantiation: vfio_ioctls::fam::vec_with_size_in_bytes::<vfio_ioctls::vfio_device::vfio_region_info_with_cap>
Unexecuted instantiation: vfio_ioctls::fam::vec_with_size_in_bytes::<vfio_bindings::vfio_bindings::vfio::vfio_irq_set>
19
20
/// The VFIO API has several structs that resembles the following `Foo` structure:
21
///
22
/// ```
23
/// struct ControlMessageHeader {
24
///     r#type: u8,
25
///     length: u8,
26
/// }
27
///
28
/// #[repr(C)]
29
/// pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>);
30
/// #[repr(C)]
31
/// struct Foo {
32
///     some_data: ControlMessageHeader,
33
///     entries: __IncompleteArrayField<u32>,
34
/// }
35
/// ```
36
///
37
/// In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would not
38
/// include any space for `entries`. To make the allocation large enough while still being aligned
39
/// for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually be used
40
/// as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be contiguous
41
/// with `Foo`. This function is used to make the `Vec<Foo>` with enough space for `count` entries.
42
0
pub(crate) fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> {
43
0
    let element_space = match count.checked_mul(size_of::<F>()) {
44
0
        None => panic!("allocating too large buffer with vec_with_array_field"),
45
0
        Some(v) => v,
46
    };
47
0
    let vec_size_bytes = match element_space.checked_add(size_of::<T>()) {
48
0
        None => panic!("allocating too large buffer with vec_with_array_field"),
49
0
        Some(v) => v,
50
    };
51
52
0
    vec_with_size_in_bytes(vec_size_bytes)
53
0
}
Unexecuted instantiation: vfio_ioctls::fam::vec_with_array_field::<vfio_ioctls::vfio_device::vfio_region_info_with_cap, u8>
Unexecuted instantiation: vfio_ioctls::fam::vec_with_array_field::<vfio_bindings::vfio_bindings::vfio::vfio_irq_set, u32>
54
55
#[cfg(test)]
56
mod tests {
57
    use super::*;
58
59
    #[derive(Default)]
60
    #[allow(dead_code)]
61
    struct Header {
62
        ty: u32,
63
        len: u32,
64
    }
65
66
    #[allow(dead_code)]
67
    struct Field {
68
        f1: u64,
69
        f2: u64,
70
    }
71
72
    #[test]
73
    fn test_vec_with_array_field() {
74
        let v1 = vec_with_array_field::<Header, Field>(1);
75
        assert_eq!(v1.len(), 3);
76
77
        let v2 = vec_with_array_field::<Header, Field>(0);
78
        assert_eq!(v2.len(), 1);
79
80
        let v3 = vec_with_array_field::<Header, Field>(5);
81
        assert_eq!(v3.len(), 11);
82
    }
83
84
    #[test]
85
    #[should_panic]
86
    fn test_vec_with_array_field_overflow() {
87
        let _ = vec_with_array_field::<Header, Field>(usize::MAX);
88
    }
89
}