hickory_proto/rr/
dns_class.rs1#![allow(clippy::use_self)]
10
11use alloc::string::ToString;
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 = ProtoError;
48
49 fn from_str(str: &str) -> ProtoResult<Self> {
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(ProtoErrorKind::UnknownDnsClassStr(str.to_string()).into()),
67 }
68 }
69}
70
71impl DNSClass {
72 #[deprecated(note = "use u16::into instead, this is now infallible")]
81 pub fn from_u16(value: u16) -> ProtoResult<Self> {
82 match value {
83 1 => Ok(Self::IN),
84 3 => Ok(Self::CH),
85 4 => Ok(Self::HS),
86 254 => Ok(Self::NONE),
87 255 => Ok(Self::ANY),
88 _ => Ok(Self::Unknown(value)),
89 }
90 }
91
92 pub fn for_opt(value: u16) -> Self {
94 let value = value.max(512);
96 Self::OPT(value)
97 }
98}
99
100impl BinEncodable for DNSClass {
101 fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
102 encoder.emit_u16((*self).into())
103 }
104}
105
106impl BinDecodable<'_> for DNSClass {
107 fn read(decoder: &mut BinDecoder<'_>) -> ProtoResult<Self> {
108 let this = Self::from(
109 decoder.read_u16()?.unverified(),
110 );
111
112 Ok(this)
113 }
114}
115
116impl From<DNSClass> for &'static str {
127 fn from(rt: DNSClass) -> &'static str {
128 match rt {
129 DNSClass::IN => "IN",
130 DNSClass::CH => "CH",
131 DNSClass::HS => "HS",
132 DNSClass::NONE => "NONE",
133 DNSClass::ANY => "ANY",
134 DNSClass::OPT(_) => "OPT",
135 DNSClass::Unknown(_) => "UNKNOWN",
136 }
137 }
138}
139
140impl From<u16> for DNSClass {
149 fn from(value: u16) -> Self {
150 match value {
151 1 => Self::IN,
152 3 => Self::CH,
153 4 => Self::HS,
154 254 => Self::NONE,
155 255 => Self::ANY,
156 _ => Self::Unknown(value),
157 }
158 }
159}
160
161impl From<DNSClass> for u16 {
170 fn from(rt: DNSClass) -> Self {
171 match rt {
172 DNSClass::IN => 1,
173 DNSClass::CH => 3,
174 DNSClass::HS => 4,
175 DNSClass::NONE => 254,
176 DNSClass::ANY => 255,
177 DNSClass::OPT(max_payload_len) => max_payload_len.max(512),
179 DNSClass::Unknown(unknown) => unknown,
180 }
181 }
182}
183
184impl PartialOrd<Self> for DNSClass {
185 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
186 Some(self.cmp(other))
187 }
188}
189
190impl Ord for DNSClass {
191 fn cmp(&self, other: &Self) -> Ordering {
192 u16::from(*self).cmp(&u16::from(*other))
193 }
194}
195
196impl Display for DNSClass {
197 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
198 f.write_str(Into::<&str>::into(*self))
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205 #[test]
206 fn test_order() {
207 let ordered = vec![
208 DNSClass::IN,
209 DNSClass::CH,
210 DNSClass::HS,
211 DNSClass::NONE,
212 DNSClass::ANY,
213 ];
214 let mut unordered = vec![
215 DNSClass::NONE,
216 DNSClass::HS,
217 DNSClass::CH,
218 DNSClass::IN,
219 DNSClass::ANY,
220 ];
221
222 unordered.sort();
223
224 assert_eq!(unordered, ordered);
225 }
226
227 #[test]
228 fn check_dns_class_parse_wont_panic_with_symbols() {
229 let dns_class = "a-b-c".to_ascii_uppercase().parse::<DNSClass>();
230 assert!(matches!(&dns_class, Err(ProtoError { .. })));
231 }
232}