domain_core/bits/
question.rs

1//! A single question in a DNS message.
2//!
3//! This module defines the type `Question` which represents an entry in
4//! the question section of a DNS message.
5
6use std::fmt;
7use bytes::BufMut;
8use ::iana::{Class, Rtype};
9use super::compose::{Compose, Compress, Compressor};
10use super::name::ToDname;
11use super::parse::{Parse, Parser, ShortBuf};
12
13
14//------------ Question ------------------------------------------------------
15
16/// A question in a DNS message.
17///
18/// In DNS, a question describes what is requested in a query. It consists
19/// of three elements: a domain name, a record type, and a class. This type
20/// such a question.
21///
22/// Questions are generic over the domain name type. When read from an
23/// actual message, a [`ParsedDname`] has to be used because the name part
24/// may be compressed.
25///
26/// In order to allow questions on the fly, in particular when creating 
27/// messages via [`MessageBuilder`], the `From` trait is implemented for
28/// tuples of all three elements of a question as well as for only name
29/// and record type assuming `Class::In` which is likely what you want,
30/// anyway.
31///
32/// [`ParsedDname`]: ../name/struct.ParsedDname.html
33/// [`MessageBuilder`]: ../message_builder/struct.MessageBuilder.html
34#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
35pub struct Question<N: ToDname> {
36    /// The domain name of the question.
37    qname: N,
38
39    /// The record type of the question.
40    qtype: Rtype,
41
42    /// The class of the quesiton.
43    qclass: Class,
44}
45
46/// # Creation and Conversion
47///
48impl<N: ToDname> Question<N> {
49    /// Creates a new question from its three componets.
50    pub fn new(qname: N, qtype: Rtype, qclass: Class) -> Self {
51        Question { qname, qtype, qclass }
52    }
53
54    /// Creates a new question from a name and record type, assuming class IN.
55    pub fn new_in(qname: N, qtype: Rtype) -> Self {
56        Question { qname, qtype, qclass: Class::In }
57    }
58}
59
60
61/// # Field Access
62///
63impl<N: ToDname> Question<N> {
64    /// Returns a reference to the domain nmae in the question,
65    pub fn qname(&self) -> &N {
66        &self.qname
67    }
68
69    /// Returns the record type of the question.
70    pub fn qtype(&self) -> Rtype {
71        self.qtype
72    }
73
74    /// Returns the class of the question.
75    pub fn qclass(&self) -> Class {
76        self.qclass
77    }
78}
79
80
81//--- From
82
83impl<N: ToDname> From<(N, Rtype, Class)> for Question<N> {
84    fn from((name, rtype, class): (N, Rtype, Class)) -> Self {
85        Question::new(name, rtype, class)
86    }
87}
88
89impl<N: ToDname> From<(N, Rtype)> for Question<N> {
90    fn from((name, rtype): (N, Rtype)) -> Self {
91        Question::new(name, rtype, Class::In)
92    }
93}
94
95
96//--- Parse, Compose, and Compress
97
98impl<N: ToDname + Parse> Parse for Question<N> {
99    type Err = <N as Parse>::Err;
100
101    fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
102        Ok(Question::new(
103            N::parse(parser)?,
104            Rtype::parse(parser)?,
105            Class::parse(parser)?
106        ))
107    }
108
109    fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
110        N::skip(parser)?;
111        Rtype::skip(parser)?;
112        Class::skip(parser)?;
113        Ok(())
114    }
115}
116
117impl<N: ToDname> Compose for Question<N> {
118    fn compose_len(&self) -> usize {
119        self.qname.compose_len() + self.qtype.compose_len()
120            + self.qclass.compose_len()
121    }
122
123    fn compose<B: BufMut>(&self, buf: &mut B) {
124        self.qname.compose(buf);
125        self.qtype.compose(buf);
126        self.qclass.compose(buf);
127    }
128}
129
130impl<N: ToDname> Compress for Question<N> {
131    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
132        self.qname.compress(buf)?;
133        buf.compose(&self.qtype)?;
134        buf.compose(&self.qclass)
135    }
136}
137
138
139//--- Display
140
141impl<N: ToDname + fmt::Display> fmt::Display for Question<N> {
142    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
143        write!(f, "{}.\t{}\t{}", self.qname, self.qtype, self.qclass)
144    }
145}
146