1use crate::models::*;
2use itertools::Itertools;
3use std::borrow::Cow;
4use std::fmt::{Display, Formatter};
5use std::hash::{Hash, Hasher};
6use std::iter::FromIterator;
7use std::marker::PhantomData;
8use std::mem::discriminant;
9
10#[derive(Debug, Clone)]
12pub enum AsPathSegment {
13 AsSequence(Vec<Asn>),
14 AsSet(Vec<Asn>),
15 ConfedSequence(Vec<Asn>),
16 ConfedSet(Vec<Asn>),
17}
18
19impl AsPathSegment {
20 pub fn sequence<S: AsRef<[u32]>>(seq: S) -> Self {
22 AsPathSegment::AsSequence(seq.as_ref().iter().copied().map_into().collect())
23 }
24
25 pub fn set<S: AsRef<[u32]>>(seq: S) -> Self {
27 AsPathSegment::AsSet(seq.as_ref().iter().copied().map_into().collect())
28 }
29
30 pub fn route_len(&self) -> usize {
33 match self {
34 AsPathSegment::AsSequence(v) => v.len(),
35 AsPathSegment::AsSet(_) => 1,
36 AsPathSegment::ConfedSequence(_) | AsPathSegment::ConfedSet(_) => 0,
37 }
38 }
39
40 pub fn len(&self) -> usize {
43 self.as_ref().len()
44 }
45
46 pub fn is_empty(&self) -> bool {
48 self.as_ref().is_empty()
49 }
50
51 pub fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter {
53 self.into_iter()
54 }
55
56 pub fn iter_mut(&mut self) -> <&'_ mut Self as IntoIterator>::IntoIter {
58 self.into_iter()
59 }
60
61 pub fn is_confed(&self) -> bool {
66 matches!(
67 self,
68 AsPathSegment::ConfedSequence(_) | AsPathSegment::ConfedSet(_)
69 )
70 }
71
72 fn merge_in_place(&mut self, other: &mut Self) -> bool {
76 use AsPathSegment::*;
77
78 match (self, other) {
79 (AsSequence(x), AsSequence(y)) | (ConfedSequence(x), ConfedSequence(y)) => {
80 x.extend_from_slice(y);
81 true
82 }
83 (x @ (AsSequence(_) | ConfedSequence(_)), y) if x.is_empty() => {
84 std::mem::swap(x, y);
85 true
86 }
87 (_, AsSequence(y) | ConfedSequence(y)) if y.is_empty() => true,
88 _ => false,
89 }
90 }
91
92 fn dedup_merge_in_place(&mut self, other: &mut Self) -> bool {
97 use AsPathSegment::*;
98
99 other.dedup();
100 match (self, other) {
101 (AsSequence(x), AsSequence(y)) | (ConfedSequence(x), ConfedSequence(y)) => {
102 x.extend_from_slice(y);
103 x.dedup();
104 true
105 }
106 (x @ (AsSequence(_) | ConfedSequence(_)), y) if x.is_empty() => {
107 std::mem::swap(x, y);
108 true
109 }
110 (_, AsSequence(y) | ConfedSequence(y)) if y.is_empty() => true,
111 _ => false,
112 }
113 }
114
115 fn dedup(&mut self) {
120 match self {
121 AsPathSegment::AsSequence(x) | AsPathSegment::ConfedSequence(x) => x.dedup(),
122 AsPathSegment::AsSet(x) => {
123 x.sort_unstable();
124 x.dedup();
125 if x.len() == 1 {
126 *self = AsPathSegment::AsSequence(std::mem::take(x));
127 }
128 }
129 AsPathSegment::ConfedSet(x) => {
130 x.sort_unstable();
131 x.dedup();
132 if x.len() == 1 {
133 *self = AsPathSegment::ConfedSequence(std::mem::take(x));
134 }
135 }
136 }
137 }
138
139 pub fn to_u32_vec_opt(&self, dedup: bool) -> Option<Vec<u32>> {
140 match self {
141 AsPathSegment::AsSequence(v) => {
142 let mut p: Vec<u32> = v.iter().map(|asn| (*asn).into()).collect();
143 if dedup {
144 p.dedup();
145 }
146 Some(p)
147 }
148 AsPathSegment::AsSet(v) => {
149 if v.len() == 1 {
150 Some(vec![v[0].into()])
153 } else {
154 None
155 }
156 }
157 _ => None,
158 }
159 }
160}
161
162impl IntoIterator for AsPathSegment {
163 type Item = Asn;
164 type IntoIter = std::vec::IntoIter<Asn>;
165
166 fn into_iter(self) -> Self::IntoIter {
167 let (AsPathSegment::AsSequence(x)
168 | AsPathSegment::AsSet(x)
169 | AsPathSegment::ConfedSequence(x)
170 | AsPathSegment::ConfedSet(x)) = self;
171 x.into_iter()
172 }
173}
174
175impl<'a> IntoIterator for &'a AsPathSegment {
176 type Item = &'a Asn;
177 type IntoIter = std::slice::Iter<'a, Asn>;
178
179 fn into_iter(self) -> Self::IntoIter {
180 let (AsPathSegment::AsSequence(x)
181 | AsPathSegment::AsSet(x)
182 | AsPathSegment::ConfedSequence(x)
183 | AsPathSegment::ConfedSet(x)) = self;
184 x.iter()
185 }
186}
187
188impl<'a> IntoIterator for &'a mut AsPathSegment {
189 type Item = &'a mut Asn;
190 type IntoIter = std::slice::IterMut<'a, Asn>;
191
192 fn into_iter(self) -> Self::IntoIter {
193 let (AsPathSegment::AsSequence(x)
194 | AsPathSegment::AsSet(x)
195 | AsPathSegment::ConfedSequence(x)
196 | AsPathSegment::ConfedSet(x)) = self;
197 x.iter_mut()
198 }
199}
200
201impl AsRef<[Asn]> for AsPathSegment {
202 fn as_ref(&self) -> &[Asn] {
203 let (AsPathSegment::AsSequence(x)
204 | AsPathSegment::AsSet(x)
205 | AsPathSegment::ConfedSequence(x)
206 | AsPathSegment::ConfedSet(x)) = self;
207 x
208 }
209}
210
211impl Hash for AsPathSegment {
212 fn hash<H: Hasher>(&self, state: &mut H) {
213 discriminant(self).hash(state);
215
216 let set = match self {
217 AsPathSegment::AsSequence(x) | AsPathSegment::ConfedSequence(x) => {
218 return x.hash(state)
219 }
220 AsPathSegment::AsSet(x) | AsPathSegment::ConfedSet(x) => x,
221 };
222
223 if set.len() <= 32 {
225 let mut buffer = [Asn::new_32bit(0); 32];
226 set.iter()
227 .zip(&mut buffer)
228 .for_each(|(asn, buffer)| *buffer = *asn);
229
230 let slice = &mut buffer[..set.len()];
231 slice.sort_unstable();
232 Asn::hash_slice(slice, state);
233 return;
234 }
235
236 set.iter().sorted().for_each(|x| x.hash(state));
238 }
239}
240
241impl PartialEq for AsPathSegment {
256 fn eq(&self, other: &Self) -> bool {
257 let (x, y) = match (self, other) {
258 (AsPathSegment::AsSequence(x), AsPathSegment::AsSequence(y))
259 | (AsPathSegment::ConfedSequence(x), AsPathSegment::ConfedSequence(y)) => {
260 return x == y
261 }
262 (AsPathSegment::AsSet(x), AsPathSegment::AsSet(y))
263 | (AsPathSegment::ConfedSet(x), AsPathSegment::ConfedSet(y)) => (x, y),
264 _ => return false,
265 };
266
267 if x.len() != y.len() {
269 return false;
270 } else if x == y {
271 return true;
272 }
273
274 if x.len() <= 32 {
275 let mut x_buffer = [Asn::new_32bit(0); 32];
276 let mut y_buffer = [Asn::new_32bit(0); 32];
277 x.iter()
278 .zip(&mut x_buffer)
279 .for_each(|(asn, buffer)| *buffer = *asn);
280 y.iter()
281 .zip(&mut y_buffer)
282 .for_each(|(asn, buffer)| *buffer = *asn);
283
284 x_buffer[..x.len()].sort_unstable();
285 y_buffer[..y.len()].sort_unstable();
286 return x_buffer[..x.len()] == y_buffer[..y.len()];
287 }
288
289 x.iter()
290 .sorted()
291 .zip(y.iter().sorted())
292 .all(|(a, b)| a == b)
293 }
294}
295
296impl Eq for AsPathSegment {}
297
298struct AsPathNumberedRouteIter<'a> {
302 path: &'a [AsPathSegment],
303 index: usize,
304 route_num: u64,
305}
306
307impl Iterator for AsPathNumberedRouteIter<'_> {
308 type Item = Asn;
309
310 fn next(&mut self) -> Option<Self::Item> {
311 loop {
312 match self.path.first()? {
313 AsPathSegment::AsSequence(x) => match x.get(self.index) {
314 None => {
315 self.index = 0;
316 self.path = &self.path[1..];
317 }
318 Some(asn) => {
319 self.index += 1;
320 return Some(*asn);
321 }
322 },
323 AsPathSegment::AsSet(x) => {
324 self.path = &self.path[1..];
325 if x.is_empty() {
326 return Some(Asn::RESERVED);
327 }
328
329 let asn = x[(self.route_num % x.len() as u64) as usize];
330 self.route_num /= x.len() as u64;
331 return Some(asn);
332 }
333 _ => self.path = &self.path[1..],
334 }
335 }
336 }
337}
338
339pub struct AsPathRouteIter<'a, D> {
340 path: Cow<'a, [AsPathSegment]>,
341 route_num: u64,
342 total_routes: u64,
343 _phantom: PhantomData<D>,
344}
345
346impl<D> Iterator for AsPathRouteIter<'_, D>
347where
348 D: FromIterator<Asn>,
349{
350 type Item = D;
351
352 fn next(&mut self) -> Option<Self::Item> {
353 if self.route_num >= self.total_routes {
354 return None;
355 }
356
357 if self.route_num == 0 && self.path.len() == 1 {
359 if let AsPathSegment::AsSequence(sequence) = &self.path[0] {
360 let route = D::from_iter(sequence.iter().copied());
361 self.route_num += 1;
362 return Some(route);
363 }
364 }
365
366 let route_asn_iter = AsPathNumberedRouteIter {
367 path: self.path.as_ref(),
368 index: 0,
369 route_num: self.route_num,
370 };
371
372 self.route_num += 1;
373 Some(D::from_iter(route_asn_iter))
374 }
375}
376
377#[derive(Debug, PartialEq, Clone, Eq, Default, Hash)]
378pub struct AsPath {
379 pub segments: Vec<AsPathSegment>,
380}
381
382pub type SegmentIter<'a> = std::slice::Iter<'a, AsPathSegment>;
385pub type SegmentIterMut<'a> = std::slice::IterMut<'a, AsPathSegment>;
386pub type SegmentIntoIter = std::vec::IntoIter<AsPathSegment>;
387
388impl AsPath {
389 pub fn new() -> AsPath {
390 AsPath { segments: vec![] }
391 }
392
393 pub fn from_sequence<S: AsRef<[u32]>>(seq: S) -> Self {
395 let segment = AsPathSegment::AsSequence(seq.as_ref().iter().copied().map_into().collect());
396
397 AsPath {
398 segments: vec![segment],
399 }
400 }
401
402 pub fn from_segments(segments: Vec<AsPathSegment>) -> AsPath {
403 AsPath { segments }
404 }
405
406 pub fn append_segment(&mut self, segment: AsPathSegment) {
409 self.segments.push(segment);
410 }
411
412 pub fn is_empty(&self) -> bool {
415 self.segments.is_empty()
416 }
417
418 pub fn route_len(&self) -> usize {
425 self.segments.iter().map(AsPathSegment::route_len).sum()
426 }
427
428 pub fn len(&self) -> usize {
431 self.segments.len()
432 }
433
434 pub fn num_route_variations(&self) -> u64 {
437 let mut variations: u64 = 1;
438
439 for segment in &self.segments {
440 if let AsPathSegment::AsSet(x) = segment {
441 variations *= x.len() as u64;
442 }
443 }
444
445 variations
446 }
447
448 pub fn contains_asn(&self, x: Asn) -> bool {
450 self.iter_segments().flatten().contains(&x)
451 }
452
453 pub fn coalesce(&mut self) {
485 let mut end_index = 0;
486 let mut scan_index = 1;
487
488 while scan_index < self.segments.len() {
489 let (a, b) = self.segments.split_at_mut(scan_index);
490 if !AsPathSegment::merge_in_place(&mut a[end_index], &mut b[0]) {
491 end_index += 1;
492 self.segments.swap(end_index, scan_index);
493 }
494 scan_index += 1;
495 }
496
497 self.segments.truncate(end_index + 1);
498 }
499
500 pub fn dedup_coalesce(&mut self) {
533 if !self.segments.is_empty() {
534 self.segments[0].dedup();
535 }
536 let mut end_index = 0;
537 let mut scan_index = 1;
538
539 while scan_index < self.segments.len() {
540 let (a, b) = self.segments.split_at_mut(scan_index);
541 if !AsPathSegment::dedup_merge_in_place(&mut a[end_index], &mut b[0]) {
542 end_index += 1;
543 self.segments.swap(end_index, scan_index);
544 }
545 scan_index += 1;
546 }
547
548 self.segments.truncate(end_index + 1);
549 }
550
551 pub fn has_equivalent_routing(&self, other: &Self) -> bool {
556 let mut a = self.to_owned();
557 let mut b = other.to_owned();
558
559 a.dedup_coalesce();
560 b.dedup_coalesce();
561
562 a == b
563 }
564
565 pub fn required_asn_length(&self) -> AsnLength {
567 self.iter_segments().flatten().map(Asn::required_len).fold(
568 AsnLength::Bits16,
569 |a, b| match (a, b) {
570 (AsnLength::Bits16, AsnLength::Bits16) => AsnLength::Bits16,
571 _ => AsnLength::Bits32,
572 },
573 )
574 }
575
576 pub fn iter_segments(&self) -> SegmentIter<'_> {
577 self.segments.iter()
578 }
579
580 pub fn iter_segments_mut(&mut self) -> SegmentIterMut<'_> {
581 self.segments.iter_mut()
582 }
583
584 pub fn into_segments_iter(self) -> SegmentIntoIter {
585 self.segments.into_iter()
586 }
587
588 pub fn iter_routes<D>(&self) -> AsPathRouteIter<'_, D>
590 where
591 D: FromIterator<Asn>,
592 {
593 AsPathRouteIter {
594 path: Cow::Borrowed(&self.segments),
595 route_num: 0,
596 total_routes: self.num_route_variations(),
597 _phantom: PhantomData,
598 }
599 }
600
601 pub fn merge_aspath_as4path(aspath: &AsPath, as4path: &AsPath) -> AsPath {
623 if aspath.route_len() < as4path.route_len() {
624 return aspath.clone();
626 }
627
628 let mut as4iter = as4path.segments.iter();
629 let mut new_segs: Vec<AsPathSegment> = vec![];
630
631 for seg in &aspath.segments {
632 match as4iter.next() {
633 None => {
634 new_segs.push(seg.clone());
635 }
636 Some(as4seg_unwrapped) => {
637 if let (AsPathSegment::AsSequence(seq), AsPathSegment::AsSequence(seq4)) =
638 (seg, as4seg_unwrapped)
639 {
640 let diff_len = seq.len() as i32 - seq4.len() as i32;
641 match diff_len {
642 d if d > 0 => {
643 let mut new_seq: Vec<Asn> = vec![];
646 new_seq.extend(seq.iter().take(d as usize));
647 new_seq.extend(seq4);
648 new_segs.push(AsPathSegment::AsSequence(new_seq));
649 }
650 d if d < 0 => {
651 new_segs.push(AsPathSegment::AsSequence(seq.clone()));
652 }
653 _ => {
654 new_segs.push(AsPathSegment::AsSequence(seq4.clone()));
655 }
656 }
657 } else {
658 new_segs.push(as4seg_unwrapped.clone());
659 }
660 }
661 };
662 }
663
664 AsPath { segments: new_segs }
665 }
666
667 pub fn iter_origins(&self) -> impl '_ + Iterator<Item = Asn> {
670 let origin_slice = match self.segments.last() {
671 Some(AsPathSegment::AsSequence(v)) => v.last().map(std::slice::from_ref).unwrap_or(&[]),
672 Some(AsPathSegment::AsSet(v)) => v.as_ref(),
673 _ => &[],
674 };
675
676 origin_slice.iter().copied()
677 }
678
679 pub fn get_origin_opt(&self) -> Option<Asn> {
683 match self.segments.last() {
684 Some(AsPathSegment::AsSequence(v)) => v.last().copied(),
685 Some(AsPathSegment::AsSet(v)) if v.len() == 1 => Some(v[0]),
686 _ => None,
687 }
688 }
689
690 pub fn get_collector_opt(&self) -> Option<Asn> {
693 match self.segments.first() {
694 Some(AsPathSegment::AsSequence(v)) => v.first().copied(),
695 Some(AsPathSegment::AsSet(v)) if v.len() == 1 => Some(v[0]),
696 _ => None,
697 }
698 }
699
700 pub fn to_u32_vec_opt(&self, dedup: bool) -> Option<Vec<u32>> {
701 let mut path = vec![];
702
703 for seg in self.segments.iter().rev() {
705 if let Some(p) = seg.to_u32_vec_opt(dedup) {
706 path.extend(p.iter().rev());
709 } else {
710 return None;
714 }
715 }
716
717 match path.is_empty() {
718 true => {
719 None
721 }
722 false => {
723 path.reverse();
725 Some(path)
726 }
727 }
728 }
729}
730
731impl<'a> IntoIterator for &'a AsPath {
733 type Item = Vec<Asn>;
734 type IntoIter = AsPathRouteIter<'a, Vec<Asn>>;
735
736 fn into_iter(self) -> Self::IntoIter {
737 self.iter_routes()
738 }
739}
740
741impl IntoIterator for AsPath {
743 type Item = Vec<Asn>;
744 type IntoIter = AsPathRouteIter<'static, Vec<Asn>>;
745
746 fn into_iter(self) -> Self::IntoIter {
747 AsPathRouteIter {
748 total_routes: self.num_route_variations(),
749 path: Cow::Owned(self.segments),
750 route_num: 0,
751 _phantom: PhantomData,
752 }
753 }
754}
755
756impl Display for AsPath {
757 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
758 for (index, segment) in self.iter_segments().enumerate() {
759 if index != 0 {
760 write!(f, " ")?;
761 }
762
763 match segment {
764 AsPathSegment::AsSequence(v) | AsPathSegment::ConfedSequence(v) => {
765 let mut asn_iter = v.iter();
766 if let Some(first_element) = asn_iter.next() {
767 write!(f, "{}", first_element)?;
768
769 for asn in asn_iter {
770 write!(f, " {}", asn)?;
771 }
772 }
773 }
774 AsPathSegment::AsSet(v) | AsPathSegment::ConfedSet(v) => {
775 write!(f, "{{")?;
776 let mut asn_iter = v.iter();
777 if let Some(first_element) = asn_iter.next() {
778 write!(f, "{}", first_element)?;
779
780 for asn in asn_iter {
781 write!(f, ",{}", asn)?;
782 }
783 }
784 write!(f, "}}")?;
785 }
786 }
787 }
788
789 Ok(())
790 }
791}
792
793#[cfg(feature = "serde")]
794mod serde_impl {
795 use super::*;
796 use serde::de::{SeqAccess, Visitor};
797 use serde::ser::SerializeSeq;
798 use serde::{Deserialize, Deserializer, Serialize, Serializer};
799 use std::borrow::Cow;
800
801 #[allow(non_camel_case_types)]
805 #[derive(Serialize, Deserialize)]
806 enum SegmentType {
807 AS_SET,
808 AS_SEQUENCE,
809 AS_CONFED_SEQUENCE,
810 AS_CONFED_SET,
811 }
812
813 #[derive(Serialize, Deserialize)]
814 struct VerboseSegment<'s> {
815 ty: SegmentType,
816 values: Cow<'s, [Asn]>,
817 }
818
819 impl Serialize for AsPathSegment {
820 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
821 where
822 S: Serializer,
823 {
824 let (ty, elements) = match self {
825 AsPathSegment::AsSequence(x) => (SegmentType::AS_SEQUENCE, x.as_ref()),
826 AsPathSegment::AsSet(x) => (SegmentType::AS_SET, x.as_ref()),
827 AsPathSegment::ConfedSequence(x) => (SegmentType::AS_CONFED_SEQUENCE, x.as_ref()),
828 AsPathSegment::ConfedSet(x) => (SegmentType::AS_CONFED_SET, x.as_ref()),
829 };
830
831 let verbose = VerboseSegment {
832 ty,
833 values: Cow::Borrowed(elements),
834 };
835
836 verbose.serialize(serializer)
837 }
838 }
839
840 impl<'de> Deserialize<'de> for AsPathSegment {
841 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
842 where
843 D: Deserializer<'de>,
844 {
845 let verbose = VerboseSegment::deserialize(deserializer)?;
846
847 let values = verbose.values.into_owned();
848 match verbose.ty {
849 SegmentType::AS_SET => Ok(AsPathSegment::AsSet(values)),
850 SegmentType::AS_SEQUENCE => Ok(AsPathSegment::AsSequence(values)),
851 SegmentType::AS_CONFED_SEQUENCE => Ok(AsPathSegment::ConfedSequence(values)),
852 SegmentType::AS_CONFED_SET => Ok(AsPathSegment::ConfedSet(values)),
853 }
854 }
855 }
856
857 fn simplified_format_len(segments: &[AsPathSegment]) -> Option<usize> {
861 let mut elements = 0;
862 let mut prev_was_sequence = false;
863 for segment in segments {
864 match segment {
865 AsPathSegment::AsSequence(seq) if !prev_was_sequence => {
866 prev_was_sequence = true;
867 elements += seq.len();
868 }
869 AsPathSegment::AsSet(_) => {
870 prev_was_sequence = false;
871 elements += 1;
872 }
873 _ => return None,
874 }
875 }
876
877 Some(elements)
878 }
879
880 impl Serialize for AsPath {
929 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
930 where
931 S: Serializer,
932 {
933 if let Some(num_elements) = simplified_format_len(&self.segments) {
934 let mut seq_serializer = serializer.serialize_seq(Some(num_elements))?;
936
937 for segment in &self.segments {
938 match segment {
939 AsPathSegment::AsSequence(elements) => {
940 elements
941 .iter()
942 .try_for_each(|x| seq_serializer.serialize_element(x))?;
943 }
944 AsPathSegment::AsSet(x) => seq_serializer.serialize_element(x)?,
945 _ => unreachable!("simplified_format_len checked for confed segments"),
946 }
947 }
948 return seq_serializer.end();
949 }
950
951 serializer.collect_seq(&self.segments)
953 }
954 }
955
956 struct AsPathVisitor;
957
958 impl<'de> Visitor<'de> for AsPathVisitor {
959 type Value = AsPath;
960
961 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
962 formatter.write_str("list of AS_PATH segments")
963 }
964
965 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
966 where
967 A: SeqAccess<'de>,
968 {
969 #[derive(Deserialize)]
972 #[serde(untagged)]
973 enum PathElement {
974 SequenceElement(Asn),
975 Set(Vec<Asn>),
976 Verbose(AsPathSegment),
977 }
978
979 let mut append_new_sequence = false;
980 let mut segments = Vec::new();
981 while let Some(element) = seq.next_element()? {
982 match element {
983 PathElement::SequenceElement(x) => {
984 if append_new_sequence {
985 append_new_sequence = false;
988 segments.push(AsPathSegment::AsSequence(Vec::new()));
989 }
990
991 if let Some(AsPathSegment::AsSequence(last_sequence)) = segments.last_mut()
992 {
993 last_sequence.push(x);
994 } else {
995 segments.push(AsPathSegment::AsSequence(vec![x]));
996 }
997 }
998 PathElement::Set(values) => {
999 segments.push(AsPathSegment::AsSet(values));
1000 }
1001 PathElement::Verbose(verbose) => {
1002 segments.push(verbose);
1003 }
1004 }
1005 }
1006
1007 Ok(AsPath { segments })
1008 }
1009 }
1010
1011 impl<'de> Deserialize<'de> for AsPath {
1012 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1013 where
1014 D: Deserializer<'de>,
1015 {
1016 deserializer.deserialize_seq(AsPathVisitor)
1017 }
1018 }
1019}
1020
1021#[cfg(test)]
1022mod tests {
1023 use crate::models::*;
1024 use itertools::Itertools;
1025 use std::collections::HashSet;
1026
1027 #[test]
1028 fn test_aspath_as4path_merge() {
1029 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
1030 let as4path = AsPath::from_sequence([2, 3, 7]);
1031 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1032 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2, 3, 7]));
1033
1034 let aspath = AsPath::from_sequence([1, 2]);
1035 let as4path = AsPath::from_sequence([2, 3, 7]);
1036 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1037 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2]));
1038
1039 let aspath = AsPath::from_sequence([1, 2]);
1041 let as4path = AsPath::from_sequence([3, 4]);
1042 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1043 assert_eq!(newpath.segments[0], AsPathSegment::sequence([3, 4]));
1044
1045 let aspath = AsPath::from_segments(vec![
1046 AsPathSegment::sequence([1, 2, 3, 5]),
1047 AsPathSegment::set([7, 8]),
1048 ]);
1049 let as4path = AsPath::from_sequence([6, 7, 8]);
1050 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1051 assert_eq!(newpath.segments.len(), 2);
1052 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 6, 7, 8]));
1053 assert_eq!(newpath.segments[1], AsPathSegment::set([7, 8]));
1054
1055 let aspath = AsPath::from_segments(vec![
1056 AsPathSegment::sequence([1, 2]),
1057 AsPathSegment::sequence([3, 5]),
1058 AsPathSegment::set([13, 14]),
1059 ]);
1060 let as4path = AsPath::from_segments(vec![
1061 AsPathSegment::sequence([8, 4, 6]),
1062 AsPathSegment::set([11, 12]),
1063 ]);
1064 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1065 assert_eq!(newpath.segments.len(), 3);
1066 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2]));
1067 assert_eq!(newpath.segments[1], AsPathSegment::set([11, 12]));
1068 assert_eq!(newpath.segments[2], AsPathSegment::set([13, 14]));
1069
1070 let aspath = AsPath::from_segments(vec![
1071 AsPathSegment::sequence([1, 2, 3]),
1072 AsPathSegment::sequence([5]),
1073 AsPathSegment::set([13, 14]),
1074 ]);
1075 let as4path = AsPath::from_segments(vec![
1076 AsPathSegment::sequence([7, 8]),
1077 AsPathSegment::set([11, 12]),
1078 ]);
1079 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1080 assert_eq!(newpath.segments.len(), 3);
1081 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 7, 8]));
1082 assert_eq!(newpath.segments[1], AsPathSegment::set([11, 12]));
1083 assert_eq!(newpath.segments[2], AsPathSegment::set([13, 14]));
1084 }
1085
1086 #[test]
1087 fn test_get_origin() {
1088 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
1089 let origin = aspath.get_origin_opt();
1090 assert_eq!(origin.unwrap(), 5);
1091
1092 let aspath = AsPath::from_segments(vec![AsPathSegment::set([1, 2, 3, 5])]);
1093 let origin = aspath.get_origin_opt();
1094 assert!(origin.is_none());
1095
1096 let aspath = AsPath::from_segments(vec![AsPathSegment::set([1])]);
1097 let origin = aspath.get_origin_opt();
1098 assert_eq!(origin.unwrap(), 1);
1099
1100 let aspath = AsPath::from_segments(vec![
1101 AsPathSegment::sequence([1, 2, 3, 5]),
1102 AsPathSegment::set([7, 8]),
1103 ]);
1104 let origins = aspath.iter_origins().map_into::<u32>().collect::<Vec<_>>();
1105 assert_eq!(origins, vec![7, 8]);
1106
1107 let aspath = AsPath::from_segments(vec![
1108 AsPathSegment::sequence([1, 2, 3, 5]),
1109 AsPathSegment::ConfedSet(vec![Asn::new_32bit(9)]),
1110 ]);
1111 let origins = aspath.iter_origins().map_into::<u32>().collect::<Vec<_>>();
1112 assert_eq!(origins, Vec::<u32>::new());
1113 }
1114
1115 #[test]
1116 fn test_get_collector() {
1117 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
1118 let collector = aspath.get_collector_opt();
1119 assert_eq!(collector.unwrap(), 1);
1120
1121 let aspath = AsPath::from_segments(vec![AsPathSegment::set([7])]);
1122 let collector = aspath.get_collector_opt();
1123 assert_eq!(collector.unwrap(), 7);
1124
1125 let aspath = AsPath::from_segments(vec![AsPathSegment::set([7, 8])]);
1126 let collector = aspath.get_collector_opt();
1127 assert!(collector.is_none());
1128 }
1129
1130 #[test]
1131 fn test_aspath_route_iter() {
1132 let path = AsPath::from_segments(vec![AsPathSegment::sequence([3, 4])]);
1133 let mut routes = HashSet::new();
1134 for route in &path {
1135 assert!(routes.insert(route));
1136 }
1137 assert_eq!(1, routes.len());
1138
1139 let path = AsPath::from_segments(vec![
1140 AsPathSegment::set([3, 4]),
1141 AsPathSegment::set([5, 6]),
1142 AsPathSegment::sequence([7, 8]),
1143 AsPathSegment::ConfedSet(vec![Asn::new_32bit(9)]),
1144 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(9)]),
1145 ]);
1146 assert_eq!(path.route_len(), 4);
1147
1148 let mut routes = HashSet::new();
1149 for route in &path {
1150 assert!(routes.insert(route));
1151 }
1152
1153 assert_eq!(routes.len(), 4);
1154 assert!(routes.contains(&vec![
1155 Asn::from(3),
1156 Asn::from(5),
1157 Asn::from(7),
1158 Asn::from(8)
1159 ]));
1160 assert!(routes.contains(&vec![
1161 Asn::from(3),
1162 Asn::from(6),
1163 Asn::from(7),
1164 Asn::from(8)
1165 ]));
1166 assert!(routes.contains(&vec![
1167 Asn::from(4),
1168 Asn::from(5),
1169 Asn::from(7),
1170 Asn::from(8)
1171 ]));
1172 assert!(routes.contains(&vec![
1173 Asn::from(4),
1174 Asn::from(6),
1175 Asn::from(7),
1176 Asn::from(8)
1177 ]));
1178 }
1179
1180 #[test]
1181 fn test_segment() {
1182 let path_segment = AsPathSegment::sequence([1, 2, 3, 4]);
1183 assert_eq!(path_segment.len(), 4);
1184
1185 let mut iter = path_segment.iter();
1187 assert_eq!(iter.next(), Some(&Asn::new_32bit(1)));
1188 assert_eq!(iter.next(), Some(&Asn::new_32bit(2)));
1189 assert_eq!(iter.next(), Some(&Asn::new_32bit(3)));
1190 assert_eq!(iter.next(), Some(&Asn::new_32bit(4)));
1191 assert_eq!(iter.next(), None);
1192
1193 let mut path_segment = AsPathSegment::sequence([1]);
1195 let mut iter_mut = path_segment.iter_mut();
1196 assert_eq!(iter_mut.next(), Some(&mut Asn::new_32bit(1)));
1197 assert_eq!(iter_mut.next(), None);
1198
1199 assert!(AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1)]).is_confed());
1201 assert!(AsPathSegment::ConfedSet(vec![Asn::new_32bit(1)]).is_confed());
1202 }
1203
1204 #[test]
1205 fn test_coalesce() {
1206 let mut a = AsPath::from_segments(vec![
1207 AsPathSegment::sequence([]),
1208 AsPathSegment::sequence([1, 2]),
1209 AsPathSegment::sequence([]),
1210 AsPathSegment::sequence([2]),
1211 AsPathSegment::set([2]),
1212 AsPathSegment::set([5, 3, 3, 2]),
1213 ]);
1214
1215 let expected = AsPath::from_segments(vec![
1216 AsPathSegment::sequence([1, 2, 2]),
1217 AsPathSegment::set([2]),
1218 AsPathSegment::set([5, 3, 3, 2]),
1219 ]);
1220
1221 a.coalesce();
1222 assert_eq!(a, expected);
1223 }
1224
1225 #[test]
1226 fn test_confed_set_dedup() {
1227 let mut path_segment = AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(1)]);
1228 path_segment.dedup();
1229 assert_eq!(
1230 path_segment,
1231 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1)])
1232 );
1233
1234 let mut path_segment = AsPathSegment::ConfedSet(vec![
1235 Asn::new_32bit(1),
1236 Asn::new_32bit(2),
1237 Asn::new_32bit(2),
1238 ]);
1239 path_segment.dedup();
1240 assert_eq!(
1241 path_segment,
1242 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)])
1243 );
1244 }
1245
1246 #[test]
1247 fn test_path_to_u32() {
1248 let path_segment = AsPathSegment::sequence([1, 2, 3, 3]);
1250 assert_eq!(path_segment.to_u32_vec_opt(false), Some(vec![1, 2, 3, 3]));
1251 assert_eq!(path_segment.to_u32_vec_opt(true), Some(vec![1, 2, 3]));
1252
1253 let path_segment = AsPathSegment::set([1, 2, 3, 3]);
1255 assert_eq!(path_segment.to_u32_vec_opt(false), None);
1256 assert_eq!(path_segment.to_u32_vec_opt(true), None);
1257
1258 let path_segment = AsPathSegment::set([1]);
1260 assert_eq!(path_segment.to_u32_vec_opt(false), Some(vec![1]));
1261 assert_eq!(path_segment.to_u32_vec_opt(true), Some(vec![1]));
1262
1263 let as_path = AsPath::from_segments(vec![
1265 AsPathSegment::set([4]),
1266 AsPathSegment::sequence([2, 3, 3]),
1267 AsPathSegment::set([1]),
1268 ]);
1269 assert_eq!(as_path.to_u32_vec_opt(false), Some(vec![4, 2, 3, 3, 1]));
1270 assert_eq!(as_path.to_u32_vec_opt(true), Some(vec![4, 2, 3, 1]));
1271
1272 let as_path = AsPath::from_segments(vec![
1274 AsPathSegment::set([4, 2]),
1275 AsPathSegment::sequence([2, 3, 3]),
1276 AsPathSegment::set([1]),
1277 ]);
1278 assert_eq!(as_path.to_u32_vec_opt(false), None);
1279 assert_eq!(as_path.to_u32_vec_opt(true), None);
1280
1281 let as_path = AsPath::from_segments(vec![]);
1285 assert_eq!(as_path.to_u32_vec_opt(false), None);
1286 assert_eq!(as_path.to_u32_vec_opt(true), None);
1287
1288 let as_path = AsPath::from_segments(vec![
1290 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)]),
1291 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(3), Asn::new_32bit(4)]),
1292 ]);
1293 assert_eq!(as_path.to_u32_vec_opt(false), None);
1294 assert_eq!(as_path.to_u32_vec_opt(true), None);
1295 }
1296
1297 #[test]
1298 fn test_as_ref() {
1299 let path_segment = AsPathSegment::sequence([1, 2]);
1300 assert_eq!(
1301 path_segment.as_ref(),
1302 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1303 );
1304
1305 let path_segment = AsPathSegment::set([1, 2]);
1306 assert_eq!(
1307 path_segment.as_ref(),
1308 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1309 );
1310
1311 let path_segment =
1312 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1), Asn::new_32bit(2)]);
1313 assert_eq!(
1314 path_segment.as_ref(),
1315 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1316 );
1317
1318 let path_segment = AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)]);
1319 assert_eq!(
1320 path_segment.as_ref(),
1321 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1322 );
1323 }
1324
1325 #[test]
1326 fn test_hashing() {
1327 let path_segment = AsPathSegment::sequence([1, 2]);
1328 let path_segment2 = AsPathSegment::sequence([1, 2]);
1329
1330 let hashset = std::iter::once(path_segment).collect::<HashSet<_>>();
1331 assert!(hashset.contains(&path_segment2));
1332 }
1333
1334 #[test]
1335 fn test_equality() {
1336 let path_segment = AsPathSegment::sequence([1, 2]);
1337 let path_segment2 = AsPathSegment::sequence([1, 2]);
1338
1339 assert_eq!(path_segment, path_segment2);
1340
1341 let path_segment = AsPathSegment::sequence([1, 2]);
1342 let path_segment2 = AsPathSegment::set([1, 2, 3]);
1343 assert_ne!(path_segment, path_segment2);
1344
1345 let path_segment = AsPathSegment::sequence((1..33).collect::<Vec<_>>());
1347 let path_segment2 = AsPathSegment::sequence((1..33).collect::<Vec<_>>());
1348 assert_eq!(path_segment, path_segment2);
1349 }
1350
1351 #[test]
1352 fn test_as_path_display() {
1353 let path = AsPath::from_segments(vec![
1354 AsPathSegment::sequence([1, 2]),
1355 AsPathSegment::set([3, 4]),
1356 AsPathSegment::sequence([5, 6]),
1357 AsPathSegment::ConfedSet(vec![Asn::new_32bit(7)]),
1358 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(8)]),
1359 ]);
1360
1361 assert_eq!(path.to_string(), "1 2 {3,4} 5 6 {7} 8");
1362 }
1363}