virtio_spec/virtq/
alloc.rs1use ::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}