dns_message_parser/rr/
rfc_8659.rs1use super::Class;
2use crate::DomainName;
3use hex::encode;
4use std::convert::{AsRef, TryFrom};
5use std::fmt::{Display, Formatter, Result as FmtResult};
6use thiserror::Error;
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash, Error)]
9pub enum TagError {
10 #[error("Tag is empty")]
11 Empty,
12 #[error("Tag contains illegal character: {0}")]
13 IllegalChar(char),
14}
15
16#[derive(Debug, Clone, PartialEq, Eq, Hash)]
17pub struct Tag(String);
18
19impl TryFrom<String> for Tag {
20 type Error = TagError;
21
22 fn try_from(mut tag: String) -> Result<Self, Self::Error> {
23 if tag.is_empty() {
24 return Err(TagError::Empty);
25 }
26
27 for c in tag.chars() {
28 if !c.is_ascii_alphanumeric() {
29 return Err(TagError::IllegalChar(c));
30 }
31 }
32
33 tag.make_ascii_lowercase();
34 Ok(Tag(tag))
35 }
36}
37
38impl AsRef<str> for Tag {
39 fn as_ref(&self) -> &str {
40 &self.0
41 }
42}
43
44impl Display for Tag {
45 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
46 write!(f, "{}", self.0)
47 }
48}
49
50#[derive(Debug, Clone, PartialEq, Eq, Hash)]
54pub struct CAA {
55 pub domain_name: DomainName,
56 pub ttl: u32,
57 pub class: Class,
58 pub flags: u8,
59 pub tag: Tag,
60 pub value: Vec<u8>,
61}
62
63impl_to_type!(CAA);
64
65impl Display for CAA {
66 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
67 write!(
68 f,
69 "{} {} {} CAA {} {} {}",
70 self.domain_name,
71 self.ttl,
72 self.class,
73 self.flags,
74 self.tag,
75 encode(&self.value)
76 )
77 }
78}