Skip to main content

mdns_proto/wire/
response_code.rs

1//! DNS response codes (RFC 1035 §4.1.1 / RFC 6762 §18.11).
2
3use derive_more::{Display, IsVariant, TryUnwrap, Unwrap};
4
5/// DNS response code. mDNS requires `ResponseCode::NoError` in both queries
6/// and responses; other values are kept for round-trip correctness.
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 ResponseCode {
13  /// No error (`0`).
14  NoError,
15  /// Format error (`1`).
16  FormatError,
17  /// Server failure (`2`).
18  ServerFailure,
19  /// Name error (`3`, "NXDOMAIN").
20  NameError,
21  /// Not implemented (`4`).
22  NotImplemented,
23  /// Refused (`5`).
24  Refused,
25  /// Lossless escape for unknown response codes.
26  Unknown(u8),
27}
28
29impl ResponseCode {
30  /// Canonical lowercase slug for this response code.
31  pub const fn as_str(&self) -> &'static str {
32    match self {
33      Self::NoError => "no_error",
34      Self::FormatError => "format_error",
35      Self::ServerFailure => "server_failure",
36      Self::NameError => "name_error",
37      Self::NotImplemented => "not_implemented",
38      Self::Refused => "refused",
39      Self::Unknown(_) => "unknown",
40    }
41  }
42
43  /// Returns the wire-format `u8` value.
44  #[inline(always)]
45  pub const fn to_u8(self) -> u8 {
46    match self {
47      Self::NoError => 0,
48      Self::FormatError => 1,
49      Self::ServerFailure => 2,
50      Self::NameError => 3,
51      Self::NotImplemented => 4,
52      Self::Refused => 5,
53      Self::Unknown(v) => v,
54    }
55  }
56
57  /// Reconstructs a `ResponseCode` from a wire-format `u8`. Always succeeds —
58  /// unknown values land in `Unknown(v)`.
59  #[inline(always)]
60  pub const fn from_u8(v: u8) -> Self {
61    match v {
62      0 => Self::NoError,
63      1 => Self::FormatError,
64      2 => Self::ServerFailure,
65      3 => Self::NameError,
66      4 => Self::NotImplemented,
67      5 => Self::Refused,
68      other => Self::Unknown(other),
69    }
70  }
71}
72
73#[cfg(test)]
74#[allow(clippy::unwrap_used)]
75mod tests;