trust_dns_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}
40
41impl FromStr for DNSClass {
42 type Err = ProtoError;
43
44 fn from_str(str: &str) -> ProtoResult<Self> {
54 debug_assert!(str.chars().all(|x| !char::is_ascii_lowercase(&x)));
55 match str {
56 "IN" => Ok(Self::IN),
57 "CH" => Ok(Self::CH),
58 "HS" => Ok(Self::HS),
59 "NONE" => Ok(Self::NONE),
60 "ANY" | "*" => Ok(Self::ANY),
61 _ => Err(ProtoErrorKind::UnknownDnsClassStr(str.to_string()).into()),
62 }
63 }
64}
65
66impl DNSClass {
67 pub fn from_u16(value: u16) -> ProtoResult<Self> {
76 match value {
77 1 => Ok(Self::IN),
78 3 => Ok(Self::CH),
79 4 => Ok(Self::HS),
80 254 => Ok(Self::NONE),
81 255 => Ok(Self::ANY),
82 _ => Err(ProtoErrorKind::UnknownDnsClassValue(value).into()),
83 }
84 }
85
86 pub fn for_opt(value: u16) -> Self {
88 let value = value.max(512);
90 Self::OPT(value)
91 }
92}
93
94impl BinEncodable for DNSClass {
95 fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
96 encoder.emit_u16((*self).into())
97 }
98}
99
100impl<'r> BinDecodable<'r> for DNSClass {
101 fn read(decoder: &mut BinDecoder<'_>) -> ProtoResult<Self> {
102 Self::from_u16(
103 decoder.read_u16()?.unverified(),
104 )
105 }
106}
107
108impl From<DNSClass> for &'static str {
119 fn from(rt: DNSClass) -> &'static str {
120 match rt {
121 DNSClass::IN => "IN",
122 DNSClass::CH => "CH",
123 DNSClass::HS => "HS",
124 DNSClass::NONE => "NONE",
125 DNSClass::ANY => "ANY",
126 DNSClass::OPT(_) => "OPT",
127 }
128 }
129}
130
131impl From<DNSClass> for u16 {
140 fn from(rt: DNSClass) -> Self {
141 match rt {
142 DNSClass::IN => 1,
143 DNSClass::CH => 3,
144 DNSClass::HS => 4,
145 DNSClass::NONE => 254,
146 DNSClass::ANY => 255,
147 DNSClass::OPT(max_payload_len) => max_payload_len.max(512),
149 }
150 }
151}
152
153impl PartialOrd<Self> for DNSClass {
154 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
155 Some(self.cmp(other))
156 }
157}
158
159impl Ord for DNSClass {
160 fn cmp(&self, other: &Self) -> Ordering {
161 u16::from(*self).cmp(&u16::from(*other))
162 }
163}
164
165impl Display for DNSClass {
166 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
167 f.write_str(Into::<&str>::into(*self))
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174 #[test]
175 fn test_order() {
176 let ordered = vec![
177 DNSClass::IN,
178 DNSClass::CH,
179 DNSClass::HS,
180 DNSClass::NONE,
181 DNSClass::ANY,
182 ];
183 let mut unordered = vec![
184 DNSClass::NONE,
185 DNSClass::HS,
186 DNSClass::CH,
187 DNSClass::IN,
188 DNSClass::ANY,
189 ];
190
191 unordered.sort();
192
193 assert_eq!(unordered, ordered);
194 }
195
196 #[test]
197 fn check_dns_class_parse_wont_panic_with_symbols() {
198 let dns_class = "a-b-c".to_ascii_uppercase().parse::<DNSClass>();
199 assert!(matches!(&dns_class, Err(ProtoError { .. })));
200 }
201}