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 match str {
60 "IN" => Ok(Self::IN),
61 "CH" => Ok(Self::CH),
62 "HS" => Ok(Self::HS),
63 "NONE" => Ok(Self::NONE),
64 "ANY" | "*" => Ok(Self::ANY),
65 _ => Err(DecodeError::UnknownDnsClassStr(str.to_owned())),
66 }
67 }
68}
69
70impl DNSClass {
71 pub fn for_opt(value: u16) -> Self {
73 let value = value.max(512);
75 Self::OPT(value)
76 }
77}
78
79impl BinEncodable for DNSClass {
80 fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
81 encoder.emit_u16((*self).into())
82 }
83}
84
85impl BinDecodable<'_> for DNSClass {
86 fn read(decoder: &mut BinDecoder<'_>) -> Result<Self, DecodeError> {
87 let this = Self::from(
88 decoder.read_u16()?.unverified(),
89 );
90
91 Ok(this)
92 }
93}
94
95impl From<DNSClass> for &'static str {
106 fn from(rt: DNSClass) -> &'static str {
107 match rt {
108 DNSClass::IN => "IN",
109 DNSClass::CH => "CH",
110 DNSClass::HS => "HS",
111 DNSClass::NONE => "NONE",
112 DNSClass::ANY => "ANY",
113 DNSClass::OPT(_) => "OPT",
114 DNSClass::Unknown(_) => "UNKNOWN",
115 }
116 }
117}
118
119impl From<u16> for DNSClass {
128 fn from(value: u16) -> Self {
129 match value {
130 1 => Self::IN,
131 3 => Self::CH,
132 4 => Self::HS,
133 254 => Self::NONE,
134 255 => Self::ANY,
135 _ => Self::Unknown(value),
136 }
137 }
138}
139
140impl From<DNSClass> for u16 {
149 fn from(rt: DNSClass) -> Self {
150 match rt {
151 DNSClass::IN => 1,
152 DNSClass::CH => 3,
153 DNSClass::HS => 4,
154 DNSClass::NONE => 254,
155 DNSClass::ANY => 255,
156 DNSClass::OPT(max_payload_len) => max_payload_len.max(512),
158 DNSClass::Unknown(unknown) => unknown,
159 }
160 }
161}
162
163impl PartialOrd<Self> for DNSClass {
164 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
165 Some(self.cmp(other))
166 }
167}
168
169impl Ord for DNSClass {
170 fn cmp(&self, other: &Self) -> Ordering {
171 u16::from(*self).cmp(&u16::from(*other))
172 }
173}
174
175impl Display for DNSClass {
176 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
177 f.write_str(Into::<&str>::into(*self))
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184 #[test]
185 fn test_order() {
186 let ordered = vec![
187 DNSClass::IN,
188 DNSClass::CH,
189 DNSClass::HS,
190 DNSClass::NONE,
191 DNSClass::ANY,
192 ];
193 let mut unordered = vec![
194 DNSClass::NONE,
195 DNSClass::HS,
196 DNSClass::CH,
197 DNSClass::IN,
198 DNSClass::ANY,
199 ];
200
201 unordered.sort();
202
203 assert_eq!(unordered, ordered);
204 }
205
206 #[test]
207 fn check_dns_class_parse_wont_panic_with_symbols() {
208 let dns_class = "a-b-c".to_ascii_uppercase().parse::<DNSClass>();
209 assert!(matches!(
210 &dns_class,
211 Err(DecodeError::UnknownDnsClassStr(_))
212 ));
213 }
214}