1use super::super::scan::Scanner;
7use super::label::Label;
8use super::relative::DnameIter;
9use super::traits::{FlattenInto, ToDname, ToLabelIter, ToRelativeDname};
10use super::uncertain::UncertainDname;
11use super::Dname;
12use core::{fmt, iter};
13use octseq::builder::{
14 BuilderAppendError, EmptyBuilder, FreezeBuilder, FromBuilder,
15};
16
17#[derive(Clone, Debug)]
37#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
38pub struct Chain<L, R> {
39 left: L,
41
42 right: R,
44}
45
46impl<L: ToLabelIter, R: ToLabelIter> Chain<L, R> {
47 pub(super) fn new(left: L, right: R) -> Result<Self, LongChainError> {
49 if usize::from(left.compose_len() + right.compose_len())
50 > Dname::MAX_LEN
51 {
52 Err(LongChainError)
54 } else {
55 Ok(Chain { left, right })
56 }
57 }
58}
59
60impl<Octets: AsRef<[u8]>, R: ToLabelIter> Chain<UncertainDname<Octets>, R> {
61 pub(super) fn new_uncertain(
66 left: UncertainDname<Octets>,
67 right: R,
68 ) -> Result<Self, LongChainError> {
69 if let UncertainDname::Relative(ref name) = left {
70 if usize::from(name.compose_len() + right.compose_len())
71 > Dname::MAX_LEN
72 {
73 return Err(LongChainError);
74 }
75 }
76 Ok(Chain { left, right })
77 }
78}
79
80impl<L, R> Chain<L, R> {
81 pub fn scan<S: Scanner<Dname = Self>>(
82 scanner: &mut S,
83 ) -> Result<Self, S::Error> {
84 scanner.scan_dname()
85 }
86}
87
88impl<L: ToRelativeDname, R: ToLabelIter> Chain<L, R> {
89 pub fn chain<N: ToLabelIter>(
103 self,
104 other: N,
105 ) -> Result<Chain<Self, N>, LongChainError> {
106 Chain::new(self, other)
107 }
108}
109
110impl<L, R> Chain<L, R> {
111 pub fn unwrap(self) -> (L, R) {
113 (self.left, self.right)
114 }
115}
116
117impl<L: ToRelativeDname, R: ToLabelIter> ToLabelIter for Chain<L, R> {
120 type LabelIter<'a> = ChainIter<'a, L, R> where L: 'a, R: 'a;
121
122 fn iter_labels(&self) -> Self::LabelIter<'_> {
123 ChainIter(self.left.iter_labels().chain(self.right.iter_labels()))
124 }
125
126 fn compose_len(&self) -> u16 {
127 self.left
128 .compose_len()
129 .checked_add(self.right.compose_len())
130 .expect("long domain name")
131 }
132}
133
134impl<Octs, R> ToLabelIter for Chain<UncertainDname<Octs>, R>
135where
136 Octs: AsRef<[u8]>,
137 R: ToDname,
138{
139 type LabelIter<'a> = UncertainChainIter<'a, Octs, R>
140 where Octs: 'a, R: 'a;
141
142 fn iter_labels(&self) -> Self::LabelIter<'_> {
143 match self.left {
144 UncertainDname::Absolute(ref name) => {
145 UncertainChainIter::Absolute(name.iter_labels())
146 }
147 UncertainDname::Relative(ref name) => {
148 UncertainChainIter::Relative(ChainIter(
149 name.iter_labels().chain(self.right.iter_labels()),
150 ))
151 }
152 }
153 }
154
155 fn compose_len(&self) -> u16 {
156 match self.left {
157 UncertainDname::Absolute(ref name) => name.compose_len(),
158 UncertainDname::Relative(ref name) => name
159 .compose_len()
160 .checked_add(self.right.compose_len())
161 .expect("long domain name"),
162 }
163 }
164}
165
166impl<L: ToRelativeDname, R: ToRelativeDname> ToRelativeDname for Chain<L, R> {}
167
168impl<L: ToRelativeDname, R: ToDname> ToDname for Chain<L, R> {}
169
170impl<Octets, R> ToDname for Chain<UncertainDname<Octets>, R>
171where
172 Octets: AsRef<[u8]>,
173 R: ToDname,
174{
175}
176
177impl<L, R, Target> FlattenInto<Dname<Target>> for Chain<L, R>
180where
181 L: ToRelativeDname,
182 R: ToDname,
183 R: FlattenInto<Dname<Target>, AppendError = BuilderAppendError<Target>>,
184 Target: FromBuilder,
185 <Target as FromBuilder>::Builder: EmptyBuilder,
186{
187 type AppendError = BuilderAppendError<Target>;
188
189 fn try_flatten_into(self) -> Result<Dname<Target>, Self::AppendError> {
190 if self.left.is_empty() {
191 self.right.try_flatten_into()
192 } else {
193 let mut builder =
194 Target::Builder::with_capacity(self.compose_len().into());
195 self.compose(&mut builder)?;
196 Ok(unsafe { Dname::from_octets_unchecked(builder.freeze()) })
197 }
198 }
199}
200
201impl<L: fmt::Display, R: fmt::Display> fmt::Display for Chain<L, R> {
204 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
205 write!(f, "{}.{}", self.left, self.right)
206 }
207}
208
209#[derive(Debug)]
213pub struct ChainIter<'a, L: ToLabelIter + 'a, R: ToLabelIter + 'a>(
214 iter::Chain<L::LabelIter<'a>, R::LabelIter<'a>>,
215);
216
217impl<'a, L, R> Clone for ChainIter<'a, L, R>
218where
219 L: ToLabelIter,
220 R: ToLabelIter,
221{
222 fn clone(&self) -> Self {
223 ChainIter(self.0.clone())
224 }
225}
226
227impl<'a, L, R> Iterator for ChainIter<'a, L, R>
228where
229 L: ToLabelIter,
230 R: ToLabelIter,
231{
232 type Item = &'a Label;
233
234 fn next(&mut self) -> Option<Self::Item> {
235 self.0.next()
236 }
237}
238
239impl<'a, L, R> DoubleEndedIterator for ChainIter<'a, L, R>
240where
241 L: ToLabelIter,
242 R: ToLabelIter,
243{
244 fn next_back(&mut self) -> Option<Self::Item> {
245 self.0.next_back()
246 }
247}
248
249pub enum UncertainChainIter<'a, Octets: AsRef<[u8]>, R: ToLabelIter> {
253 Absolute(DnameIter<'a>),
254 Relative(ChainIter<'a, UncertainDname<Octets>, R>),
255}
256
257impl<'a, Octets, R> Clone for UncertainChainIter<'a, Octets, R>
258where
259 Octets: AsRef<[u8]>,
260 R: ToLabelIter,
261{
262 fn clone(&self) -> Self {
263 use UncertainChainIter::*;
264
265 match *self {
266 Absolute(ref inner) => Absolute(inner.clone()),
267 Relative(ref inner) => Relative(inner.clone()),
268 }
269 }
270}
271
272impl<'a, Octets, R> Iterator for UncertainChainIter<'a, Octets, R>
273where
274 Octets: AsRef<[u8]>,
275 R: ToLabelIter,
276{
277 type Item = &'a Label;
278
279 fn next(&mut self) -> Option<Self::Item> {
280 match *self {
281 UncertainChainIter::Absolute(ref mut inner) => inner.next(),
282 UncertainChainIter::Relative(ref mut inner) => inner.next(),
283 }
284 }
285}
286
287impl<'a, Octets, R> DoubleEndedIterator for UncertainChainIter<'a, Octets, R>
288where
289 Octets: AsRef<[u8]>,
290 R: ToLabelIter,
291{
292 fn next_back(&mut self) -> Option<Self::Item> {
293 match *self {
294 UncertainChainIter::Absolute(ref mut inner) => inner.next_back(),
295 UncertainChainIter::Relative(ref mut inner) => inner.next_back(),
296 }
297 }
298}
299
300#[derive(Clone, Copy, Debug, Eq, PartialEq)]
306pub struct LongChainError;
307
308impl fmt::Display for LongChainError {
311 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
312 f.write_str("long domain name")
313 }
314}
315
316#[cfg(feature = "std")]
317impl std::error::Error for LongChainError {}
318
319#[cfg(test)]
322#[cfg(feature = "std")]
323mod test {
324 use super::*;
325 use crate::base::name::{Dname, RelativeDname, ToLabelIter};
326 use octseq::builder::infallible;
327
328 #[test]
331 #[cfg(feature = "std")]
332 fn impls() {
333 fn assert_to_dname<T: ToDname>(_: &T) {}
334 fn assert_to_relative_dname<T: ToRelativeDname>(_: &T) {}
335
336 let rel = RelativeDname::empty_ref()
337 .chain(RelativeDname::empty_ref())
338 .unwrap();
339 assert_to_relative_dname(&rel);
340 assert_to_dname(
341 &RelativeDname::empty_ref().chain(Dname::root_ref()).unwrap(),
342 );
343 assert_to_dname(
344 &RelativeDname::empty_ref()
345 .chain(RelativeDname::empty_ref())
346 .unwrap()
347 .chain(Dname::root_ref())
348 .unwrap(),
349 );
350 assert_to_dname(&rel.clone().chain(Dname::root_ref()).unwrap());
351 assert_to_relative_dname(
352 &rel.chain(RelativeDname::empty_ref()).unwrap(),
353 );
354 assert_to_dname(
355 &UncertainDname::root_vec().chain(Dname::root_vec()).unwrap(),
356 );
357 assert_to_dname(
358 &UncertainDname::empty_vec()
359 .chain(Dname::root_vec())
360 .unwrap(),
361 );
362 }
363
364 #[test]
366 fn name_limit() {
367 use crate::base::name::DnameBuilder;
368
369 let mut builder = DnameBuilder::new_vec();
370 for _ in 0..25 {
371 builder.append_label(b"123456789").unwrap();
373 }
374 let left = builder.finish();
375 assert_eq!(left.len(), 250);
376
377 let mut builder = DnameBuilder::new_vec();
378 builder.append_slice(b"123").unwrap();
379 let five_abs = builder.clone().into_dname().unwrap();
380 assert_eq!(five_abs.len(), 5);
381 builder.push(b'4').unwrap();
382 let five_rel = builder.clone().finish();
383 assert_eq!(five_rel.len(), 5);
384 let six_abs = builder.clone().into_dname().unwrap();
385 assert_eq!(six_abs.len(), 6);
386 builder.push(b'5').unwrap();
387 let six_rel = builder.finish();
388 assert_eq!(six_rel.len(), 6);
389
390 assert_eq!(
391 left.clone().chain(five_abs.clone()).unwrap().compose_len(),
392 255
393 );
394 assert_eq!(
395 left.clone().chain(five_rel.clone()).unwrap().compose_len(),
396 255
397 );
398 assert!(left.clone().chain(six_abs.clone()).is_err());
399 assert!(left.clone().chain(six_rel).is_err());
400 assert!(left
401 .clone()
402 .chain(five_rel.clone())
403 .unwrap()
404 .chain(five_abs.clone())
405 .is_err());
406 assert!(left
407 .clone()
408 .chain(five_rel.clone())
409 .unwrap()
410 .chain(five_rel)
411 .is_err());
412
413 let left = UncertainDname::from(left);
414 assert_eq!(left.clone().chain(five_abs).unwrap().compose_len(), 255);
415 assert!(left.clone().chain(six_abs.clone()).is_err());
416
417 let left = UncertainDname::from(left.into_absolute().unwrap());
418 println!("{:?}", left);
419 assert_eq!(left.chain(six_abs).unwrap().compose_len(), 251);
420 }
421
422 #[test]
424 fn to_label_iter_impl() {
425 fn check_impl<N: ToLabelIter>(name: N, labels: &[&[u8]]) {
426 let labels = labels.iter().map(|s| Label::from_slice(s).unwrap());
427 assert!(name.iter_labels().eq(labels));
428 assert_eq!(
429 name.iter_labels().map(|l| l.compose_len()).sum::<u16>(),
430 name.compose_len()
431 );
432 }
433
434 let w = RelativeDname::from_octets(b"\x03www".as_ref()).unwrap();
435 let ec = RelativeDname::from_octets(b"\x07example\x03com".as_ref())
436 .unwrap();
437 let ecr =
438 Dname::from_octets(b"\x07example\x03com\x00".as_ref()).unwrap();
439 let fbr = Dname::from_octets(b"\x03foo\x03bar\x00".as_ref()).unwrap();
440
441 check_impl(
442 w.clone().chain(ec.clone()).unwrap(),
443 &[b"www", b"example", b"com"],
444 );
445 check_impl(
446 w.clone().chain(ecr.clone()).unwrap(),
447 &[b"www", b"example", b"com", b""],
448 );
449 check_impl(
450 w.clone()
451 .chain(ec.clone())
452 .unwrap()
453 .chain(Dname::root_ref())
454 .unwrap(),
455 &[b"www", b"example", b"com", b""],
456 );
457 check_impl(
458 RelativeDname::empty_slice()
459 .chain(Dname::root_slice())
460 .unwrap(),
461 &[b""],
462 );
463
464 check_impl(
465 UncertainDname::from(w.clone()).chain(ecr.clone()).unwrap(),
466 &[b"www", b"example", b"com", b""],
467 );
468 check_impl(
469 UncertainDname::from(ecr.clone())
470 .chain(fbr.clone())
471 .unwrap(),
472 &[b"example", b"com", b""],
473 );
474 }
475
476 #[test]
478 fn compose() {
479 use std::vec::Vec;
480
481 let w = RelativeDname::from_octets(b"\x03www".as_ref()).unwrap();
482 let ec = RelativeDname::from_octets(b"\x07example\x03com".as_ref())
483 .unwrap();
484 let ecr =
485 Dname::from_octets(b"\x07example\x03com\x00".as_ref()).unwrap();
486 let fbr = Dname::from_octets(b"\x03foo\x03bar\x00".as_ref()).unwrap();
487
488 let mut buf = Vec::new();
489 infallible(w.clone().chain(ec.clone()).unwrap().compose(&mut buf));
490 assert_eq!(buf, b"\x03www\x07example\x03com".as_ref());
491
492 let mut buf = Vec::new();
493 infallible(w.clone().chain(ecr.clone()).unwrap().compose(&mut buf));
494 assert_eq!(buf, b"\x03www\x07example\x03com\x00");
495
496 let mut buf = Vec::new();
497 infallible(
498 w.clone()
499 .chain(ec.clone())
500 .unwrap()
501 .chain(Dname::root_ref())
502 .unwrap()
503 .compose(&mut buf),
504 );
505 assert_eq!(buf, b"\x03www\x07example\x03com\x00");
506
507 let mut buf = Vec::new();
508 infallible(
509 UncertainDname::from(w.clone())
510 .chain(ecr.clone())
511 .unwrap()
512 .compose(&mut buf),
513 );
514 assert_eq!(buf, b"\x03www\x07example\x03com\x00");
515
516 let mut buf = Vec::new();
517 infallible(
518 UncertainDname::from(ecr.clone())
519 .chain(fbr.clone())
520 .unwrap()
521 .compose(&mut buf),
522 );
523 assert_eq!(buf, b"\x07example\x03com\x00");
524 }
525}