1use std::{
2 borrow::Cow,
3 cmp::max,
4 time::{Duration, SystemTime},
5};
6
7use bytes::{Buf, BufMut, Bytes, BytesMut};
8use derive_more::{AsMut, AsRef, Display, From, Into};
9use ndn_tlv::{NonNegativeInteger, Tlv, TlvDecode, TlvEncode, VarNum};
10use url::Url;
11
12use crate::error::{NdnError, Result};
13
14trait FromUriPart: Sized {
15 fn from_uri_part(s: &[u8]) -> Option<Self>;
16}
17
18trait ToUriPart {
19 fn to_uri_part(&self) -> String;
20}
21
22#[derive(Debug, Tlv, PartialEq, Eq, Clone, Hash, From, Into, AsRef, AsMut)]
23#[tlv(8)]
24pub struct GenericNameComponent {
25 pub name: Bytes,
26}
27
28impl GenericNameComponent {
29 pub fn new(name: Bytes) -> Self {
30 Self { name }
31 }
32}
33
34impl FromUriPart for GenericNameComponent {
35 fn from_uri_part(s: &[u8]) -> Option<Self> {
36 let name = if s.starts_with(b"8=") {
37 Bytes::copy_from_slice(&s[2..])
38 } else {
39 Bytes::copy_from_slice(s)
40 };
41 Some(Self { name })
42 }
43}
44
45impl ToUriPart for GenericNameComponent {
46 fn to_uri_part(&self) -> String {
47 let name = if self.name.iter().all(|x| *x == b'.') {
48 Bytes::from_iter(b"...".iter().chain(self.name.iter()).map(|x| *x))
49 } else {
50 self.name.clone()
51 };
52 urlencoding::encode_binary(&name).into_owned()
53 }
54}
55
56#[derive(Debug, Tlv, PartialEq, Eq, Clone, Hash, From, Into, AsRef, AsMut)]
57#[tlv(32)]
58pub struct KeywordNameComponent {
59 pub name: Bytes,
60}
61
62impl KeywordNameComponent {
63 pub fn new(name: Bytes) -> Self {
64 Self { name }
65 }
66}
67
68impl FromUriPart for KeywordNameComponent {
69 fn from_uri_part(s: &[u8]) -> Option<Self> {
70 let name = if s.starts_with(b"32=") {
71 Bytes::copy_from_slice(&s[3..])
72 } else {
73 return None;
74 };
75 Some(Self { name })
76 }
77}
78
79impl ToUriPart for KeywordNameComponent {
80 fn to_uri_part(&self) -> String {
81 format!("32={}", urlencoding::encode_binary(&self.name))
82 }
83}
84
85#[derive(
86 Debug,
87 Tlv,
88 PartialEq,
89 Eq,
90 Clone,
91 Hash,
92 Default,
93 PartialOrd,
94 Ord,
95 From,
96 Into,
97 AsRef,
98 AsMut,
99 Display,
100)]
101#[tlv(50)]
102pub struct SegmentNameComponent {
103 pub segment_number: NonNegativeInteger,
104}
105
106impl SegmentNameComponent {
107 pub fn new(segment_number: NonNegativeInteger) -> Self {
108 Self { segment_number }
109 }
110}
111
112impl From<u64> for SegmentNameComponent {
113 fn from(value: u64) -> Self {
114 Self::new(NonNegativeInteger::new(value))
115 }
116}
117
118impl From<usize> for SegmentNameComponent {
119 fn from(value: usize) -> Self {
120 Self::new(NonNegativeInteger::new(value as u64))
121 }
122}
123
124impl FromUriPart for SegmentNameComponent {
125 fn from_uri_part(s: &[u8]) -> Option<Self> {
126 let name = if s.starts_with(b"50=") {
127 let mut buf = [0; std::mem::size_of::<u64>()];
128 let slice = &s[3..];
129
130 let start_idx = max(0, buf.len() - slice.len());
131 for i in start_idx..buf.len() {
132 buf[i] = slice[i - start_idx];
133 }
134
135 NonNegativeInteger::new(u64::from_be_bytes(buf))
136 } else if s.starts_with(b"seg=") {
137 let number = std::str::from_utf8(&s[4..]).ok()?.parse::<u64>().ok()?;
138 NonNegativeInteger::new(number)
139 } else {
140 return None;
141 };
142 Some(Self {
143 segment_number: name,
144 })
145 }
146}
147
148impl ToUriPart for SegmentNameComponent {
149 fn to_uri_part(&self) -> String {
150 format!("seg={}", self.segment_number)
151 }
152}
153
154#[derive(
155 Debug,
156 Tlv,
157 PartialEq,
158 Eq,
159 Clone,
160 Hash,
161 PartialOrd,
162 Ord,
163 Default,
164 From,
165 Into,
166 AsRef,
167 AsMut,
168 Display,
169)]
170#[tlv(52)]
171pub struct ByteOffsetNameComponent {
172 pub offset: NonNegativeInteger,
173}
174
175impl ByteOffsetNameComponent {
176 pub fn new(offset: NonNegativeInteger) -> Self {
177 Self { offset }
178 }
179}
180
181impl From<u64> for ByteOffsetNameComponent {
182 fn from(value: u64) -> Self {
183 Self::new(NonNegativeInteger::new(value))
184 }
185}
186
187impl From<usize> for ByteOffsetNameComponent {
188 fn from(value: usize) -> Self {
189 Self::new(NonNegativeInteger::new(value as u64))
190 }
191}
192
193impl FromUriPart for ByteOffsetNameComponent {
194 fn from_uri_part(s: &[u8]) -> Option<Self> {
195 let name = if s.starts_with(b"52=") {
196 let mut buf = [0; std::mem::size_of::<u64>()];
197 let slice = &s[3..];
198
199 let start_idx = max(0, buf.len() - slice.len());
200 for i in start_idx..buf.len() {
201 buf[i] = slice[i - start_idx];
202 }
203
204 NonNegativeInteger::new(u64::from_be_bytes(buf))
205 } else if s.starts_with(b"off=") {
206 let number = std::str::from_utf8(&s[4..]).ok()?.parse::<u64>().ok()?;
207 NonNegativeInteger::new(number)
208 } else {
209 return None;
210 };
211 Some(Self { offset: name })
212 }
213}
214
215impl ToUriPart for ByteOffsetNameComponent {
216 fn to_uri_part(&self) -> String {
217 format!("off={}", self.offset)
218 }
219}
220
221#[derive(
222 Debug,
223 Tlv,
224 PartialEq,
225 Eq,
226 Clone,
227 Hash,
228 PartialOrd,
229 Ord,
230 Default,
231 From,
232 Into,
233 AsRef,
234 AsMut,
235 Display,
236)]
237#[tlv(54)]
238pub struct VersionNameComponent {
239 pub version: NonNegativeInteger,
240}
241
242impl VersionNameComponent {
243 pub fn new(version: NonNegativeInteger) -> Self {
244 Self { version }
245 }
246}
247
248impl From<u64> for VersionNameComponent {
249 fn from(value: u64) -> Self {
250 Self::new(NonNegativeInteger::new(value))
251 }
252}
253
254impl From<usize> for VersionNameComponent {
255 fn from(value: usize) -> Self {
256 Self::new(NonNegativeInteger::new(value as u64))
257 }
258}
259
260impl FromUriPart for VersionNameComponent {
261 fn from_uri_part(s: &[u8]) -> Option<Self> {
262 let name = if s.starts_with(b"54=") {
263 let mut buf = [0; std::mem::size_of::<u64>()];
264 let slice = &s[3..];
265
266 let start_idx = max(0, buf.len() - slice.len());
267 for i in start_idx..buf.len() {
268 buf[i] = slice[i - start_idx];
269 }
270
271 NonNegativeInteger::new(u64::from_be_bytes(buf))
272 } else if s.starts_with(b"v=") {
273 let number = std::str::from_utf8(&s[2..]).ok()?.parse::<u64>().ok()?;
274 NonNegativeInteger::new(number)
275 } else {
276 return None;
277 };
278 Some(Self { version: name })
279 }
280}
281
282impl ToUriPart for VersionNameComponent {
283 fn to_uri_part(&self) -> String {
284 format!("v={}", self.version)
285 }
286}
287
288#[derive(
289 Debug, Tlv, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, From, Into, AsRef, AsMut, Display,
290)]
291#[tlv(56)]
292pub struct TimestampNameComponent {
293 pub time: NonNegativeInteger,
294}
295
296impl TimestampNameComponent {
297 pub fn new(time: NonNegativeInteger) -> Self {
298 Self { time }
299 }
300
301 pub fn now() -> Self {
302 Self::new(NonNegativeInteger::new(
303 SystemTime::now()
304 .duration_since(SystemTime::UNIX_EPOCH)
305 .unwrap_or(Duration::ZERO)
306 .as_millis() as u64,
307 ))
308 }
309}
310
311impl Default for TimestampNameComponent {
312 fn default() -> Self {
313 Self::now()
314 }
315}
316
317impl From<u64> for TimestampNameComponent {
318 fn from(value: u64) -> Self {
319 Self::new(NonNegativeInteger::new(value))
320 }
321}
322
323impl From<usize> for TimestampNameComponent {
324 fn from(value: usize) -> Self {
325 Self::new(NonNegativeInteger::new(value as u64))
326 }
327}
328
329impl FromUriPart for TimestampNameComponent {
330 fn from_uri_part(s: &[u8]) -> Option<Self> {
331 let name = if s.starts_with(b"56=") {
332 let mut buf = [0; std::mem::size_of::<u64>()];
333 let slice = &s[3..];
334
335 let start_idx = max(0, buf.len() - slice.len());
336 for i in start_idx..buf.len() {
337 buf[i] = slice[i - start_idx];
338 }
339
340 NonNegativeInteger::new(u64::from_be_bytes(buf))
341 } else if s.starts_with(b"t=") {
342 let number = std::str::from_utf8(&s[2..]).ok()?.parse::<u64>().ok()?;
343 NonNegativeInteger::new(number)
344 } else {
345 return None;
346 };
347 Some(Self { time: name })
348 }
349}
350
351impl ToUriPart for TimestampNameComponent {
352 fn to_uri_part(&self) -> String {
353 format!("t={}", self.time)
354 }
355}
356
357#[derive(
358 Debug,
359 Tlv,
360 PartialEq,
361 Eq,
362 Clone,
363 Hash,
364 PartialOrd,
365 Ord,
366 Default,
367 From,
368 Into,
369 AsRef,
370 AsMut,
371 Display,
372)]
373#[tlv(58)]
374pub struct SequenceNumNameComponent {
375 pub sequence_number: NonNegativeInteger,
376}
377
378impl SequenceNumNameComponent {
379 pub fn new(sequence_number: NonNegativeInteger) -> Self {
380 Self { sequence_number }
381 }
382}
383
384impl From<u64> for SequenceNumNameComponent {
385 fn from(value: u64) -> Self {
386 Self::new(NonNegativeInteger::new(value))
387 }
388}
389
390impl From<usize> for SequenceNumNameComponent {
391 fn from(value: usize) -> Self {
392 Self::new(NonNegativeInteger::new(value as u64))
393 }
394}
395
396impl FromUriPart for SequenceNumNameComponent {
397 fn from_uri_part(s: &[u8]) -> Option<Self> {
398 let name = if s.starts_with(b"58=") {
399 let mut buf = [0; std::mem::size_of::<u64>()];
400 let slice = &s[3..];
401
402 let start_idx = max(0, buf.len() - slice.len());
403 for i in start_idx..buf.len() {
404 buf[i] = slice[i - start_idx];
405 }
406
407 NonNegativeInteger::new(u64::from_be_bytes(buf))
408 } else if s.starts_with(b"seq=") {
409 let number = std::str::from_utf8(&s[4..]).ok()?.parse::<u64>().ok()?;
410 NonNegativeInteger::new(number)
411 } else {
412 return None;
413 };
414 Some(Self {
415 sequence_number: name,
416 })
417 }
418}
419
420impl ToUriPart for SequenceNumNameComponent {
421 fn to_uri_part(&self) -> String {
422 format!("seq={}", self.sequence_number)
423 }
424}
425
426#[derive(Debug, Tlv, PartialEq, Eq, Clone, Hash, From, Into, AsRef, AsMut)]
427#[tlv(1)]
428pub struct ImplicitSha256DigestComponent {
429 pub(crate) name: [u8; 32],
430}
431
432impl FromUriPart for ImplicitSha256DigestComponent {
433 fn from_uri_part(s: &[u8]) -> Option<Self> {
434 let mut name = [0; 32];
435 if s.starts_with(b"sha256digest=") {
436 hex::decode_to_slice(&s["sha256digest=".len()..], &mut name).ok()?;
437 } else {
438 assert!(s.starts_with(b"1="));
439 name.clone_from_slice(&s[2..]);
440 }
441 Some(Self { name })
442 }
443}
444
445impl ToUriPart for ImplicitSha256DigestComponent {
446 fn to_uri_part(&self) -> String {
447 format!("sha256digest={}", hex::encode(&self.name))
448 }
449}
450
451impl std::fmt::Display for ImplicitSha256DigestComponent {
452 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
453 if f.alternate() {
454 write!(f, "{}", hex::encode_upper(self.name))
455 } else {
456 write!(f, "{}", hex::encode(self.name))
457 }
458 }
459}
460
461#[derive(Debug, Tlv, PartialEq, Eq, Clone, Hash, From, Into, AsRef, AsMut)]
462#[tlv(2)]
463pub struct ParametersSha256DigestComponent {
464 pub(crate) name: [u8; 32],
465}
466
467impl FromUriPart for ParametersSha256DigestComponent {
468 fn from_uri_part(s: &[u8]) -> Option<Self> {
469 let mut name = [0; 32];
470 if s.starts_with(b"params-sha256=") {
471 hex::decode_to_slice(&s["params-sha256=".len()..], &mut name).ok()?;
472 } else {
473 assert!(s.starts_with(b"2="));
474 name.clone_from_slice(&s[2..]);
475 }
476 Some(Self { name })
477 }
478}
479
480impl ToUriPart for ParametersSha256DigestComponent {
481 fn to_uri_part(&self) -> String {
482 format!("params-sha256={}", hex::encode(&self.name))
483 }
484}
485
486impl std::fmt::Display for ParametersSha256DigestComponent {
487 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
488 if f.alternate() {
489 write!(f, "{}", hex::encode_upper(self.name))
490 } else {
491 write!(f, "{}", hex::encode(self.name))
492 }
493 }
494}
495
496#[derive(Debug, PartialEq, Eq, Clone, Hash)]
497pub struct OtherNameComponent {
498 pub typ: VarNum,
499 pub length: VarNum,
500 pub data: Bytes,
501}
502
503impl FromUriPart for OtherNameComponent {
504 fn from_uri_part(segment: &[u8]) -> Option<OtherNameComponent> {
505 let (start, end) = segment.split_at(segment.partition_point(|x| *x == b'='));
506 let typ = std::str::from_utf8(&start[..start.len() - 1]).ok()?;
507 let length = end.len();
508
509 let mut buf = BytesMut::with_capacity(length);
510 buf.put(&end[..]);
511
512 Some(OtherNameComponent {
513 typ: VarNum::from(typ.parse::<u64>().ok()?),
514 length: VarNum::from(length),
515 data: buf.freeze(),
516 })
517 }
518}
519
520impl TlvEncode for OtherNameComponent {
521 fn encode(&self) -> Bytes {
522 let mut buf = BytesMut::with_capacity(self.size());
523 buf.put(self.typ.encode());
524 buf.put(self.length.encode());
525 buf.put(self.data.encode());
526 buf.freeze()
527 }
528
529 fn size(&self) -> usize {
530 self.typ.size() + self.length.size() + self.data.len()
531 }
532}
533
534impl TlvDecode for OtherNameComponent {
535 fn decode(bytes: &mut Bytes) -> ndn_tlv::Result<Self> {
536 let typ = VarNum::decode(bytes)?;
537 let length = VarNum::decode(bytes)?;
538
539 if bytes.remaining() < length.into() {
540 return Err(ndn_tlv::TlvError::UnexpectedEndOfStream);
541 }
542
543 let mut buf = BytesMut::with_capacity(length.into());
544 bytes.copy_to_slice(&mut buf);
545 Ok(Self {
546 typ,
547 length,
548 data: buf.freeze(),
549 })
550 }
551}
552
553impl ToUriPart for OtherNameComponent {
554 fn to_uri_part(&self) -> String {
555 format!(
556 "{}={}",
557 self.typ.value(),
558 urlencoding::encode_binary(&self.data)
559 )
560 }
561}
562
563#[derive(Debug, Tlv, PartialEq, Eq, Clone, From, Hash)]
564pub enum NameComponent {
565 GenericNameComponent(GenericNameComponent),
566 ImplicitSha256DigestComponent(ImplicitSha256DigestComponent),
567 ParametersSha256DigestComponent(ParametersSha256DigestComponent),
568 KeywordNameComponent(KeywordNameComponent),
569 SegmentNameComponent(SegmentNameComponent),
570 ByteOffsetNameComponent(ByteOffsetNameComponent),
571 VersionNameComponent(VersionNameComponent),
572 TimestampNameComponent(TimestampNameComponent),
573 SequenceNumNameComponent(SequenceNumNameComponent),
574 #[tlv(default)]
575 OtherNameComponent(OtherNameComponent),
576}
577
578impl PartialOrd for NameComponent {
579 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
580 Some(self.cmp(other))
581 }
582}
583
584impl Ord for NameComponent {
585 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
586 let mut self_repr = self.encode();
587 let mut other_repr = other.encode();
588
589 while self_repr.has_remaining() && other_repr.has_remaining() {
590 let self_cur = self_repr.get_u8();
591 let other_cur = other_repr.get_u8();
592
593 if self_cur < other_cur {
594 return std::cmp::Ordering::Less;
595 } else if self_cur > other_cur {
596 return std::cmp::Ordering::Greater;
597 }
598 }
599 std::cmp::Ordering::Equal
600 }
601}
602
603impl FromUriPart for NameComponent {
604 fn from_uri_part(segment: &[u8]) -> Option<Self> {
605 if segment.starts_with(b"sha256digest=") {
606 ImplicitSha256DigestComponent::from_uri_part(segment)
607 .map(Self::ImplicitSha256DigestComponent)
608 } else if segment.starts_with(b"params-sha256=") {
609 ParametersSha256DigestComponent::from_uri_part(segment)
610 .map(Self::ParametersSha256DigestComponent)
611 } else if segment.starts_with(b"seg=") {
612 SegmentNameComponent::from_uri_part(segment).map(Self::SegmentNameComponent)
613 } else if segment.starts_with(b"off=") {
614 ByteOffsetNameComponent::from_uri_part(segment).map(Self::ByteOffsetNameComponent)
615 } else if segment.starts_with(b"v=") {
616 VersionNameComponent::from_uri_part(segment).map(Self::VersionNameComponent)
617 } else if segment.starts_with(b"t=") {
618 TimestampNameComponent::from_uri_part(segment).map(Self::TimestampNameComponent)
619 } else if segment.starts_with(b"seq=") {
620 SequenceNumNameComponent::from_uri_part(segment).map(Self::SequenceNumNameComponent)
621 } else {
622 let expr = regex::bytes::Regex::new(r"^([0-9]+)=").expect("failed to compile regex");
623 if let Some(captures) = expr.captures(segment) {
624 let prefix: usize = String::from_utf8(captures.get(1).unwrap().as_bytes().to_vec())
625 .ok()?
626 .parse()
627 .ok()?;
628 match prefix {
629 8 => {
630 GenericNameComponent::from_uri_part(segment).map(Self::GenericNameComponent)
631 }
632 1 => ImplicitSha256DigestComponent::from_uri_part(segment)
633 .map(Self::ImplicitSha256DigestComponent),
634 2 => ParametersSha256DigestComponent::from_uri_part(segment)
635 .map(Self::ParametersSha256DigestComponent),
636 32 => {
637 KeywordNameComponent::from_uri_part(segment).map(Self::KeywordNameComponent)
638 }
639 50 => {
640 SegmentNameComponent::from_uri_part(segment).map(Self::SegmentNameComponent)
641 }
642 52 => ByteOffsetNameComponent::from_uri_part(segment)
643 .map(Self::ByteOffsetNameComponent),
644 54 => {
645 VersionNameComponent::from_uri_part(segment).map(Self::VersionNameComponent)
646 }
647 56 => TimestampNameComponent::from_uri_part(segment)
648 .map(Self::TimestampNameComponent),
649 58 => SequenceNumNameComponent::from_uri_part(segment)
650 .map(Self::SequenceNumNameComponent),
651 _ => OtherNameComponent::from_uri_part(segment).map(Self::OtherNameComponent),
652 }
653 } else {
654 Some(NameComponent::GenericNameComponent(
655 GenericNameComponent::from_uri_part(segment)?,
656 ))
657 }
658 }
659 }
660}
661
662impl ToUriPart for NameComponent {
663 fn to_uri_part(&self) -> String {
664 match *self {
665 Self::GenericNameComponent(ref component) => component.to_uri_part(),
666 Self::ImplicitSha256DigestComponent(ref component) => component.to_uri_part(),
667 Self::ParametersSha256DigestComponent(ref component) => component.to_uri_part(),
668 Self::KeywordNameComponent(ref component) => component.to_uri_part(),
669 Self::SegmentNameComponent(ref component) => component.to_uri_part(),
670 Self::ByteOffsetNameComponent(ref component) => component.to_uri_part(),
671 Self::VersionNameComponent(ref component) => component.to_uri_part(),
672 Self::TimestampNameComponent(ref component) => component.to_uri_part(),
673 Self::SequenceNumNameComponent(ref component) => component.to_uri_part(),
674 Self::OtherNameComponent(ref component) => component.to_uri_part(),
675 }
676 }
677}
678
679#[derive(Debug, Tlv, PartialEq, Eq, Clone, Hash)]
680#[tlv(7)]
681pub struct Name {
682 pub components: Vec<NameComponent>,
683}
684
685impl PartialOrd for Name {
686 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
687 Some(self.cmp(other))
688 }
689}
690
691impl Ord for Name {
692 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
693 let mut self_repr = self.encode();
694 let mut other_repr = other.encode();
695
696 while self_repr.has_remaining() && other_repr.has_remaining() {
697 let self_cur = self_repr.get_u8();
698 let other_cur = other_repr.get_u8();
699
700 if self_cur < other_cur {
701 return std::cmp::Ordering::Less;
702 } else if self_cur > other_cur {
703 return std::cmp::Ordering::Greater;
704 }
705 }
706 std::cmp::Ordering::Equal
707 }
708}
709
710impl Name {
711 pub const fn empty() -> Self {
712 Name {
713 components: Vec::new(),
714 }
715 }
716
717 pub fn from_str(s: &str) -> Result<Self> {
718 let s = if !s.starts_with("ndn:") {
719 Cow::Owned(format!("ndn:{}", s))
720 } else {
721 Cow::Borrowed(s)
722 };
723
724 let uri = Url::parse(&s)?;
725 let path = uri.path();
726
727 let mut components = Vec::with_capacity(path.split("/").count());
728
729 for mut segment in path.split("/") {
730 if segment == "" {
731 continue;
732 }
733 if segment.bytes().all(|x| x == b'.') {
734 segment = &segment[3..];
735 }
736 let decoded = urlencoding::decode_binary(segment.as_bytes());
737 components.push(NameComponent::from_uri_part(&decoded).ok_or(NdnError::ParseError)?);
738 }
739
740 Ok(Name { components })
741 }
742
743 pub fn to_uri(&self) -> Url {
744 let path: String = itertools::intersperse(
745 self.components
746 .iter()
747 .map(ToUriPart::to_uri_part)
748 .map(Cow::Owned),
749 Cow::Borrowed("/"),
750 )
751 .collect();
752 Url::parse(&format!("ndn:/{}", path)).unwrap()
753 }
754
755 pub fn iter(&self) -> impl Iterator<Item = &NameComponent> {
756 self.components.iter()
757 }
758
759 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut NameComponent> {
760 self.components.iter_mut()
761 }
762
763 pub fn into_iter(self) -> impl Iterator<Item = NameComponent> {
764 self.components.into_iter()
765 }
766
767 pub fn join<T: TryInto<Self>>(&self, other: T) -> Self
768 where
769 <T as TryInto<Self>>::Error: std::fmt::Debug,
770 {
771 let other = other.try_into().expect("Invalid name component string");
772
773 let mut components = Vec::with_capacity(self.components.len() + other.components.len());
774 components.extend_from_slice(&self.components);
775 components.extend_from_slice(&other.components);
776 Self { components }
777 }
778
779 pub fn has_prefix(&self, prefix: &Name) -> bool {
780 if prefix.components.len() > self.components.len() {
781 return false;
782 }
783 for (s, p) in self.components.iter().zip(prefix.iter()) {
784 if s != p {
785 return false;
786 }
787 }
788 true
789 }
790
791 pub fn remove_prefix(&mut self, prefix: &Name) -> bool {
792 if !self.has_prefix(prefix) {
793 return false;
794 }
795
796 for _ in 0..prefix.components.len() {
797 self.components.remove(0);
798 }
799 true
800 }
801}
802
803impl std::fmt::Display for Name {
804 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
805 self.to_uri().fmt(f)
806 }
807}
808
809impl From<NameComponent> for Name {
810 fn from(value: NameComponent) -> Self {
811 Name {
812 components: vec![value],
813 }
814 }
815}
816
817impl TryFrom<&str> for Name {
818 type Error = NdnError;
819
820 fn try_from(value: &str) -> std::result::Result<Name, NdnError> {
821 Name::from_str(value)
822 }
823}
824
825impl FromIterator<NameComponent> for Name {
826 fn from_iter<T: IntoIterator<Item = NameComponent>>(iter: T) -> Self {
827 Self {
828 components: iter.into_iter().collect(),
829 }
830 }
831}
832
833impl Extend<NameComponent> for Name {
834 fn extend<T: IntoIterator<Item = NameComponent>>(&mut self, iter: T) {
835 self.components.extend(iter)
836 }
837}
838
839#[cfg(test)]
840mod tests {
841 use super::*;
842
843 #[test]
844 fn simple_name() {
845 let uri = "/hello/world";
846 let name = Name::from_str(uri).unwrap();
847 assert_eq!(
848 name,
849 Name {
850 components: vec![
851 NameComponent::GenericNameComponent(GenericNameComponent {
852 name: Bytes::from(&b"hello"[..])
853 }),
854 NameComponent::GenericNameComponent(GenericNameComponent {
855 name: Bytes::from(&b"world"[..])
856 })
857 ]
858 }
859 );
860 assert_eq!(name.to_uri(), Url::parse("ndn:/hello/world").unwrap());
861 }
862
863 #[test]
864 fn simple_name_with_schema() {
865 let uri = "ndn:/hello/world";
866 let name = Name::from_str(uri).unwrap();
867 assert_eq!(
868 name,
869 Name {
870 components: vec![
871 NameComponent::GenericNameComponent(GenericNameComponent {
872 name: Bytes::from(&b"hello"[..])
873 }),
874 NameComponent::GenericNameComponent(GenericNameComponent {
875 name: Bytes::from(&b"world"[..])
876 })
877 ]
878 }
879 );
880 assert_eq!(name.to_uri(), Url::parse("ndn:/hello/world").unwrap());
881 }
882
883 #[test]
884 fn name_with_digest() {
885 let uri = "/hello/world/sha256digest=deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
886 let name = Name::from_str(uri).unwrap();
887 assert_eq!(
888 name,
889 Name {
890 components: vec![
891 NameComponent::GenericNameComponent(GenericNameComponent {
892 name: Bytes::from(&b"hello"[..])
893 }),
894 NameComponent::GenericNameComponent(GenericNameComponent {
895 name: Bytes::from(&b"world"[..])
896 }),
897 NameComponent::ImplicitSha256DigestComponent(ImplicitSha256DigestComponent {
898 name: [
899 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
900 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
901 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
902 ]
903 })
904 ]
905 }
906 );
907 assert_eq!(name.to_uri(), Url::parse(&format!("ndn:{}", uri)).unwrap());
908 }
909
910 #[test]
911 fn name_with_digest_direct() {
912 let uri = "/hello/world/1=%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef";
913 let name = Name::from_str(uri).unwrap();
914 assert_eq!(
915 name,
916 Name {
917 components: vec![
918 NameComponent::GenericNameComponent(GenericNameComponent {
919 name: Bytes::from(&b"hello"[..])
920 }),
921 NameComponent::GenericNameComponent(GenericNameComponent {
922 name: Bytes::from(&b"world"[..])
923 }),
924 NameComponent::ImplicitSha256DigestComponent(ImplicitSha256DigestComponent {
925 name: [
926 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
927 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
928 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
929 ]
930 })
931 ]
932 }
933 );
934 }
935
936 #[test]
937 fn name_with_params_sha256() {
938 let uri = "/hello/world/params-sha256=deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
939 let name = Name::from_str(uri).unwrap();
940 assert_eq!(
941 name,
942 Name {
943 components: vec![
944 NameComponent::GenericNameComponent(GenericNameComponent {
945 name: Bytes::from(&b"hello"[..])
946 }),
947 NameComponent::GenericNameComponent(GenericNameComponent {
948 name: Bytes::from(&b"world"[..])
949 }),
950 NameComponent::ParametersSha256DigestComponent(
951 ParametersSha256DigestComponent {
952 name: [
953 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE,
954 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD,
955 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
956 ]
957 }
958 )
959 ]
960 }
961 );
962 assert_eq!(name.to_uri(), Url::parse(&format!("ndn:{}", uri)).unwrap());
963 }
964
965 #[test]
966 fn name_with_params_sha256_direct() {
967 let uri = "/hello/world/2=%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef%de%ad%be%ef";
968 let name = Name::from_str(uri).unwrap();
969 assert_eq!(
970 name,
971 Name {
972 components: vec![
973 NameComponent::GenericNameComponent(GenericNameComponent {
974 name: Bytes::from(&b"hello"[..])
975 }),
976 NameComponent::GenericNameComponent(GenericNameComponent {
977 name: Bytes::from(&b"world"[..])
978 }),
979 NameComponent::ParametersSha256DigestComponent(
980 ParametersSha256DigestComponent {
981 name: [
982 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE,
983 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD,
984 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
985 ]
986 }
987 )
988 ]
989 }
990 );
991 }
992
993 #[test]
994 fn dot2() {
995 let uri = "/hello/../world";
996 let name = Name::from_str(uri).unwrap();
997 assert_eq!(
998 name,
999 Name {
1000 components: vec![NameComponent::GenericNameComponent(GenericNameComponent {
1001 name: Bytes::from(&b"world"[..])
1002 })]
1003 }
1004 );
1005 }
1006
1007 #[test]
1008 fn dot3() {
1009 let uri = "/.../world";
1010 let name = Name::from_str(uri).unwrap();
1011 assert_eq!(
1012 name,
1013 Name {
1014 components: vec![
1015 NameComponent::GenericNameComponent(GenericNameComponent {
1016 name: Bytes::from(&b""[..])
1017 }),
1018 NameComponent::GenericNameComponent(GenericNameComponent {
1019 name: Bytes::from(&b"world"[..])
1020 })
1021 ]
1022 }
1023 );
1024 assert_eq!(name.to_uri(), Url::parse(&format!("ndn:{}", uri)).unwrap());
1025 }
1026
1027 #[test]
1028 fn dot4() {
1029 let uri = "/..../world";
1030 let name = Name::from_str(uri).unwrap();
1031 assert_eq!(
1032 name,
1033 Name {
1034 components: vec![
1035 NameComponent::GenericNameComponent(GenericNameComponent {
1036 name: Bytes::from(&b"."[..])
1037 }),
1038 NameComponent::GenericNameComponent(GenericNameComponent {
1039 name: Bytes::from(&b"world"[..])
1040 })
1041 ]
1042 }
1043 );
1044 assert_eq!(name.to_uri(), Url::parse(&format!("ndn:{}", uri)).unwrap());
1045 }
1046
1047 #[test]
1048 fn name_join_name() {
1049 let name = Name::from_str("/hello").unwrap();
1050 let name2 = Name::from_str("/world").unwrap();
1051 assert_eq!(name.join(name2), Name::from_str("/hello/world").unwrap());
1052 }
1053
1054 #[test]
1055 fn name_join_component() {
1056 let name = Name::from_str("/hello").unwrap();
1057 let component = NameComponent::from_uri_part(b"world").unwrap();
1058 assert_eq!(
1059 name.join(component),
1060 Name::from_str("/hello/world").unwrap()
1061 );
1062 }
1063
1064 #[test]
1065 fn name_slash_str() {
1066 let name = Name::from_str("/hello").unwrap();
1067 assert_eq!(name.join("world"), Name::from_str("/hello/world").unwrap());
1068 }
1069
1070 #[test]
1071 fn name_keyword() {
1072 let uri = "ndn:/hello/32=PA/world";
1073 let name = Name::from_str(&uri).unwrap();
1074 assert_eq!(
1075 name,
1076 Name {
1077 components: vec![
1078 NameComponent::GenericNameComponent(GenericNameComponent {
1079 name: Bytes::from(&b"hello"[..])
1080 }),
1081 NameComponent::KeywordNameComponent(KeywordNameComponent {
1082 name: Bytes::from(&b"PA"[..])
1083 }),
1084 NameComponent::GenericNameComponent(GenericNameComponent {
1085 name: Bytes::from(&b"world"[..])
1086 }),
1087 ]
1088 }
1089 );
1090
1091 assert_eq!(name.to_uri(), Url::parse(&uri).unwrap());
1092 }
1093
1094 #[test]
1095 fn name_segment() {
1096 let uri = "ndn:/hello/seg=5/world";
1097 let name = Name::from_str(&uri).unwrap();
1098 assert_eq!(
1099 name,
1100 Name {
1101 components: vec![
1102 NameComponent::GenericNameComponent(GenericNameComponent {
1103 name: Bytes::from(&b"hello"[..])
1104 }),
1105 NameComponent::SegmentNameComponent(SegmentNameComponent {
1106 segment_number: NonNegativeInteger::U8(5)
1107 }),
1108 NameComponent::GenericNameComponent(GenericNameComponent {
1109 name: Bytes::from(&b"world"[..])
1110 }),
1111 ]
1112 }
1113 );
1114
1115 assert_eq!(name.to_uri(), Url::parse(&uri).unwrap());
1116 }
1117
1118 #[test]
1119 fn name_segment_binary() {
1120 let uri = "ndn:/hello/50=%05/world";
1121 let name = Name::from_str(&uri).unwrap();
1122 assert_eq!(
1123 name,
1124 Name {
1125 components: vec![
1126 NameComponent::GenericNameComponent(GenericNameComponent {
1127 name: Bytes::from(&b"hello"[..])
1128 }),
1129 NameComponent::SegmentNameComponent(SegmentNameComponent {
1130 segment_number: NonNegativeInteger::U8(5)
1131 }),
1132 NameComponent::GenericNameComponent(GenericNameComponent {
1133 name: Bytes::from(&b"world"[..])
1134 }),
1135 ]
1136 }
1137 );
1138 }
1139
1140 #[test]
1141 fn name_offset() {
1142 let uri = "ndn:/hello/off=5/world";
1143 let name = Name::from_str(&uri).unwrap();
1144 assert_eq!(
1145 name,
1146 Name {
1147 components: vec![
1148 NameComponent::GenericNameComponent(GenericNameComponent {
1149 name: Bytes::from(&b"hello"[..])
1150 }),
1151 NameComponent::ByteOffsetNameComponent(ByteOffsetNameComponent {
1152 offset: NonNegativeInteger::U8(5)
1153 }),
1154 NameComponent::GenericNameComponent(GenericNameComponent {
1155 name: Bytes::from(&b"world"[..])
1156 }),
1157 ]
1158 }
1159 );
1160
1161 assert_eq!(name.to_uri(), Url::parse(&uri).unwrap());
1162 }
1163
1164 #[test]
1165 fn name_offset_binary() {
1166 let uri = "ndn:/hello/52=%05/world";
1167 let name = Name::from_str(&uri).unwrap();
1168 assert_eq!(
1169 name,
1170 Name {
1171 components: vec![
1172 NameComponent::GenericNameComponent(GenericNameComponent {
1173 name: Bytes::from(&b"hello"[..])
1174 }),
1175 NameComponent::ByteOffsetNameComponent(ByteOffsetNameComponent {
1176 offset: NonNegativeInteger::U8(5)
1177 }),
1178 NameComponent::GenericNameComponent(GenericNameComponent {
1179 name: Bytes::from(&b"world"[..])
1180 }),
1181 ]
1182 }
1183 );
1184 }
1185
1186 #[test]
1187 fn name_version() {
1188 let uri = "ndn:/hello/v=5/world";
1189 let name = Name::from_str(&uri).unwrap();
1190 assert_eq!(
1191 name,
1192 Name {
1193 components: vec![
1194 NameComponent::GenericNameComponent(GenericNameComponent {
1195 name: Bytes::from(&b"hello"[..])
1196 }),
1197 NameComponent::VersionNameComponent(VersionNameComponent {
1198 version: NonNegativeInteger::U8(5)
1199 }),
1200 NameComponent::GenericNameComponent(GenericNameComponent {
1201 name: Bytes::from(&b"world"[..])
1202 }),
1203 ]
1204 }
1205 );
1206
1207 assert_eq!(name.to_uri(), Url::parse(&uri).unwrap());
1208 }
1209
1210 #[test]
1211 fn name_version_binary() {
1212 let uri = "ndn:/hello/54=%05/world";
1213 let name = Name::from_str(&uri).unwrap();
1214 assert_eq!(
1215 name,
1216 Name {
1217 components: vec![
1218 NameComponent::GenericNameComponent(GenericNameComponent {
1219 name: Bytes::from(&b"hello"[..])
1220 }),
1221 NameComponent::VersionNameComponent(VersionNameComponent {
1222 version: NonNegativeInteger::U8(5)
1223 }),
1224 NameComponent::GenericNameComponent(GenericNameComponent {
1225 name: Bytes::from(&b"world"[..])
1226 }),
1227 ]
1228 }
1229 );
1230 }
1231
1232 #[test]
1233 fn name_timestamp() {
1234 let uri = "ndn:/hello/t=5/world";
1235 let name = Name::from_str(&uri).unwrap();
1236 assert_eq!(
1237 name,
1238 Name {
1239 components: vec![
1240 NameComponent::GenericNameComponent(GenericNameComponent {
1241 name: Bytes::from(&b"hello"[..])
1242 }),
1243 NameComponent::TimestampNameComponent(TimestampNameComponent {
1244 time: NonNegativeInteger::U8(5)
1245 }),
1246 NameComponent::GenericNameComponent(GenericNameComponent {
1247 name: Bytes::from(&b"world"[..])
1248 }),
1249 ]
1250 }
1251 );
1252
1253 assert_eq!(name.to_uri(), Url::parse(&uri).unwrap());
1254 }
1255
1256 #[test]
1257 fn name_timestamp_binary() {
1258 let uri = "ndn:/hello/56=%05/world";
1259 let name = Name::from_str(&uri).unwrap();
1260 assert_eq!(
1261 name,
1262 Name {
1263 components: vec![
1264 NameComponent::GenericNameComponent(GenericNameComponent {
1265 name: Bytes::from(&b"hello"[..])
1266 }),
1267 NameComponent::TimestampNameComponent(TimestampNameComponent {
1268 time: NonNegativeInteger::U8(5)
1269 }),
1270 NameComponent::GenericNameComponent(GenericNameComponent {
1271 name: Bytes::from(&b"world"[..])
1272 }),
1273 ]
1274 }
1275 );
1276 }
1277
1278 #[test]
1279 fn name_sequence_num() {
1280 let uri = "ndn:/hello/seq=5/world";
1281 let name = Name::from_str(&uri).unwrap();
1282 assert_eq!(
1283 name,
1284 Name {
1285 components: vec![
1286 NameComponent::GenericNameComponent(GenericNameComponent {
1287 name: Bytes::from(&b"hello"[..])
1288 }),
1289 NameComponent::SequenceNumNameComponent(SequenceNumNameComponent {
1290 sequence_number: NonNegativeInteger::U8(5)
1291 }),
1292 NameComponent::GenericNameComponent(GenericNameComponent {
1293 name: Bytes::from(&b"world"[..])
1294 }),
1295 ]
1296 }
1297 );
1298
1299 assert_eq!(name.to_uri(), Url::parse(&uri).unwrap());
1300 }
1301
1302 #[test]
1303 fn name_sequence_num_binary() {
1304 let uri = "ndn:/hello/58=%05/world";
1305 let name = Name::from_str(&uri).unwrap();
1306 assert_eq!(
1307 name,
1308 Name {
1309 components: vec![
1310 NameComponent::GenericNameComponent(GenericNameComponent {
1311 name: Bytes::from(&b"hello"[..])
1312 }),
1313 NameComponent::SequenceNumNameComponent(SequenceNumNameComponent {
1314 sequence_number: NonNegativeInteger::U8(5)
1315 }),
1316 NameComponent::GenericNameComponent(GenericNameComponent {
1317 name: Bytes::from(&b"world"[..])
1318 }),
1319 ]
1320 }
1321 );
1322 }
1323
1324 #[test]
1325 fn name_order() {
1326 let mut names = [
1327 Name::from_str("ndn:/some/prefix/name/fgh").unwrap(),
1328 Name::from_str("ndn:/some/prefix/name/asd").unwrap(),
1329 Name::from_str("ndn:/some/prefix/name/sha256digest=deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
1330 Name::from_str("ndn:/some/prefix").unwrap(),
1331 ];
1332 names.sort();
1333 assert_eq!(names, [
1334 Name::from_str("ndn:/some/prefix").unwrap(),
1335 Name::from_str("ndn:/some/prefix/name/asd").unwrap(),
1336 Name::from_str("ndn:/some/prefix/name/fgh").unwrap(),
1337 Name::from_str("ndn:/some/prefix/name/sha256digest=deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(),
1338 ]);
1339 }
1340}