Skip to main content

mdns_proto/wire/
resource_class.rs

1//! DNS resource record classes with mDNS-specific cache-flush bit.
2
3use derive_more::{Display, IsVariant, TryUnwrap, Unwrap};
4
5/// Mask for the mDNS cache-flush bit (top bit of the 16-bit class field).
6/// RFC 6762 §10.2 — set on response records to indicate "any prior record(s)
7/// of this name/type/class are now invalid".
8pub const CACHE_FLUSH_BIT: u16 = 0x8000;
9
10/// Mask for the mDNS unicast-response bit (top bit of the 16-bit class field
11/// in a question). RFC 6762 §5.4.
12pub const UNICAST_RESPONSE_BIT: u16 = 0x8000;
13
14/// DNS class. mDNS uses `In` (1) almost exclusively; the top bit is repurposed
15/// per RFC 6762.
16#[derive(
17  Debug, Display, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, IsVariant, Unwrap, TryUnwrap,
18)]
19#[display("{}", self.as_str())]
20#[non_exhaustive]
21pub enum ResourceClass {
22  /// Internet (`1`).
23  In,
24  /// Wildcard (`255`).
25  Any,
26  /// Lossless escape for unknown classes.
27  Unknown(u16),
28}
29
30impl ResourceClass {
31  /// Canonical lowercase slug for this resource class.
32  pub const fn as_str(&self) -> &'static str {
33    match self {
34      Self::In => "in",
35      Self::Any => "any",
36      Self::Unknown(_) => "unknown",
37    }
38  }
39
40  /// Returns the wire-format `u16` value.
41  #[inline(always)]
42  pub const fn to_u16(self) -> u16 {
43    match self {
44      Self::In => 1,
45      Self::Any => 255,
46      Self::Unknown(v) => v,
47    }
48  }
49
50  /// Reconstructs from a wire-format 16-bit class field, **stripping** the
51  /// top bit (cache-flush / unicast-response). Use [`Self::from_u16_raw`]
52  /// if you need to preserve the bit.
53  #[inline(always)]
54  pub const fn from_u16(v: u16) -> Self {
55    Self::from_u16_raw(v & !CACHE_FLUSH_BIT)
56  }
57
58  /// Reconstructs from a wire-format 16-bit class field without masking.
59  #[inline(always)]
60  pub const fn from_u16_raw(v: u16) -> Self {
61    match v {
62      1 => Self::In,
63      255 => Self::Any,
64      other => Self::Unknown(other),
65    }
66  }
67}
68
69#[cfg(test)]
70#[allow(clippy::unwrap_used)]
71mod tests;