1 // SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
2 
3 use crate::rxops::RxOps;
4 
5 #[derive(Debug, Eq, PartialEq)]
6 pub(crate) struct RxQueue {
7     /// Bitmap of rx operations.
8     queue: u8,
9 }
10 
11 impl RxQueue {
12     /// New instance of RxQueue.
new() -> Self13     pub fn new() -> Self {
14         RxQueue { queue: 0_u8 }
15     }
16 
17     /// Enqueue a new rx operation into the queue.
enqueue(&mut self, op: RxOps)18     pub fn enqueue(&mut self, op: RxOps) {
19         self.queue |= op.bitmask();
20     }
21 
22     /// Dequeue an rx operation from the queue.
dequeue(&mut self) -> Option<RxOps>23     pub fn dequeue(&mut self) -> Option<RxOps> {
24         match self.peek() {
25             Some(req) => {
26                 self.queue &= !req.bitmask();
27                 Some(req)
28             }
29             None => None,
30         }
31     }
32 
33     /// Peek into the queue to check if it contains an rx operation.
peek(&self) -> Option<RxOps>34     pub fn peek(&self) -> Option<RxOps> {
35         if self.contains(RxOps::Request.bitmask()) {
36             return Some(RxOps::Request);
37         }
38         if self.contains(RxOps::Rw.bitmask()) {
39             return Some(RxOps::Rw);
40         }
41         if self.contains(RxOps::Response.bitmask()) {
42             return Some(RxOps::Response);
43         }
44         if self.contains(RxOps::CreditUpdate.bitmask()) {
45             return Some(RxOps::CreditUpdate);
46         }
47         if self.contains(RxOps::Reset.bitmask()) {
48             Some(RxOps::Reset)
49         } else {
50             None
51         }
52     }
53 
54     /// Check if the queue contains a particular rx operation.
contains(&self, op: u8) -> bool55     pub fn contains(&self, op: u8) -> bool {
56         (self.queue & op) != 0
57     }
58 
59     /// Check if there are any pending rx operations in the queue.
pending_rx(&self) -> bool60     pub fn pending_rx(&self) -> bool {
61         self.queue != 0
62     }
63 }
64 
65 #[cfg(test)]
66 mod tests {
67     use super::*;
68 
69     #[test]
test_contains()70     fn test_contains() {
71         let mut rxqueue = RxQueue::new();
72         rxqueue.queue = 31;
73 
74         assert!(rxqueue.contains(RxOps::Request.bitmask()));
75         assert!(rxqueue.contains(RxOps::Rw.bitmask()));
76         assert!(rxqueue.contains(RxOps::Response.bitmask()));
77         assert!(rxqueue.contains(RxOps::CreditUpdate.bitmask()));
78         assert!(rxqueue.contains(RxOps::Reset.bitmask()));
79 
80         rxqueue.queue = 0;
81         assert!(!rxqueue.contains(RxOps::Request.bitmask()));
82         assert!(!rxqueue.contains(RxOps::Rw.bitmask()));
83         assert!(!rxqueue.contains(RxOps::Response.bitmask()));
84         assert!(!rxqueue.contains(RxOps::CreditUpdate.bitmask()));
85         assert!(!rxqueue.contains(RxOps::Reset.bitmask()));
86     }
87 
88     #[test]
test_enqueue()89     fn test_enqueue() {
90         let mut rxqueue = RxQueue::new();
91 
92         rxqueue.enqueue(RxOps::Request);
93         assert!(rxqueue.contains(RxOps::Request.bitmask()));
94 
95         rxqueue.enqueue(RxOps::Rw);
96         assert!(rxqueue.contains(RxOps::Rw.bitmask()));
97 
98         rxqueue.enqueue(RxOps::Response);
99         assert!(rxqueue.contains(RxOps::Response.bitmask()));
100 
101         rxqueue.enqueue(RxOps::CreditUpdate);
102         assert!(rxqueue.contains(RxOps::CreditUpdate.bitmask()));
103 
104         rxqueue.enqueue(RxOps::Reset);
105         assert!(rxqueue.contains(RxOps::Reset.bitmask()));
106     }
107 
108     #[test]
test_peek()109     fn test_peek() {
110         let mut rxqueue = RxQueue::new();
111 
112         rxqueue.queue = 31;
113         assert_eq!(rxqueue.peek(), Some(RxOps::Request));
114 
115         rxqueue.queue = 30;
116         assert_eq!(rxqueue.peek(), Some(RxOps::Rw));
117 
118         rxqueue.queue = 28;
119         assert_eq!(rxqueue.peek(), Some(RxOps::Response));
120 
121         rxqueue.queue = 24;
122         assert_eq!(rxqueue.peek(), Some(RxOps::CreditUpdate));
123 
124         rxqueue.queue = 16;
125         assert_eq!(rxqueue.peek(), Some(RxOps::Reset));
126     }
127 
128     #[test]
test_dequeue()129     fn test_dequeue() {
130         let mut rxqueue = RxQueue::new();
131         rxqueue.queue = 31;
132 
133         assert_eq!(rxqueue.dequeue(), Some(RxOps::Request));
134         assert!(!rxqueue.contains(RxOps::Request.bitmask()));
135 
136         assert_eq!(rxqueue.dequeue(), Some(RxOps::Rw));
137         assert!(!rxqueue.contains(RxOps::Rw.bitmask()));
138 
139         assert_eq!(rxqueue.dequeue(), Some(RxOps::Response));
140         assert!(!rxqueue.contains(RxOps::Response.bitmask()));
141 
142         assert_eq!(rxqueue.dequeue(), Some(RxOps::CreditUpdate));
143         assert!(!rxqueue.contains(RxOps::CreditUpdate.bitmask()));
144 
145         assert_eq!(rxqueue.dequeue(), Some(RxOps::Reset));
146         assert!(!rxqueue.contains(RxOps::Reset.bitmask()));
147     }
148 
149     #[test]
test_pending_rx()150     fn test_pending_rx() {
151         let mut rxqueue = RxQueue::new();
152         assert!(!rxqueue.pending_rx());
153 
154         rxqueue.queue = 1;
155         assert!(rxqueue.pending_rx());
156     }
157 }
158