virtio_spec/virtq/
alloc.rs

1use ::alloc::alloc::handle_alloc_error;
2use allocator_api2::alloc::{AllocError, Allocator, Global};
3use allocator_api2::boxed::Box;
4
5use super::*;
6
7impl Avail {
8    pub fn new(queue_size: u16, has_event_idx: bool) -> Box<Self> {
9        Self::new_in(queue_size, has_event_idx, Global)
10    }
11
12    pub fn try_new(queue_size: u16, has_event_idx: bool) -> Result<Box<Self>, AllocError> {
13        Self::try_new_in(queue_size, has_event_idx, Global)
14    }
15
16    pub fn new_in<A: Allocator>(queue_size: u16, has_event_idx: bool, alloc: A) -> Box<Self, A> {
17        Self::try_new_in(queue_size, has_event_idx, alloc)
18            .unwrap_or_else(|_| handle_alloc_error(Self::layout(queue_size, has_event_idx)))
19    }
20
21    pub fn try_new_in<A: Allocator>(
22        queue_size: u16,
23        has_event_idx: bool,
24        alloc: A,
25    ) -> Result<Box<Self, A>, AllocError> {
26        let layout = Self::layout(queue_size, has_event_idx);
27
28        let mem = alloc.allocate_zeroed(layout)?;
29        let mem = NonNull::slice_from_raw_parts(mem.cast(), layout.size());
30        let raw = Self::from_ptr(mem).unwrap();
31        let boxed = unsafe { Box::from_raw_in(raw.as_ptr(), alloc) };
32
33        debug_assert_eq!(Layout::for_value(&*boxed), layout);
34        debug_assert_eq!(boxed.ring(has_event_idx).len(), queue_size.into());
35        debug_assert_eq!(boxed.used_event(has_event_idx).is_some(), has_event_idx);
36
37        Ok(boxed)
38    }
39}
40
41impl Used {
42    pub fn new(queue_size: u16, has_event_idx: bool) -> Box<Self> {
43        Self::new_in(queue_size, has_event_idx, Global)
44    }
45
46    pub fn try_new(queue_size: u16, has_event_idx: bool) -> Result<Box<Self>, AllocError> {
47        Self::try_new_in(queue_size, has_event_idx, Global)
48    }
49
50    pub fn new_in<A: Allocator>(queue_size: u16, has_event_idx: bool, alloc: A) -> Box<Self, A> {
51        Self::try_new_in(queue_size, has_event_idx, alloc)
52            .unwrap_or_else(|_| handle_alloc_error(Self::layout(queue_size, has_event_idx)))
53    }
54
55    pub fn try_new_in<A: Allocator>(
56        queue_size: u16,
57        has_event_idx: bool,
58        alloc: A,
59    ) -> Result<Box<Self, A>, AllocError> {
60        let layout = Self::layout(queue_size, has_event_idx);
61
62        let mem = alloc.allocate_zeroed(layout)?;
63        let mem = NonNull::slice_from_raw_parts(mem.cast(), layout.size());
64        let raw = Self::from_ptr(mem, has_event_idx).unwrap();
65        let boxed = unsafe { Box::from_raw_in(raw.as_ptr(), alloc) };
66
67        debug_assert_eq!(Layout::for_value(&*boxed), layout);
68        debug_assert_eq!(boxed.ring().len(), queue_size.into());
69        debug_assert_eq!(boxed.avail_event().is_some(), has_event_idx);
70
71        Ok(boxed)
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn avail_layout() {
81        for queue_size in [255, 256, 257] {
82            for has_event_idx in [false, true] {
83                Avail::new(queue_size, has_event_idx);
84            }
85        }
86    }
87
88    #[test]
89    fn used_layout() {
90        for queue_size in [255, 256, 257] {
91            for has_event_idx in [false, true] {
92                Used::new(queue_size, has_event_idx);
93            }
94        }
95    }
96}