1use super::{Opcode, ResponseCode};
4
5const QR_BIT: u16 = 1 << 15;
6const OPCODE_SHIFT: u32 = 11;
7const OPCODE_MASK: u16 = 0b1111 << OPCODE_SHIFT;
8const AA_BIT: u16 = 1 << 10;
9const TC_BIT: u16 = 1 << 9;
10const RD_BIT: u16 = 1 << 8;
11const RA_BIT: u16 = 1 << 7;
12const RCODE_MASK: u16 = 0b1111;
13
14#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]
16pub struct Flags {
17 bits: u16,
18}
19
20impl Flags {
21 #[inline(always)]
23 pub const fn new() -> Self {
24 Self { bits: 0 }
25 }
26
27 #[inline(always)]
29 pub const fn from_u16(bits: u16) -> Self {
30 Self { bits }
31 }
32
33 #[inline(always)]
35 pub const fn to_u16(&self) -> u16 {
36 self.bits
37 }
38
39 #[inline(always)]
41 pub const fn is_response(&self) -> bool {
42 self.bits & QR_BIT != 0
43 }
44
45 #[inline(always)]
47 pub const fn opcode(&self) -> Opcode {
48 Opcode::from_u8(((self.bits & OPCODE_MASK) >> OPCODE_SHIFT) as u8)
49 }
50
51 #[inline(always)]
53 pub const fn is_authoritative(&self) -> bool {
54 self.bits & AA_BIT != 0
55 }
56
57 #[inline(always)]
59 pub const fn is_truncated(&self) -> bool {
60 self.bits & TC_BIT != 0
61 }
62
63 #[inline(always)]
65 pub const fn is_recursion_desired(&self) -> bool {
66 self.bits & RD_BIT != 0
67 }
68
69 #[inline(always)]
71 pub const fn is_recursion_available(&self) -> bool {
72 self.bits & RA_BIT != 0
73 }
74
75 #[inline(always)]
77 pub const fn response_code(&self) -> ResponseCode {
78 ResponseCode::from_u8((self.bits & RCODE_MASK) as u8)
79 }
80
81 #[inline(always)]
85 pub const fn set_response(&mut self) -> &mut Self {
86 self.bits |= QR_BIT;
87 self
88 }
89 #[inline(always)]
91 pub const fn with_response(mut self) -> Self {
92 self.bits |= QR_BIT;
93 self
94 }
95 #[inline(always)]
97 pub const fn clear_response(&mut self) -> &mut Self {
98 self.bits &= !QR_BIT;
99 self
100 }
101
102 #[inline(always)]
104 pub const fn set_opcode(&mut self, op: Opcode) -> &mut Self {
105 self.bits &= !OPCODE_MASK;
106 self.bits |= ((op.to_u8() as u16) << OPCODE_SHIFT) & OPCODE_MASK;
107 self
108 }
109 #[inline(always)]
111 pub const fn with_opcode(mut self, op: Opcode) -> Self {
112 self.bits &= !OPCODE_MASK;
113 self.bits |= ((op.to_u8() as u16) << OPCODE_SHIFT) & OPCODE_MASK;
114 self
115 }
116
117 #[inline(always)]
119 pub const fn set_authoritative(&mut self) -> &mut Self {
120 self.bits |= AA_BIT;
121 self
122 }
123 #[inline(always)]
125 pub const fn with_authoritative(mut self) -> Self {
126 self.bits |= AA_BIT;
127 self
128 }
129 #[inline(always)]
131 pub const fn clear_authoritative(&mut self) -> &mut Self {
132 self.bits &= !AA_BIT;
133 self
134 }
135
136 #[inline(always)]
138 pub const fn set_truncated(&mut self) -> &mut Self {
139 self.bits |= TC_BIT;
140 self
141 }
142 #[inline(always)]
144 pub const fn with_truncated(mut self) -> Self {
145 self.bits |= TC_BIT;
146 self
147 }
148 #[inline(always)]
150 pub const fn clear_truncated(&mut self) -> &mut Self {
151 self.bits &= !TC_BIT;
152 self
153 }
154
155 #[inline(always)]
157 pub const fn set_response_code(&mut self, rc: ResponseCode) -> &mut Self {
158 self.bits &= !RCODE_MASK;
159 self.bits |= (rc.to_u8() as u16) & RCODE_MASK;
160 self
161 }
162 #[inline(always)]
164 pub const fn with_response_code(mut self, rc: ResponseCode) -> Self {
165 self.bits &= !RCODE_MASK;
166 self.bits |= (rc.to_u8() as u16) & RCODE_MASK;
167 self
168 }
169}
170
171#[cfg(test)]
172#[allow(clippy::unwrap_used)]
173mod tests;