ndn_protocol/
name.rs

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}