hickory_proto/rr/
dns_class.rs1#![allow(clippy::use_self)]
10
11use std::cmp::Ordering;
12use std::fmt::{self, Display, Formatter};
13use std::str::FromStr;
14
15#[cfg(feature = "serde-config")]
16use serde::{Deserialize, Serialize};
17
18use crate::error::*;
19use crate::serialize::binary::*;
20
21#[cfg_attr(feature = "serde-config", derive(Deserialize, Serialize))]
23#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
24#[allow(dead_code)]
25pub enum DNSClass {
26 IN,
28 CH,
30 HS,
32 NONE,
34 ANY,
36 OPT(u16),
39 Unknown(u16),
41}
42
43impl FromStr for DNSClass {
44 type Err = ProtoError;
45
46 fn from_str(str: &str) -> ProtoResult<Self> {
56 debug_assert!(str.chars().all(|x| !char::is_ascii_lowercase(&x)));
57 match str {
58 "IN" => Ok(Self::IN),
59 "CH" => Ok(Self::CH),
60 "HS" => Ok(Self::HS),
61 "NONE" => Ok(Self::NONE),
62 "ANY" | "*" => Ok(Self::ANY),
63 _ => Err(ProtoErrorKind::UnknownDnsClassStr(str.to_string()).into()),
64 }
65 }
66}
67
68impl DNSClass {
69 #[deprecated(note = "use u16::into instead, this is now infallible")]
78 pub fn from_u16(value: u16) -> ProtoResult<Self> {
79 match value {
80 1 => Ok(Self::IN),
81 3 => Ok(Self::CH),
82 4 => Ok(Self::HS),
83 254 => Ok(Self::NONE),
84 255 => Ok(Self::ANY),
85 _ => Ok(Self::Unknown(value)),
86 }
87 }
88
89 pub fn for_opt(value: u16) -> Self {
91 let value = value.max(512);
93 Self::OPT(value)
94 }
95}
96
97impl BinEncodable for DNSClass {
98 fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
99 encoder.emit_u16((*self).into())
100 }
101}
102
103impl BinDecodable<'_> for DNSClass {
104 fn read(decoder: &mut BinDecoder<'_>) -> ProtoResult<Self> {
105 let this = Self::from(
106 decoder.read_u16()?.unverified(),
107 );
108
109 Ok(this)
110 }
111}
112
113impl From<DNSClass> for &'static str {
124 fn from(rt: DNSClass) -> &'static str {
125 match rt {
126 DNSClass::IN => "IN",
127 DNSClass::CH => "CH",
128 DNSClass::HS => "HS",
129 DNSClass::NONE => "NONE",
130 DNSClass::ANY => "ANY",
131 DNSClass::OPT(_) => "OPT",
132 DNSClass::Unknown(_) => "UNKNOWN",
133 }
134 }
135}
136
137impl From<u16> for DNSClass {
146 fn from(value: u16) -> Self {
147 match value {
148 1 => Self::IN,
149 3 => Self::CH,
150 4 => Self::HS,
151 254 => Self::NONE,
152 255 => Self::ANY,
153 _ => Self::Unknown(value),
154 }
155 }
156}
157
158impl From<DNSClass> for u16 {
167 fn from(rt: DNSClass) -> Self {
168 match rt {
169 DNSClass::IN => 1,
170 DNSClass::CH => 3,
171 DNSClass::HS => 4,
172 DNSClass::NONE => 254,
173 DNSClass::ANY => 255,
174 DNSClass::OPT(max_payload_len) => max_payload_len.max(512),
176 DNSClass::Unknown(unknown) => unknown,
177 }
178 }
179}
180
181impl PartialOrd<Self> for DNSClass {
182 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
183 Some(self.cmp(other))
184 }
185}
186
187impl Ord for DNSClass {
188 fn cmp(&self, other: &Self) -> Ordering {
189 u16::from(*self).cmp(&u16::from(*other))
190 }
191}
192
193impl Display for DNSClass {
194 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
195 f.write_str(Into::<&str>::into(*self))
196 }
197}
198
199#[cfg(test)]
200mod tests {
201 use super::*;
202 #[test]
203 fn test_order() {
204 let ordered = vec![
205 DNSClass::IN,
206 DNSClass::CH,
207 DNSClass::HS,
208 DNSClass::NONE,
209 DNSClass::ANY,
210 ];
211 let mut unordered = vec![
212 DNSClass::NONE,
213 DNSClass::HS,
214 DNSClass::CH,
215 DNSClass::IN,
216 DNSClass::ANY,
217 ];
218
219 unordered.sort();
220
221 assert_eq!(unordered, ordered);
222 }
223
224 #[test]
225 fn check_dns_class_parse_wont_panic_with_symbols() {
226 let dns_class = "a-b-c".to_ascii_uppercase().parse::<DNSClass>();
227 assert!(matches!(&dns_class, Err(ProtoError { .. })));
228 }
229}