Skip to main content

ndn_protocol/
name.rs

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