trust_dns_server/authority/
auth_lookup.rs1use std::iter::Chain;
9use std::slice::Iter;
10use std::sync::Arc;
11
12use cfg_if::cfg_if;
13
14use crate::authority::{LookupObject, LookupOptions};
15use crate::proto::rr::{LowerName, Record, RecordSet, RecordType, RrsetRecords};
16
17#[derive(Debug)]
25#[allow(clippy::large_enum_variant)]
26pub enum AuthLookup {
27 Empty,
29 Records {
32 answers: LookupRecords,
34 additionals: Option<LookupRecords>,
36 },
37 SOA(LookupRecords),
39 AXFR {
41 start_soa: LookupRecords,
43 records: LookupRecords,
45 end_soa: LookupRecords,
47 },
48}
49
50impl AuthLookup {
51 pub fn answers(answers: LookupRecords, additionals: Option<LookupRecords>) -> Self {
53 Self::Records {
54 answers,
55 additionals,
56 }
57 }
58
59 pub fn is_empty(&self) -> bool {
61 self.was_empty()
63 }
64
65 pub fn was_empty(&self) -> bool {
69 self.iter().count() == 0
70 }
71
72 pub fn iter(&self) -> AuthLookupIter<'_> {
74 self.into_iter()
75 }
76
77 pub fn unwrap_records(self) -> LookupRecords {
79 match self {
80 Self::Records { answers, .. } => answers,
82 _ => LookupRecords::default(),
83 }
84 }
85
86 pub fn take_additionals(&mut self) -> Option<LookupRecords> {
88 match self {
89 Self::Records {
90 ref mut additionals,
91 ..
92 } => additionals.take(),
93 _ => None,
94 }
95 }
96}
97
98impl LookupObject for AuthLookup {
99 fn is_empty(&self) -> bool {
100 Self::is_empty(self)
101 }
102
103 fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Record> + Send + 'a> {
104 let boxed_iter = Self::iter(self);
105 Box::new(boxed_iter)
106 }
107
108 fn take_additionals(&mut self) -> Option<Box<dyn LookupObject>> {
109 let additionals = Self::take_additionals(self);
110 additionals.map(|a| Box::new(a) as Box<dyn LookupObject>)
111 }
112}
113
114impl Default for AuthLookup {
115 fn default() -> Self {
116 Self::Empty
117 }
118}
119
120impl<'a> IntoIterator for &'a AuthLookup {
121 type Item = &'a Record;
122 type IntoIter = AuthLookupIter<'a>;
123
124 fn into_iter(self) -> Self::IntoIter {
125 match self {
126 AuthLookup::Empty => AuthLookupIter::Empty,
127 AuthLookup::Records { answers: r, .. } | AuthLookup::SOA(r) => {
129 AuthLookupIter::Records(r.into_iter())
130 }
131 AuthLookup::AXFR {
132 start_soa,
133 records,
134 end_soa,
135 } => AuthLookupIter::AXFR(start_soa.into_iter().chain(records).chain(end_soa)),
136 }
137 }
138}
139
140#[allow(clippy::large_enum_variant)]
142#[derive(Default)]
143pub enum AuthLookupIter<'r> {
144 #[default]
146 Empty,
147 Records(LookupRecordsIter<'r>),
149 AXFR(Chain<Chain<LookupRecordsIter<'r>, LookupRecordsIter<'r>>, LookupRecordsIter<'r>>),
151}
152
153impl<'r> Iterator for AuthLookupIter<'r> {
154 type Item = &'r Record;
155
156 fn next(&mut self) -> Option<Self::Item> {
157 match self {
158 AuthLookupIter::Empty => None,
159 AuthLookupIter::Records(i) => i.next(),
160 AuthLookupIter::AXFR(i) => i.next(),
161 }
162 }
163}
164
165impl From<LookupRecords> for AuthLookup {
166 fn from(lookup: LookupRecords) -> Self {
167 Self::Records {
168 answers: lookup,
169 additionals: None,
170 }
171 }
172}
173
174#[derive(Debug)]
183pub struct AnyRecords {
184 lookup_options: LookupOptions,
185 rrsets: Vec<Arc<RecordSet>>,
186 query_type: RecordType,
187 query_name: LowerName,
188}
189
190impl AnyRecords {
191 pub fn new(
193 lookup_options: LookupOptions,
194 rrsets: Vec<Arc<RecordSet>>,
196 query_type: RecordType,
197 query_name: LowerName,
198 ) -> Self {
199 Self {
200 lookup_options,
201 rrsets,
202 query_type,
203 query_name,
204 }
205 }
206
207 fn iter(&self) -> AnyRecordsIter<'_> {
208 self.into_iter()
209 }
210}
211
212impl<'r> IntoIterator for &'r AnyRecords {
213 type Item = &'r Record;
214 type IntoIter = AnyRecordsIter<'r>;
215
216 fn into_iter(self) -> Self::IntoIter {
217 AnyRecordsIter {
218 lookup_options: self.lookup_options,
219 rrsets: self.rrsets.iter(),
221 rrset: None,
222 records: None,
223 query_type: self.query_type,
224 query_name: &self.query_name,
225 }
226 }
227}
228
229#[allow(unused)]
231pub struct AnyRecordsIter<'r> {
232 lookup_options: LookupOptions,
233 rrsets: Iter<'r, Arc<RecordSet>>,
234 rrset: Option<&'r RecordSet>,
235 records: Option<RrsetRecords<'r>>,
236 query_type: RecordType,
237 query_name: &'r LowerName,
238}
239
240impl<'r> Iterator for AnyRecordsIter<'r> {
241 type Item = &'r Record;
242
243 fn next(&mut self) -> Option<Self::Item> {
244 use std::borrow::Borrow;
245
246 let query_type = self.query_type;
247 let query_name = self.query_name;
248
249 loop {
250 if let Some(ref mut records) = self.records {
251 let record = records
252 .by_ref()
253 .filter(|rr_set| {
254 query_type == RecordType::ANY || rr_set.record_type() != RecordType::SOA
255 })
256 .find(|rr_set| {
257 query_type == RecordType::AXFR
258 || &LowerName::from(rr_set.name()) == query_name
259 });
260
261 if record.is_some() {
262 return record;
263 }
264 }
265
266 self.rrset = self.rrsets.next().map(Borrow::borrow);
267
268 self.rrset?;
270
271 cfg_if! {
273 if #[cfg(feature = "dnssec")] {
274 self.records = Some(
275 self.rrset
276 .expect("rrset should not be None at this point")
277 .records(self.lookup_options.is_dnssec(), self.lookup_options.supported_algorithms()),
278 );
279 } else {
280 self.records = Some(self.rrset.expect("rrset should not be None at this point").records_without_rrsigs());
281 }
282 }
283 }
284 }
285}
286
287#[derive(Debug)]
289pub enum LookupRecords {
290 Empty,
292 Records {
294 lookup_options: LookupOptions,
296 records: Arc<RecordSet>,
298 },
299 ManyRecords(LookupOptions, Vec<Arc<RecordSet>>),
301 AnyRecords(AnyRecords),
304}
305
306impl LookupRecords {
307 pub fn new(lookup_options: LookupOptions, records: Arc<RecordSet>) -> Self {
309 Self::Records {
310 lookup_options,
311 records,
312 }
313 }
314
315 pub fn many(lookup_options: LookupOptions, mut records: Vec<Arc<RecordSet>>) -> Self {
317 records.reverse();
319 Self::ManyRecords(lookup_options, records)
320 }
321
322 pub fn was_empty(&self) -> bool {
326 self.iter().count() == 0
327 }
328
329 pub fn iter(&self) -> LookupRecordsIter<'_> {
331 self.into_iter()
332 }
333}
334
335impl Default for LookupRecords {
336 fn default() -> Self {
337 Self::Empty
338 }
339}
340
341impl<'a> IntoIterator for &'a LookupRecords {
342 type Item = &'a Record;
343 type IntoIter = LookupRecordsIter<'a>;
344
345 #[allow(unused_variables)]
346 fn into_iter(self) -> Self::IntoIter {
347 match self {
348 LookupRecords::Empty => LookupRecordsIter::Empty,
349 LookupRecords::Records {
350 lookup_options,
351 records,
352 } => LookupRecordsIter::RecordsIter(
353 lookup_options.rrset_with_supported_algorithms(records),
354 ),
355 LookupRecords::ManyRecords(lookup_options, r) => LookupRecordsIter::ManyRecordsIter(
356 r.iter()
357 .map(|r| lookup_options.rrset_with_supported_algorithms(r))
358 .collect(),
359 None,
360 ),
361 LookupRecords::AnyRecords(r) => LookupRecordsIter::AnyRecordsIter(r.iter()),
362 }
363 }
364}
365
366#[derive(Default)]
368pub enum LookupRecordsIter<'r> {
369 AnyRecordsIter(AnyRecordsIter<'r>),
371 RecordsIter(RrsetRecords<'r>),
373 ManyRecordsIter(Vec<RrsetRecords<'r>>, Option<RrsetRecords<'r>>),
375 #[default]
377 Empty,
378}
379
380impl<'r> Iterator for LookupRecordsIter<'r> {
381 type Item = &'r Record;
382
383 fn next(&mut self) -> Option<Self::Item> {
384 match self {
385 LookupRecordsIter::Empty => None,
386 LookupRecordsIter::AnyRecordsIter(current) => current.next(),
387 LookupRecordsIter::RecordsIter(current) => current.next(),
388 LookupRecordsIter::ManyRecordsIter(set, ref mut current) => loop {
389 if let Some(o) = current.as_mut().and_then(Iterator::next) {
390 return Some(o);
391 }
392
393 *current = set.pop();
394 if current.is_none() {
395 return None;
396 }
397 },
398 }
399 }
400}
401
402impl From<AnyRecords> for LookupRecords {
403 fn from(rrset_records: AnyRecords) -> Self {
404 Self::AnyRecords(rrset_records)
405 }
406}
407
408impl LookupObject for LookupRecords {
409 fn is_empty(&self) -> bool {
410 Self::was_empty(self)
411 }
412
413 fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Record> + Send + 'a> {
414 Box::new(self.iter())
415 }
416
417 fn take_additionals(&mut self) -> Option<Box<dyn LookupObject>> {
418 None
419 }
420}