1use crate::{Error, Queue, QueueT};
2use vm_memory::GuestAddress;
3
4#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
15pub struct QueueState {
16 pub max_size: u16,
18 pub next_avail: u16,
20 pub next_used: u16,
22 pub event_idx_enabled: bool,
24 pub size: u16,
26 pub ready: bool,
28 pub desc_table: u64,
30 pub avail_ring: u64,
32 pub used_ring: u64,
34}
35
36impl TryFrom<QueueState> for Queue {
37 type Error = Error;
38
39 fn try_from(q_state: QueueState) -> Result<Self, Self::Error> {
40 let mut q = Queue::new(q_state.max_size)?;
41
42 q.set_next_avail(q_state.next_avail);
43 q.set_next_used(q_state.next_used);
44 q.set_event_idx(q_state.event_idx_enabled);
45 q.try_set_size(q_state.size)?;
46 q.set_ready(q_state.ready);
47 q.try_set_desc_table_address(GuestAddress(q_state.desc_table))?;
48 q.try_set_avail_ring_address(GuestAddress(q_state.avail_ring))?;
49 q.try_set_used_ring_address(GuestAddress(q_state.used_ring))?;
50
51 Ok(q)
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 fn create_valid_queue_state() -> QueueState {
60 let queue = Queue::new(16).unwrap();
61 queue.state()
62 }
63
64 #[test]
65 fn test_empty_queue_state() {
66 let max_size = 16;
67 let queue = Queue::new(max_size).unwrap();
68
69 let queue_state = queue.state();
72 let restored_q = Queue::try_from(queue_state).unwrap();
73 assert_eq!(queue, restored_q);
74 }
75
76 #[test]
77 fn test_invalid_queue_state() {
78 let mut q_state = create_valid_queue_state();
80
81 q_state.max_size = 0;
84 assert!(Queue::try_from(q_state).is_err());
85 q_state.max_size = u16::MAX;
87 assert!(Queue::try_from(q_state).is_err());
88 q_state.max_size = 15;
90 assert!(Queue::try_from(q_state).is_err());
91
92 let mut q_state = create_valid_queue_state();
94 q_state.size = 0;
96 assert!(Queue::try_from(q_state).is_err());
97 q_state.size = u16::MAX;
99 assert!(Queue::try_from(q_state).is_err());
100 q_state.size = 15;
102 assert!(Queue::try_from(q_state).is_err());
103
104 let mut q_state = create_valid_queue_state();
106 q_state.desc_table = 0xf;
107 assert!(Queue::try_from(q_state).is_err());
108
109 let mut q_state = create_valid_queue_state();
111 q_state.avail_ring = 0x1;
112 assert!(Queue::try_from(q_state).is_err());
113
114 let mut q_state = create_valid_queue_state();
116 q_state.used_ring = 0x3;
117 assert!(Queue::try_from(q_state).is_err());
118 }
119}