Skip to main content

hickory_proto/op/
lower_query.rs

1// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use core::fmt::{self, Display};
9
10use crate::error::*;
11use crate::op::Query;
12use crate::rr::LowerName;
13use crate::rr::{DNSClass, RecordType};
14use crate::serialize::binary::*;
15
16/// Identical to [`Query`], except that the Name is guaranteed to be in lower case form.
17///
18/// This guarantee is helpful for performance reasons, as case-sensitive comparisons
19/// can be done faster. Name comparison is a frequent operation and so overall performance
20/// benefits.
21#[derive(Clone, Debug, PartialEq, Eq)]
22pub struct LowerQuery {
23    name: LowerName,
24    original: Query,
25}
26
27impl LowerQuery {
28    /// Create a new query from name and type, class defaults to IN
29    pub fn query(query: Query) -> Self {
30        Self {
31            name: LowerName::new(query.name()),
32            original: query,
33        }
34    }
35
36    /// ```text
37    /// QNAME           a domain name represented as a sequence of labels, where
38    ///                 each label consists of a length octet followed by that
39    ///                 number of octets.  The domain name terminates with the
40    ///                 zero length octet for the null label of the root.  Note
41    ///                 that this field may be an odd number of octets; no
42    ///                 padding is used.
43    /// ```
44    pub fn name(&self) -> &LowerName {
45        &self.name
46    }
47
48    /// Returns the original with the `Name`s case preserved
49    pub fn original(&self) -> &Query {
50        &self.original
51    }
52
53    /// ```text
54    /// QTYPE           a two octet code which specifies the type of the query.
55    ///                 The values for this field include all codes valid for a
56    ///                 TYPE field, together with some more general codes which
57    ///                 can match more than one type of RR.
58    /// ```
59    pub fn query_type(&self) -> RecordType {
60        self.original.query_type()
61    }
62
63    /// ```text
64    /// QCLASS          a two octet code that specifies the class of the query.
65    ///                 For example, the QCLASS field is IN for the Internet.
66    /// ```
67    pub fn query_class(&self) -> DNSClass {
68        self.original.query_class()
69    }
70}
71
72impl From<Query> for LowerQuery {
73    fn from(query: Query) -> Self {
74        Self::query(query)
75    }
76}
77
78impl BinEncodable for LowerQuery {
79    fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
80        self.original.emit(encoder)
81    }
82}
83
84impl<'r> BinDecodable<'r> for LowerQuery {
85    fn read(decoder: &mut BinDecoder<'r>) -> Result<Self, DecodeError> {
86        let original = Query::read(decoder)?;
87        Ok(Self::query(original))
88    }
89}
90
91impl Display for LowerQuery {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
93        write!(
94            f,
95            "name: {} type: {} class: {}",
96            self.name,
97            self.original.query_type(),
98            self.original.query_class()
99        )
100    }
101}