1use super::super::scan::{BadSymbol, Symbol, SymbolCharsError, Symbols};
7use super::absolute::Name;
8use super::relative::{RelativeName, RelativeNameError};
9use super::traits::{ToName, ToRelativeName};
10use super::Label;
11#[cfg(feature = "bytes")]
12use bytes::BytesMut;
13use core::fmt;
14use octseq::builder::{EmptyBuilder, FreezeBuilder, OctetsBuilder, ShortBuf};
15#[cfg(feature = "std")]
16use std::vec::Vec;
17
18#[derive(Clone)]
37pub struct NameBuilder<Builder> {
38 builder: Builder,
40
41 head: Option<usize>,
45}
46
47impl<Builder> NameBuilder<Builder> {
48 pub(super) unsafe fn from_builder_unchecked(builder: Builder) -> Self {
54 NameBuilder {
55 builder,
56 head: None,
57 }
58 }
59
60 #[must_use]
62 pub fn new() -> Self
63 where
64 Builder: EmptyBuilder,
65 {
66 unsafe { NameBuilder::from_builder_unchecked(Builder::empty()) }
67 }
68
69 #[must_use]
71 pub fn with_capacity(capacity: usize) -> Self
72 where
73 Builder: EmptyBuilder,
74 {
75 unsafe {
76 NameBuilder::from_builder_unchecked(Builder::with_capacity(
77 capacity,
78 ))
79 }
80 }
81
82 pub fn from_builder(builder: Builder) -> Result<Self, RelativeNameError>
87 where
88 Builder: OctetsBuilder + AsRef<[u8]>,
89 {
90 RelativeName::check_slice(builder.as_ref())?;
91 Ok(unsafe { NameBuilder::from_builder_unchecked(builder) })
92 }
93}
94
95#[cfg(feature = "std")]
96impl NameBuilder<Vec<u8>> {
97 #[must_use]
99 pub fn new_vec() -> Self {
100 Self::new()
101 }
102
103 #[must_use]
108 pub fn vec_with_capacity(capacity: usize) -> Self {
109 Self::with_capacity(capacity)
110 }
111}
112
113#[cfg(feature = "bytes")]
114impl NameBuilder<BytesMut> {
115 pub fn new_bytes() -> Self {
117 Self::new()
118 }
119
120 pub fn bytes_with_capacity(capacity: usize) -> Self {
125 Self::with_capacity(capacity)
126 }
127}
128
129impl<Builder: AsRef<[u8]>> NameBuilder<Builder> {
130 pub fn as_slice(&self) -> &[u8] {
132 self.builder.as_ref()
133 }
134
135 pub fn len(&self) -> usize {
137 self.builder.as_ref().len()
138 }
139
140 pub fn is_empty(&self) -> bool {
142 self.builder.as_ref().is_empty()
143 }
144}
145
146impl<Builder> NameBuilder<Builder>
147where
148 Builder: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>,
149{
150 pub fn in_label(&self) -> bool {
157 self.head.is_some()
158 }
159
160 fn _append_slice(&mut self, slice: &[u8]) -> Result<(), PushError> {
165 self.builder
166 .append_slice(slice)
167 .map_err(|_| PushError::ShortBuf)
168 }
169
170 pub fn push(&mut self, ch: u8) -> Result<(), PushError> {
175 let len = self.len();
176 if len >= 254 {
177 return Err(PushError::LongName);
178 }
179 if let Some(head) = self.head {
180 if len - head > Label::MAX_LEN {
181 return Err(PushError::LongLabel);
182 }
183 self._append_slice(&[ch])?;
184 } else {
185 self.head = Some(len);
186 self._append_slice(&[0, ch])?;
187 }
188 Ok(())
189 }
190
191 pub fn push_symbol(&mut self, sym: Symbol) -> Result<(), FromStrError> {
196 if matches!(sym, Symbol::Char('.')) {
197 if !self.in_label() {
198 return Err(PresentationErrorEnum::EmptyLabel.into());
199 }
200 self.end_label();
201 Ok(())
202 } else if matches!(sym, Symbol::SimpleEscape(b'['))
203 && !self.in_label()
204 {
205 Err(LabelFromStrErrorEnum::BinaryLabel.into())
206 } else {
207 self.push(sym.into_octet()?).map_err(Into::into)
208 }
209 }
210
211 pub fn append_slice(&mut self, slice: &[u8]) -> Result<(), PushError> {
218 if slice.is_empty() {
219 return Ok(());
220 }
221 if let Some(head) = self.head {
222 if slice.len() > Label::MAX_LEN - (self.len() - head) {
223 return Err(PushError::LongLabel);
224 }
225 } else {
226 if slice.len() > Label::MAX_LEN {
227 return Err(PushError::LongLabel);
228 }
229 if self.len() + slice.len() > 254 {
230 return Err(PushError::LongName);
231 }
232 self.head = Some(self.len());
233 self._append_slice(&[0])?;
234 }
235 self._append_slice(slice)?;
236 Ok(())
237 }
238
239 pub fn end_label(&mut self) {
243 if let Some(head) = self.head {
244 let len = self.len() - head - 1;
245 self.builder.as_mut()[head] = len as u8;
246 self.head = None;
247 }
248 }
249
250 pub fn append_label(&mut self, label: &[u8]) -> Result<(), PushError> {
259 let head = self.head;
260 self.end_label();
261 if let Err(err) = self.append_slice(label) {
262 self.head = head;
263 return Err(err);
264 }
265 self.end_label();
266 Ok(())
267 }
268
269 pub fn append_dec_u8_label(
277 &mut self,
278 value: u8,
279 ) -> Result<(), PushError> {
280 self.end_label();
281 let hecto = value / 100;
282 if hecto > 0 {
283 self.push(hecto + b'0')?;
284 }
285 let deka = (value / 10) % 10;
286 if hecto > 0 || deka > 0 {
287 self.push(deka + b'0')?;
288 }
289 self.push(value % 10 + b'0')?;
290 self.end_label();
291 Ok(())
292 }
293
294 pub fn append_hex_digit_label(
302 &mut self,
303 nibble: u8,
304 ) -> Result<(), PushError> {
305 fn hex_digit(nibble: u8) -> u8 {
306 match nibble & 0x0F {
307 0 => b'0',
308 1 => b'1',
309 2 => b'2',
310 3 => b'3',
311 4 => b'4',
312 5 => b'5',
313 6 => b'6',
314 7 => b'7',
315 8 => b'8',
316 9 => b'9',
317 10 => b'A',
318 11 => b'B',
319 12 => b'C',
320 13 => b'D',
321 14 => b'E',
322 15 => b'F',
323 _ => unreachable!(),
324 }
325 }
326
327 self.end_label();
328 self.push(hex_digit(nibble))?;
329 self.end_label();
330 Ok(())
331 }
332
333 pub fn append_name<N: ToRelativeName>(
343 &mut self,
344 name: &N,
345 ) -> Result<(), PushNameError> {
346 let head = self.head.take();
347 self.end_label();
348 if self.len() + usize::from(name.compose_len()) > 254 {
349 self.head = head;
350 return Err(PushNameError::LongName);
351 }
352 for label in name.iter_labels() {
353 label
354 .compose(&mut self.builder)
355 .map_err(|_| PushNameError::ShortBuf)?;
356 }
357 Ok(())
358 }
359
360 pub fn append_symbols<Sym: IntoIterator<Item = Symbol>>(
374 &mut self,
375 symbols: Sym,
376 ) -> Result<(), FromStrError> {
377 symbols
378 .into_iter()
379 .try_for_each(|symbol| self.push_symbol(symbol))
380 }
381
382 pub fn append_chars<C: IntoIterator<Item = char>>(
398 &mut self,
399 chars: C,
400 ) -> Result<(), FromStrError> {
401 Symbols::with(chars.into_iter(), |symbols| {
402 self.append_symbols(symbols)
403 })
404 }
405
406 pub fn finish(mut self) -> RelativeName<Builder::Octets>
419 where
420 Builder: FreezeBuilder,
421 {
422 self.end_label();
423 unsafe { RelativeName::from_octets_unchecked(self.builder.freeze()) }
424 }
425
426 pub fn into_name(mut self) -> Result<Name<Builder::Octets>, PushError>
432 where
433 Builder: FreezeBuilder,
434 {
435 self.end_label();
436 self._append_slice(&[0])?;
437 Ok(unsafe { Name::from_octets_unchecked(self.builder.freeze()) })
438 }
439
440 pub fn append_origin<N: ToName>(
448 mut self,
449 origin: &N,
450 ) -> Result<Name<Builder::Octets>, PushNameError>
451 where
452 Builder: FreezeBuilder,
453 {
454 self.end_label();
455 if self.len() + usize::from(origin.compose_len()) > Name::MAX_LEN {
456 return Err(PushNameError::LongName);
457 }
458 for label in origin.iter_labels() {
459 label
460 .compose(&mut self.builder)
461 .map_err(|_| PushNameError::ShortBuf)?;
462 }
463 Ok(unsafe { Name::from_octets_unchecked(self.builder.freeze()) })
464 }
465}
466
467impl<Builder: EmptyBuilder> Default for NameBuilder<Builder> {
470 fn default() -> Self {
471 Self::new()
472 }
473}
474
475impl<Builder: AsRef<[u8]>> AsRef<[u8]> for NameBuilder<Builder> {
478 fn as_ref(&self) -> &[u8] {
479 self.builder.as_ref()
480 }
481}
482
483pub(super) fn parse_escape<C>(
489 chars: &mut C,
490 in_label: bool,
491) -> Result<u8, LabelFromStrError>
492where
493 C: Iterator<Item = char>,
494{
495 let ch = chars.next().ok_or(SymbolCharsError::short_input())?;
496 if ch.is_ascii_digit() {
497 let v = ch.to_digit(10).unwrap() * 100
498 + chars
499 .next()
500 .ok_or(SymbolCharsError::short_input())
501 .and_then(|c| {
502 c.to_digit(10).ok_or(SymbolCharsError::bad_escape())
503 })?
504 * 10
505 + chars
506 .next()
507 .ok_or(SymbolCharsError::short_input())
508 .and_then(|c| {
509 c.to_digit(10).ok_or(SymbolCharsError::bad_escape())
510 })?;
511 if v > 255 {
512 return Err(SymbolCharsError::bad_escape().into());
513 }
514 Ok(v as u8)
515 } else if ch == '[' {
516 if in_label {
519 Ok(b'[')
520 } else {
521 Err(LabelFromStrErrorEnum::BinaryLabel.into())
522 }
523 } else {
524 Ok(ch as u8)
525 }
526}
527
528#[derive(Clone, Copy, Debug, Eq, PartialEq)]
534pub enum PushError {
535 LongLabel,
537
538 LongName,
540
541 ShortBuf,
543}
544
545impl From<ShortBuf> for PushError {
548 fn from(_: ShortBuf) -> PushError {
549 PushError::ShortBuf
550 }
551}
552
553impl fmt::Display for PushError {
556 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
557 match *self {
558 PushError::LongLabel => f.write_str("long label"),
559 PushError::LongName => f.write_str("long domain name"),
560 PushError::ShortBuf => ShortBuf.fmt(f),
561 }
562 }
563}
564
565#[cfg(feature = "std")]
566impl std::error::Error for PushError {}
567
568#[derive(Clone, Copy, Debug, Eq, PartialEq)]
572pub enum PushNameError {
573 LongName,
575
576 ShortBuf,
578}
579
580impl From<ShortBuf> for PushNameError {
583 fn from(_: ShortBuf) -> Self {
584 PushNameError::ShortBuf
585 }
586}
587
588impl fmt::Display for PushNameError {
591 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
592 match *self {
593 PushNameError::LongName => f.write_str("long domain name"),
594 PushNameError::ShortBuf => ShortBuf.fmt(f),
595 }
596 }
597}
598
599#[cfg(feature = "std")]
600impl std::error::Error for PushNameError {}
601
602#[derive(Clone, Copy, Debug, Eq, PartialEq)]
606pub struct LabelFromStrError(LabelFromStrErrorEnum);
607
608#[derive(Clone, Copy, Debug, Eq, PartialEq)]
609pub(super) enum LabelFromStrErrorEnum {
610 SymbolChars(SymbolCharsError),
611
612 BadSymbol(BadSymbol),
613
614 BinaryLabel,
616
617 LongLabel,
619}
620
621impl From<LabelFromStrErrorEnum> for LabelFromStrError {
624 fn from(inner: LabelFromStrErrorEnum) -> Self {
625 Self(inner)
626 }
627}
628
629impl From<SymbolCharsError> for LabelFromStrError {
630 fn from(err: SymbolCharsError) -> Self {
631 Self(LabelFromStrErrorEnum::SymbolChars(err))
632 }
633}
634
635impl From<BadSymbol> for LabelFromStrError {
636 fn from(err: BadSymbol) -> Self {
637 Self(LabelFromStrErrorEnum::BadSymbol(err))
638 }
639}
640
641impl fmt::Display for LabelFromStrError {
644 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
645 match self.0 {
646 LabelFromStrErrorEnum::SymbolChars(err) => err.fmt(f),
647 LabelFromStrErrorEnum::BadSymbol(err) => err.fmt(f),
648 LabelFromStrErrorEnum::BinaryLabel => {
649 f.write_str("a binary label was encountered")
650 }
651 LabelFromStrErrorEnum::LongLabel => {
652 f.write_str("label length limit exceeded")
653 }
654 }
655 }
656}
657
658#[cfg(feature = "std")]
659impl std::error::Error for LabelFromStrError {}
660
661#[derive(Clone, Copy, Debug, Eq, PartialEq)]
664pub enum FromStrError {
665 Presentation(PresentationError),
667
668 ShortBuf,
670}
671
672impl FromStrError {
673 pub(super) fn empty_label() -> Self {
674 Self::Presentation(PresentationErrorEnum::EmptyLabel.into())
675 }
676}
677
678impl From<PushError> for FromStrError {
681 fn from(err: PushError) -> FromStrError {
682 match err {
683 PushError::LongLabel => LabelFromStrErrorEnum::LongLabel.into(),
684 PushError::LongName => PresentationErrorEnum::LongName.into(),
685 PushError::ShortBuf => FromStrError::ShortBuf,
686 }
687 }
688}
689
690impl From<PushNameError> for FromStrError {
691 fn from(err: PushNameError) -> FromStrError {
692 match err {
693 PushNameError::LongName => PresentationErrorEnum::LongName.into(),
694 PushNameError::ShortBuf => FromStrError::ShortBuf,
695 }
696 }
697}
698
699impl<T: Into<PresentationError>> From<T> for FromStrError {
700 fn from(err: T) -> Self {
701 Self::Presentation(err.into())
702 }
703}
704
705impl fmt::Display for FromStrError {
708 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
709 match *self {
710 FromStrError::Presentation(err) => err.fmt(f),
711 FromStrError::ShortBuf => ShortBuf.fmt(f),
712 }
713 }
714}
715
716#[cfg(feature = "std")]
717impl std::error::Error for FromStrError {}
718
719#[derive(Clone, Copy, Debug, Eq, PartialEq)]
723pub struct PresentationError(PresentationErrorEnum);
724
725#[derive(Clone, Copy, Debug, Eq, PartialEq)]
726enum PresentationErrorEnum {
727 BadLabel(LabelFromStrError),
728
729 EmptyLabel,
731
732 LongName,
734}
735
736impl From<PresentationErrorEnum> for PresentationError {
739 fn from(err: PresentationErrorEnum) -> Self {
740 Self(err)
741 }
742}
743
744impl<T: Into<LabelFromStrError>> From<T> for PresentationError {
745 fn from(err: T) -> Self {
746 Self(PresentationErrorEnum::BadLabel(err.into()))
747 }
748}
749
750impl fmt::Display for PresentationError {
753 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
754 match self.0 {
755 PresentationErrorEnum::BadLabel(ref err) => err.fmt(f),
756 PresentationErrorEnum::EmptyLabel => f.write_str("empty label"),
757 PresentationErrorEnum::LongName => {
758 f.write_str("long domain name")
759 }
760 }
761 }
762}
763
764#[cfg(feature = "std")]
765impl std::error::Error for PresentationError {}
766
767#[cfg(test)]
770#[cfg(feature = "std")]
771mod test {
772 use super::*;
773
774 #[test]
775 fn compose() {
776 let mut builder = NameBuilder::new_vec();
777 builder.push(b'w').unwrap();
778 builder.append_slice(b"ww").unwrap();
779 builder.end_label();
780 builder.append_slice(b"exa").unwrap();
781 builder.push(b'm').unwrap();
782 builder.push(b'p').unwrap();
783 builder.append_slice(b"le").unwrap();
784 builder.end_label();
785 builder.append_slice(b"com").unwrap();
786 assert_eq!(builder.finish().as_slice(), b"\x03www\x07example\x03com");
787 }
788
789 #[test]
790 fn build_by_label() {
791 let mut builder = NameBuilder::new_vec();
792 builder.append_label(b"www").unwrap();
793 builder.append_label(b"example").unwrap();
794 builder.append_label(b"com").unwrap();
795 assert_eq!(builder.finish().as_slice(), b"\x03www\x07example\x03com");
796 }
797
798 #[test]
799 fn build_mixed() {
800 let mut builder = NameBuilder::new_vec();
801 builder.push(b'w').unwrap();
802 builder.append_slice(b"ww").unwrap();
803 builder.append_label(b"example").unwrap();
804 builder.append_slice(b"com").unwrap();
805 assert_eq!(builder.finish().as_slice(), b"\x03www\x07example\x03com");
806 }
807
808 #[test]
809 fn name_limit() {
810 let mut builder = NameBuilder::new_vec();
811 for _ in 0..25 {
812 builder.append_label(b"123456789").unwrap();
814 }
815
816 assert_eq!(builder.append_label(b"12345"), Err(PushError::LongName));
817 assert_eq!(builder.clone().append_label(b"1234"), Ok(()));
818
819 assert_eq!(builder.append_slice(b"12345"), Err(PushError::LongName));
820 assert_eq!(builder.clone().append_slice(b"1234"), Ok(()));
821
822 assert_eq!(builder.append_slice(b"12"), Ok(()));
823 assert_eq!(builder.push(b'3'), Ok(()));
824 assert_eq!(builder.push(b'4'), Err(PushError::LongName))
825 }
826
827 #[test]
828 fn label_limit() {
829 let mut builder = NameBuilder::new_vec();
830 builder.append_label(&[0u8; 63][..]).unwrap();
831 assert_eq!(
832 builder.append_label(&[0u8; 64][..]),
833 Err(PushError::LongLabel)
834 );
835 assert_eq!(
836 builder.append_label(&[0u8; 164][..]),
837 Err(PushError::LongLabel)
838 );
839
840 builder.append_slice(&[0u8; 60][..]).unwrap();
841 builder.clone().append_label(b"123").unwrap();
842 assert_eq!(builder.append_slice(b"1234"), Err(PushError::LongLabel));
843 builder.append_slice(b"12").unwrap();
844 builder.push(b'3').unwrap();
845 assert_eq!(builder.push(b'4'), Err(PushError::LongLabel));
846 }
847
848 #[test]
849 fn finish() {
850 let mut builder = NameBuilder::new_vec();
851 builder.append_label(b"www").unwrap();
852 builder.append_label(b"example").unwrap();
853 builder.append_slice(b"com").unwrap();
854 assert_eq!(builder.finish().as_slice(), b"\x03www\x07example\x03com");
855 }
856
857 #[test]
858 fn into_name() {
859 let mut builder = NameBuilder::new_vec();
860 builder.append_label(b"www").unwrap();
861 builder.append_label(b"example").unwrap();
862 builder.append_slice(b"com").unwrap();
863 assert_eq!(
864 builder.into_name().unwrap().as_slice(),
865 b"\x03www\x07example\x03com\x00"
866 );
867 }
868}