1use super::super::scan::Scanner;
7use super::label::Label;
8use super::relative::NameIter;
9use super::traits::{FlattenInto, ToLabelIter, ToName, ToRelativeName};
10use super::uncertain::UncertainName;
11use super::Name;
12use core::{fmt, iter};
13use octseq::builder::{
14 BuilderAppendError, EmptyBuilder, FreezeBuilder, FromBuilder,
15};
16
17#[derive(Clone, Debug)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34pub struct Chain<L, R> {
35 left: L,
37
38 right: R,
40}
41
42impl<L: ToLabelIter, R: ToLabelIter> Chain<L, R> {
43 pub(super) fn new(left: L, right: R) -> Result<Self, LongChainError> {
45 if usize::from(left.compose_len() + right.compose_len())
46 > Name::MAX_LEN
47 {
48 Err(LongChainError(()))
50 } else {
51 Ok(Chain { left, right })
52 }
53 }
54}
55
56impl<Octets: AsRef<[u8]>, R: ToLabelIter> Chain<UncertainName<Octets>, R> {
57 pub(super) fn new_uncertain(
62 left: UncertainName<Octets>,
63 right: R,
64 ) -> Result<Self, LongChainError> {
65 if let UncertainName::Relative(ref name) = left {
66 if usize::from(name.compose_len() + right.compose_len())
67 > Name::MAX_LEN
68 {
69 return Err(LongChainError(()));
70 }
71 }
72 Ok(Chain { left, right })
73 }
74}
75
76impl<L, R> Chain<L, R> {
77 pub fn scan<S: Scanner<Name = Self>>(
78 scanner: &mut S,
79 ) -> Result<Self, S::Error> {
80 scanner.scan_name()
81 }
82}
83
84impl<L: ToRelativeName, R: ToLabelIter> Chain<L, R> {
85 pub fn chain<N: ToLabelIter>(
97 self,
98 other: N,
99 ) -> Result<Chain<Self, N>, LongChainError> {
100 Chain::new(self, other)
101 }
102}
103
104impl<L, R> Chain<L, R>
105where
106 Self: ToLabelIter,
107{
108 pub fn fmt_with_dot(&self) -> impl fmt::Display + '_ {
115 DisplayWithDot(self)
116 }
117}
118
119impl<L, R> Chain<L, R> {
120 pub fn unwrap(self) -> (L, R) {
122 (self.left, self.right)
123 }
124}
125
126impl<L: ToRelativeName, R: ToLabelIter> ToLabelIter for Chain<L, R> {
129 type LabelIter<'a>
130 = ChainIter<'a, L, R>
131 where
132 L: 'a,
133 R: 'a;
134
135 fn iter_labels(&self) -> Self::LabelIter<'_> {
136 ChainIter(self.left.iter_labels().chain(self.right.iter_labels()))
137 }
138
139 fn compose_len(&self) -> u16 {
140 self.left
141 .compose_len()
142 .checked_add(self.right.compose_len())
143 .expect("long domain name")
144 }
145}
146
147impl<Octs, R> ToLabelIter for Chain<UncertainName<Octs>, R>
148where
149 Octs: AsRef<[u8]>,
150 R: ToName,
151{
152 type LabelIter<'a>
153 = UncertainChainIter<'a, Octs, R>
154 where
155 Octs: 'a,
156 R: 'a;
157
158 fn iter_labels(&self) -> Self::LabelIter<'_> {
159 match self.left {
160 UncertainName::Absolute(ref name) => {
161 UncertainChainIter::Absolute(name.iter_labels())
162 }
163 UncertainName::Relative(ref name) => {
164 UncertainChainIter::Relative(ChainIter(
165 name.iter_labels().chain(self.right.iter_labels()),
166 ))
167 }
168 }
169 }
170
171 fn compose_len(&self) -> u16 {
172 match self.left {
173 UncertainName::Absolute(ref name) => name.compose_len(),
174 UncertainName::Relative(ref name) => name
175 .compose_len()
176 .checked_add(self.right.compose_len())
177 .expect("long domain name"),
178 }
179 }
180}
181
182impl<L: ToRelativeName, R: ToRelativeName> ToRelativeName for Chain<L, R> {}
183
184impl<L: ToRelativeName, R: ToName> ToName for Chain<L, R> {}
185
186impl<Octets, R> ToName for Chain<UncertainName<Octets>, R>
187where
188 Octets: AsRef<[u8]>,
189 R: ToName,
190{
191}
192
193impl<L, R, Target> FlattenInto<Name<Target>> for Chain<L, R>
196where
197 L: ToRelativeName,
198 R: ToName,
199 R: FlattenInto<Name<Target>, AppendError = BuilderAppendError<Target>>,
200 Target: FromBuilder,
201 <Target as FromBuilder>::Builder: EmptyBuilder,
202{
203 type AppendError = BuilderAppendError<Target>;
204
205 fn try_flatten_into(self) -> Result<Name<Target>, Self::AppendError> {
206 if self.left.is_empty() {
207 self.right.try_flatten_into()
208 } else {
209 let mut builder =
210 Target::Builder::with_capacity(self.compose_len().into());
211 self.compose(&mut builder)?;
212 Ok(unsafe { Name::from_octets_unchecked(builder.freeze()) })
213 }
214 }
215}
216
217impl<L, R> fmt::Display for Chain<L, R>
220where
221 Self: ToLabelIter,
222{
223 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
224 let mut empty = true;
225 for label in self.iter_labels() {
226 if label.is_root() {
227 if empty {
228 f.write_str(".")?
229 }
230 } else {
231 if !empty {
232 f.write_str(".")?
233 } else {
234 empty = false;
235 }
236 label.fmt(f)?;
237 }
238 }
239 Ok(())
240 }
241}
242
243#[derive(Debug)]
247pub struct ChainIter<'a, L: ToLabelIter + 'a, R: ToLabelIter + 'a>(
248 iter::Chain<L::LabelIter<'a>, R::LabelIter<'a>>,
249);
250
251impl<L, R> Clone for ChainIter<'_, L, R>
252where
253 L: ToLabelIter,
254 R: ToLabelIter,
255{
256 fn clone(&self) -> Self {
257 ChainIter(self.0.clone())
258 }
259}
260
261impl<'a, L, R> Iterator for ChainIter<'a, L, R>
262where
263 L: ToLabelIter,
264 R: ToLabelIter,
265{
266 type Item = &'a Label;
267
268 fn next(&mut self) -> Option<Self::Item> {
269 self.0.next()
270 }
271}
272
273impl<L, R> DoubleEndedIterator for ChainIter<'_, L, R>
274where
275 L: ToLabelIter,
276 R: ToLabelIter,
277{
278 fn next_back(&mut self) -> Option<Self::Item> {
279 self.0.next_back()
280 }
281}
282
283pub enum UncertainChainIter<'a, Octets: AsRef<[u8]>, R: ToLabelIter> {
287 Absolute(NameIter<'a>),
288 Relative(ChainIter<'a, UncertainName<Octets>, R>),
289}
290
291impl<Octets, R> Clone for UncertainChainIter<'_, Octets, R>
292where
293 Octets: AsRef<[u8]>,
294 R: ToLabelIter,
295{
296 fn clone(&self) -> Self {
297 use UncertainChainIter::*;
298
299 match *self {
300 Absolute(ref inner) => Absolute(inner.clone()),
301 Relative(ref inner) => Relative(inner.clone()),
302 }
303 }
304}
305
306impl<'a, Octets, R> Iterator for UncertainChainIter<'a, Octets, R>
307where
308 Octets: AsRef<[u8]>,
309 R: ToLabelIter,
310{
311 type Item = &'a Label;
312
313 fn next(&mut self) -> Option<Self::Item> {
314 match *self {
315 UncertainChainIter::Absolute(ref mut inner) => inner.next(),
316 UncertainChainIter::Relative(ref mut inner) => inner.next(),
317 }
318 }
319}
320
321impl<Octets, R> DoubleEndedIterator for UncertainChainIter<'_, Octets, R>
322where
323 Octets: AsRef<[u8]>,
324 R: ToLabelIter,
325{
326 fn next_back(&mut self) -> Option<Self::Item> {
327 match *self {
328 UncertainChainIter::Absolute(ref mut inner) => inner.next_back(),
329 UncertainChainIter::Relative(ref mut inner) => inner.next_back(),
330 }
331 }
332}
333
334struct DisplayWithDot<'a, L, R>(&'a Chain<L, R>);
337
338impl<L, R> fmt::Display for DisplayWithDot<'_, L, R>
339where
340 Chain<L, R>: ToLabelIter,
341{
342 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
343 let mut empty = true;
344 for label in self.0.iter_labels() {
345 if label.is_root() {
346 f.write_str(".")?
347 } else {
348 if !empty {
349 f.write_str(".")?
350 } else {
351 empty = false;
352 }
353 label.fmt(f)?;
354 }
355 }
356 Ok(())
357 }
358}
359
360#[derive(Clone, Copy, Debug, Eq, PartialEq)]
366pub struct LongChainError(());
367
368impl fmt::Display for LongChainError {
371 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
372 f.write_str("long domain name")
373 }
374}
375
376#[cfg(feature = "std")]
377impl std::error::Error for LongChainError {}
378
379#[cfg(test)]
382#[cfg(feature = "std")]
383mod test {
384 use super::*;
385 use crate::base::name::RelativeName;
386 use octseq::builder::infallible;
387
388 #[test]
391 #[cfg(feature = "std")]
392 fn impls() {
393 fn assert_to_name<T: ToName>(_: &T) {}
394 fn assert_to_relative_name<T: ToRelativeName>(_: &T) {}
395
396 let rel = RelativeName::empty_ref()
397 .chain(RelativeName::empty_ref())
398 .unwrap();
399 assert_to_relative_name(&rel);
400 assert_to_name(
401 &RelativeName::empty_ref().chain(Name::root_ref()).unwrap(),
402 );
403 assert_to_name(
404 &RelativeName::empty_ref()
405 .chain(RelativeName::empty_ref())
406 .unwrap()
407 .chain(Name::root_ref())
408 .unwrap(),
409 );
410 assert_to_name(&rel.clone().chain(Name::root_ref()).unwrap());
411 assert_to_relative_name(
412 &rel.chain(RelativeName::empty_ref()).unwrap(),
413 );
414 assert_to_name(
415 &UncertainName::root_vec().chain(Name::root_vec()).unwrap(),
416 );
417 assert_to_name(
418 &UncertainName::empty_vec().chain(Name::root_vec()).unwrap(),
419 );
420 }
421
422 #[test]
424 fn name_limit() {
425 use crate::base::name::NameBuilder;
426
427 let mut builder = NameBuilder::new_vec();
428 for _ in 0..25 {
429 builder.append_label(b"123456789").unwrap();
431 }
432 let left = builder.finish();
433 assert_eq!(left.len(), 250);
434
435 let mut builder = NameBuilder::new_vec();
436 builder.append_slice(b"123").unwrap();
437 let five_abs = builder.clone().into_name().unwrap();
438 assert_eq!(five_abs.len(), 5);
439 builder.push(b'4').unwrap();
440 let five_rel = builder.clone().finish();
441 assert_eq!(five_rel.len(), 5);
442 let six_abs = builder.clone().into_name().unwrap();
443 assert_eq!(six_abs.len(), 6);
444 builder.push(b'5').unwrap();
445 let six_rel = builder.finish();
446 assert_eq!(six_rel.len(), 6);
447
448 assert_eq!(
449 left.clone().chain(five_abs.clone()).unwrap().compose_len(),
450 255
451 );
452 assert_eq!(
453 left.clone().chain(five_rel.clone()).unwrap().compose_len(),
454 255
455 );
456 assert!(left.clone().chain(six_abs.clone()).is_err());
457 assert!(left.clone().chain(six_rel).is_err());
458 assert!(left
459 .clone()
460 .chain(five_rel.clone())
461 .unwrap()
462 .chain(five_abs.clone())
463 .is_err());
464 assert!(left
465 .clone()
466 .chain(five_rel.clone())
467 .unwrap()
468 .chain(five_rel)
469 .is_err());
470
471 let left = UncertainName::from(left);
472 assert_eq!(left.clone().chain(five_abs).unwrap().compose_len(), 255);
473 assert!(left.clone().chain(six_abs.clone()).is_err());
474
475 let left = UncertainName::from(left.into_absolute().unwrap());
476 println!("{:?}", left);
477 assert_eq!(left.chain(six_abs).unwrap().compose_len(), 251);
478 }
479
480 #[test]
482 fn to_label_iter_impl() {
483 fn check_impl<N: ToLabelIter>(name: N, labels: &[&[u8]]) {
484 let labels = labels.iter().map(|s| Label::from_slice(s).unwrap());
485 assert!(name.iter_labels().eq(labels));
486 assert_eq!(
487 name.iter_labels().map(|l| l.compose_len()).sum::<u16>(),
488 name.compose_len()
489 );
490 }
491
492 let w = RelativeName::from_octets(b"\x03www".as_ref()).unwrap();
493 let ec = RelativeName::from_octets(b"\x07example\x03com".as_ref())
494 .unwrap();
495 let ecr =
496 Name::from_octets(b"\x07example\x03com\x00".as_ref()).unwrap();
497 let fbr = Name::from_octets(b"\x03foo\x03bar\x00".as_ref()).unwrap();
498
499 check_impl(
500 w.clone().chain(ec.clone()).unwrap(),
501 &[b"www", b"example", b"com"],
502 );
503 check_impl(
504 w.clone().chain(ecr.clone()).unwrap(),
505 &[b"www", b"example", b"com", b""],
506 );
507 check_impl(
508 w.clone()
509 .chain(ec.clone())
510 .unwrap()
511 .chain(Name::root_ref())
512 .unwrap(),
513 &[b"www", b"example", b"com", b""],
514 );
515 check_impl(
516 RelativeName::empty_slice()
517 .chain(Name::root_slice())
518 .unwrap(),
519 &[b""],
520 );
521
522 check_impl(
523 UncertainName::from(w.clone()).chain(ecr.clone()).unwrap(),
524 &[b"www", b"example", b"com", b""],
525 );
526 check_impl(
527 UncertainName::from(ecr.clone()).chain(fbr.clone()).unwrap(),
528 &[b"example", b"com", b""],
529 );
530 }
531
532 #[test]
534 fn compose() {
535 use std::vec::Vec;
536
537 let w = RelativeName::from_octets(b"\x03www".as_ref()).unwrap();
538 let ec = RelativeName::from_octets(b"\x07example\x03com".as_ref())
539 .unwrap();
540 let ecr =
541 Name::from_octets(b"\x07example\x03com\x00".as_ref()).unwrap();
542 let fbr = Name::from_octets(b"\x03foo\x03bar\x00".as_ref()).unwrap();
543
544 let mut buf = Vec::new();
545 infallible(w.clone().chain(ec.clone()).unwrap().compose(&mut buf));
546 assert_eq!(buf, b"\x03www\x07example\x03com".as_ref());
547
548 let mut buf = Vec::new();
549 infallible(w.clone().chain(ecr.clone()).unwrap().compose(&mut buf));
550 assert_eq!(buf, b"\x03www\x07example\x03com\x00");
551
552 let mut buf = Vec::new();
553 infallible(
554 w.clone()
555 .chain(ec.clone())
556 .unwrap()
557 .chain(Name::root_ref())
558 .unwrap()
559 .compose(&mut buf),
560 );
561 assert_eq!(buf, b"\x03www\x07example\x03com\x00");
562
563 let mut buf = Vec::new();
564 infallible(
565 UncertainName::from(w.clone())
566 .chain(ecr.clone())
567 .unwrap()
568 .compose(&mut buf),
569 );
570 assert_eq!(buf, b"\x03www\x07example\x03com\x00");
571
572 let mut buf = Vec::new();
573 infallible(
574 UncertainName::from(ecr.clone())
575 .chain(fbr.clone())
576 .unwrap()
577 .compose(&mut buf),
578 );
579 assert_eq!(buf, b"\x07example\x03com\x00");
580 }
581
582 #[test]
589 fn display() {
590 fn cmp<E: fmt::Debug, L, R>(
591 chain: Result<Chain<L, R>, E>,
592 out: &str,
593 dot_out: &str,
594 ) where
595 Chain<L, R>: ToLabelIter,
596 {
597 use std::string::ToString;
598
599 let chain = chain.unwrap();
600 assert_eq!(chain.to_string(), out);
601 assert_eq!(chain.fmt_with_dot().to_string(), dot_out);
602 }
603
604 let empty = &RelativeName::from_octets(b"".as_slice()).unwrap();
606
607 let uempty = &UncertainName::from(empty.clone());
609
610 let rel =
613 &RelativeName::from_octets(b"\x03www\x07example".as_slice())
614 .unwrap();
615
616 let urel = &UncertainName::from(rel.clone());
618
619 let root = &Name::from_octets(b"\0".as_slice()).unwrap();
621
622 let uroot = &UncertainName::from(root.clone());
624
625 let abs = &Name::from_octets(b"\x03com\0".as_slice()).unwrap();
627
628 let uabs = &UncertainName::from(abs.clone());
630
631 cmp(empty.chain(empty), "", "");
637 cmp(empty.chain(uempty), "", "");
638 cmp(empty.chain(rel), "www.example", "www.example");
639 cmp(empty.chain(urel), "www.example", "www.example");
640 cmp(empty.chain(root), ".", ".");
641 cmp(empty.chain(uroot), ".", ".");
642 cmp(empty.chain(abs), "com", "com.");
643 cmp(empty.chain(uabs), "com", "com.");
644
645 cmp(rel.chain(empty), "www.example", "www.example");
646 cmp(rel.chain(uempty), "www.example", "www.example");
647 cmp(
648 rel.chain(rel),
649 "www.example.www.example",
650 "www.example.www.example",
651 );
652 cmp(
653 rel.chain(urel),
654 "www.example.www.example",
655 "www.example.www.example",
656 );
657 cmp(rel.chain(root), "www.example", "www.example.");
658 cmp(rel.chain(uroot), "www.example", "www.example.");
659 cmp(rel.chain(abs), "www.example.com", "www.example.com.");
660 cmp(rel.chain(uabs), "www.example.com", "www.example.com.");
661
662 cmp(uempty.clone().chain(root), ".", ".");
665 cmp(uempty.clone().chain(abs), "com", "com.");
666 cmp(urel.clone().chain(root), "www.example", "www.example.");
667 cmp(
668 urel.clone().chain(abs),
669 "www.example.com",
670 "www.example.com.",
671 );
672 cmp(uroot.clone().chain(root), ".", ".");
673 cmp(uroot.clone().chain(abs), ".", ".");
674 cmp(uabs.clone().chain(root), "com", "com.");
675 cmp(uabs.clone().chain(abs), "com", "com.");
676 }
677}