hickory_proto/rr/
dns_class.rs1#![allow(clippy::use_self)]
10
11use alloc::borrow::ToOwned;
12use core::{
13 cmp::Ordering,
14 fmt::{self, Display, Formatter},
15 str::FromStr,
16};
17
18#[cfg(feature = "serde")]
19use serde::{Deserialize, Serialize};
20
21use crate::error::*;
22use crate::serialize::binary::*;
23
24#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
26#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
27#[allow(dead_code)]
28pub enum DNSClass {
29 IN,
31 CH,
33 HS,
35 NONE,
37 ANY,
39 OPT(u16),
42 Unknown(u16),
44}
45
46impl FromStr for DNSClass {
47 type Err = DecodeError;
48
49 fn from_str(str: &str) -> Result<Self, Self::Err> {
59 debug_assert!(str.chars().all(|x| !char::is_ascii_lowercase(&x)));
60 match str {
61 "IN" => Ok(Self::IN),
62 "CH" => Ok(Self::CH),
63 "HS" => Ok(Self::HS),
64 "NONE" => Ok(Self::NONE),
65 "ANY" | "*" => Ok(Self::ANY),
66 _ => Err(DecodeError::UnknownDnsClassStr(str.to_owned())),
67 }
68 }
69}
70
71impl DNSClass {
72 pub fn for_opt(value: u16) -> Self {
74 let value = value.max(512);
76 Self::OPT(value)
77 }
78}
79
80impl BinEncodable for DNSClass {
81 fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
82 encoder.emit_u16((*self).into())
83 }
84}
85
86impl BinDecodable<'_> for DNSClass {
87 fn read(decoder: &mut BinDecoder<'_>) -> Result<Self, DecodeError> {
88 let this = Self::from(
89 decoder.read_u16()?.unverified(),
90 );
91
92 Ok(this)
93 }
94}
95
96impl From<DNSClass> for &'static str {
107 fn from(rt: DNSClass) -> &'static str {
108 match rt {
109 DNSClass::IN => "IN",
110 DNSClass::CH => "CH",
111 DNSClass::HS => "HS",
112 DNSClass::NONE => "NONE",
113 DNSClass::ANY => "ANY",
114 DNSClass::OPT(_) => "OPT",
115 DNSClass::Unknown(_) => "UNKNOWN",
116 }
117 }
118}
119
120impl From<u16> for DNSClass {
129 fn from(value: u16) -> Self {
130 match value {
131 1 => Self::IN,
132 3 => Self::CH,
133 4 => Self::HS,
134 254 => Self::NONE,
135 255 => Self::ANY,
136 _ => Self::Unknown(value),
137 }
138 }
139}
140
141impl From<DNSClass> for u16 {
150 fn from(rt: DNSClass) -> Self {
151 match rt {
152 DNSClass::IN => 1,
153 DNSClass::CH => 3,
154 DNSClass::HS => 4,
155 DNSClass::NONE => 254,
156 DNSClass::ANY => 255,
157 DNSClass::OPT(max_payload_len) => max_payload_len.max(512),
159 DNSClass::Unknown(unknown) => unknown,
160 }
161 }
162}
163
164impl PartialOrd<Self> for DNSClass {
165 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
166 Some(self.cmp(other))
167 }
168}
169
170impl Ord for DNSClass {
171 fn cmp(&self, other: &Self) -> Ordering {
172 u16::from(*self).cmp(&u16::from(*other))
173 }
174}
175
176impl Display for DNSClass {
177 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
178 f.write_str(Into::<&str>::into(*self))
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185 #[test]
186 fn test_order() {
187 let ordered = vec![
188 DNSClass::IN,
189 DNSClass::CH,
190 DNSClass::HS,
191 DNSClass::NONE,
192 DNSClass::ANY,
193 ];
194 let mut unordered = vec![
195 DNSClass::NONE,
196 DNSClass::HS,
197 DNSClass::CH,
198 DNSClass::IN,
199 DNSClass::ANY,
200 ];
201
202 unordered.sort();
203
204 assert_eq!(unordered, ordered);
205 }
206
207 #[test]
208 fn check_dns_class_parse_wont_panic_with_symbols() {
209 let dns_class = "a-b-c".to_ascii_uppercase().parse::<DNSClass>();
210 assert!(matches!(
211 &dns_class,
212 Err(DecodeError::UnknownDnsClassStr(_))
213 ));
214 }
215}