Skip to main content

mdns_proto/wire/
opcode.rs

1//! DNS opcodes (RFC 1035 §4.1.1).
2
3use derive_more::{Display, IsVariant, TryUnwrap, Unwrap};
4
5/// DNS message opcode. mDNS requires `Opcode::Query` (0); other values are
6/// kept for round-trip correctness against non-conforming traffic.
7#[derive(
8  Debug, Display, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, IsVariant, Unwrap, TryUnwrap,
9)]
10#[display("{}", self.as_str())]
11#[non_exhaustive]
12pub enum Opcode {
13  /// Standard query (`0`).
14  Query,
15  /// Inverse query (`1`, obsoleted by RFC 3425).
16  InverseQuery,
17  /// Server status request (`2`).
18  Status,
19  /// Notify (`4`, RFC 1996).
20  Notify,
21  /// Dynamic update (`5`, RFC 2136).
22  Update,
23  /// Lossless escape for unknown opcodes encountered on the wire.
24  Unknown(u8),
25}
26
27impl Opcode {
28  /// Canonical lowercase slug for this opcode.
29  pub const fn as_str(&self) -> &'static str {
30    match self {
31      Self::Query => "query",
32      Self::InverseQuery => "inverse_query",
33      Self::Status => "status",
34      Self::Notify => "notify",
35      Self::Update => "update",
36      Self::Unknown(_) => "unknown",
37    }
38  }
39
40  /// Returns the wire-format `u8` value (only the low 4 bits are significant
41  /// in the actual flags field, but the conversion is total for `u8`).
42  #[inline(always)]
43  pub const fn to_u8(self) -> u8 {
44    match self {
45      Self::Query => 0,
46      Self::InverseQuery => 1,
47      Self::Status => 2,
48      Self::Notify => 4,
49      Self::Update => 5,
50      Self::Unknown(v) => v,
51    }
52  }
53
54  /// Reconstructs an `Opcode` from a wire-format `u8`. Always succeeds —
55  /// unknown values land in `Unknown(v)`.
56  #[inline(always)]
57  pub const fn from_u8(v: u8) -> Self {
58    match v {
59      0 => Self::Query,
60      1 => Self::InverseQuery,
61      2 => Self::Status,
62      4 => Self::Notify,
63      5 => Self::Update,
64      other => Self::Unknown(other),
65    }
66  }
67}
68
69#[cfg(test)]
70#[allow(clippy::unwrap_used)]
71mod tests;