use super::{Opcode, ResponseCode};
const QR_BIT: u16 = 1 << 15;
const OPCODE_SHIFT: u32 = 11;
const OPCODE_MASK: u16 = 0b1111 << OPCODE_SHIFT;
const AA_BIT: u16 = 1 << 10;
const TC_BIT: u16 = 1 << 9;
const RD_BIT: u16 = 1 << 8;
const RA_BIT: u16 = 1 << 7;
const RCODE_MASK: u16 = 0b1111;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]
pub struct Flags {
bits: u16,
}
impl Flags {
#[inline(always)]
pub const fn new() -> Self {
Self { bits: 0 }
}
#[inline(always)]
pub const fn from_u16(bits: u16) -> Self {
Self { bits }
}
#[inline(always)]
pub const fn to_u16(&self) -> u16 {
self.bits
}
#[inline(always)]
pub const fn is_response(&self) -> bool {
self.bits & QR_BIT != 0
}
#[inline(always)]
pub const fn opcode(&self) -> Opcode {
Opcode::from_u8(((self.bits & OPCODE_MASK) >> OPCODE_SHIFT) as u8)
}
#[inline(always)]
pub const fn is_authoritative(&self) -> bool {
self.bits & AA_BIT != 0
}
#[inline(always)]
pub const fn is_truncated(&self) -> bool {
self.bits & TC_BIT != 0
}
#[inline(always)]
pub const fn is_recursion_desired(&self) -> bool {
self.bits & RD_BIT != 0
}
#[inline(always)]
pub const fn is_recursion_available(&self) -> bool {
self.bits & RA_BIT != 0
}
#[inline(always)]
pub const fn response_code(&self) -> ResponseCode {
ResponseCode::from_u8((self.bits & RCODE_MASK) as u8)
}
#[inline(always)]
pub const fn set_response(&mut self) -> &mut Self {
self.bits |= QR_BIT;
self
}
#[inline(always)]
pub const fn with_response(mut self) -> Self {
self.bits |= QR_BIT;
self
}
#[inline(always)]
pub const fn clear_response(&mut self) -> &mut Self {
self.bits &= !QR_BIT;
self
}
#[inline(always)]
pub const fn set_opcode(&mut self, op: Opcode) -> &mut Self {
self.bits &= !OPCODE_MASK;
self.bits |= ((op.to_u8() as u16) << OPCODE_SHIFT) & OPCODE_MASK;
self
}
#[inline(always)]
pub const fn with_opcode(mut self, op: Opcode) -> Self {
self.bits &= !OPCODE_MASK;
self.bits |= ((op.to_u8() as u16) << OPCODE_SHIFT) & OPCODE_MASK;
self
}
#[inline(always)]
pub const fn set_authoritative(&mut self) -> &mut Self {
self.bits |= AA_BIT;
self
}
#[inline(always)]
pub const fn with_authoritative(mut self) -> Self {
self.bits |= AA_BIT;
self
}
#[inline(always)]
pub const fn clear_authoritative(&mut self) -> &mut Self {
self.bits &= !AA_BIT;
self
}
#[inline(always)]
pub const fn set_truncated(&mut self) -> &mut Self {
self.bits |= TC_BIT;
self
}
#[inline(always)]
pub const fn with_truncated(mut self) -> Self {
self.bits |= TC_BIT;
self
}
#[inline(always)]
pub const fn clear_truncated(&mut self) -> &mut Self {
self.bits &= !TC_BIT;
self
}
#[inline(always)]
pub const fn set_response_code(&mut self, rc: ResponseCode) -> &mut Self {
self.bits &= !RCODE_MASK;
self.bits |= (rc.to_u8() as u16) & RCODE_MASK;
self
}
#[inline(always)]
pub const fn with_response_code(mut self, rc: ResponseCode) -> Self {
self.bits &= !RCODE_MASK;
self.bits |= (rc.to_u8() as u16) & RCODE_MASK;
self
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests;