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