1use crate::models::*;
2use itertools::Itertools;
3use smallvec::SmallVec;
4use std::borrow::Cow;
5use std::fmt::{Display, Formatter};
6use std::hash::{Hash, Hasher};
7use std::iter::FromIterator;
8use std::marker::PhantomData;
9use std::mem::discriminant;
10
11#[derive(Debug, Clone)]
17pub enum AsPathSegment {
18 AsSequence(SmallVec<[Asn; 6]>),
20 AsSet(SmallVec<[Asn; 6]>),
22 ConfedSequence(SmallVec<[Asn; 6]>),
24 ConfedSet(SmallVec<[Asn; 6]>),
26}
27
28impl AsPathSegment {
29 pub fn sequence<S: AsRef<[u32]>>(seq: S) -> Self {
31 AsPathSegment::AsSequence(seq.as_ref().iter().copied().map_into().collect())
32 }
33
34 pub fn set<S: AsRef<[u32]>>(seq: S) -> Self {
36 AsPathSegment::AsSet(seq.as_ref().iter().copied().map_into().collect())
37 }
38
39 pub fn route_len(&self) -> usize {
42 match self {
43 AsPathSegment::AsSequence(v) => v.len(),
44 AsPathSegment::AsSet(_) => 1,
45 AsPathSegment::ConfedSequence(_) | AsPathSegment::ConfedSet(_) => 0,
46 }
47 }
48
49 pub fn len(&self) -> usize {
52 self.as_ref().len()
53 }
54
55 pub fn is_empty(&self) -> bool {
57 self.as_ref().is_empty()
58 }
59
60 pub fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter {
62 self.into_iter()
63 }
64
65 pub fn iter_mut(&mut self) -> <&'_ mut Self as IntoIterator>::IntoIter {
67 self.into_iter()
68 }
69
70 pub fn is_confed(&self) -> bool {
75 matches!(
76 self,
77 AsPathSegment::ConfedSequence(_) | AsPathSegment::ConfedSet(_)
78 )
79 }
80
81 fn merge_in_place(&mut self, other: &mut Self) -> bool {
85 use AsPathSegment::*;
86
87 match (self, other) {
88 (AsSequence(x), AsSequence(y)) | (ConfedSequence(x), ConfedSequence(y)) => {
89 x.extend_from_slice(y);
90 true
91 }
92 (x @ (AsSequence(_) | ConfedSequence(_)), y) if x.is_empty() => {
93 std::mem::swap(x, y);
94 true
95 }
96 (_, AsSequence(y) | ConfedSequence(y)) if y.is_empty() => true,
97 _ => false,
98 }
99 }
100
101 fn dedup_merge_in_place(&mut self, other: &mut Self) -> bool {
106 use AsPathSegment::*;
107
108 other.dedup();
109 match (self, other) {
110 (AsSequence(x), AsSequence(y)) | (ConfedSequence(x), ConfedSequence(y)) => {
111 x.extend_from_slice(y);
112 x.dedup();
113 true
114 }
115 (x @ (AsSequence(_) | ConfedSequence(_)), y) if x.is_empty() => {
116 std::mem::swap(x, y);
117 true
118 }
119 (_, AsSequence(y) | ConfedSequence(y)) if y.is_empty() => true,
120 _ => false,
121 }
122 }
123
124 fn dedup(&mut self) {
129 match self {
130 AsPathSegment::AsSequence(x) | AsPathSegment::ConfedSequence(x) => x.dedup(),
131 AsPathSegment::AsSet(x) => {
132 x.sort_unstable();
133 x.dedup();
134 if x.len() == 1 {
135 *self = AsPathSegment::AsSequence(std::mem::take(x));
136 }
137 }
138 AsPathSegment::ConfedSet(x) => {
139 x.sort_unstable();
140 x.dedup();
141 if x.len() == 1 {
142 *self = AsPathSegment::ConfedSequence(std::mem::take(x));
143 }
144 }
145 }
146 }
147
148 pub fn to_u32_vec_opt(&self, dedup: bool) -> Option<Vec<u32>> {
149 match self {
150 AsPathSegment::AsSequence(v) => {
151 let mut p: Vec<u32> = v.iter().map(|asn| (*asn).into()).collect();
152 if dedup {
153 p.dedup();
154 }
155 Some(p)
156 }
157 AsPathSegment::AsSet(v) => {
158 if v.len() == 1 {
159 Some(vec![v[0].into()])
162 } else {
163 None
164 }
165 }
166 _ => None,
167 }
168 }
169}
170
171impl IntoIterator for AsPathSegment {
172 type Item = Asn;
173 type IntoIter = smallvec::IntoIter<[Asn; 6]>;
174
175 fn into_iter(self) -> Self::IntoIter {
176 let (AsPathSegment::AsSequence(x)
177 | AsPathSegment::AsSet(x)
178 | AsPathSegment::ConfedSequence(x)
179 | AsPathSegment::ConfedSet(x)) = self;
180 x.into_iter()
181 }
182}
183
184impl<'a> IntoIterator for &'a AsPathSegment {
185 type Item = &'a Asn;
186 type IntoIter = std::slice::Iter<'a, Asn>;
187
188 fn into_iter(self) -> Self::IntoIter {
189 let (AsPathSegment::AsSequence(x)
190 | AsPathSegment::AsSet(x)
191 | AsPathSegment::ConfedSequence(x)
192 | AsPathSegment::ConfedSet(x)) = self;
193 x.iter()
194 }
195}
196
197impl<'a> IntoIterator for &'a mut AsPathSegment {
198 type Item = &'a mut Asn;
199 type IntoIter = std::slice::IterMut<'a, Asn>;
200
201 fn into_iter(self) -> Self::IntoIter {
202 let (AsPathSegment::AsSequence(x)
203 | AsPathSegment::AsSet(x)
204 | AsPathSegment::ConfedSequence(x)
205 | AsPathSegment::ConfedSet(x)) = self;
206 x.iter_mut()
207 }
208}
209
210impl AsRef<[Asn]> for AsPathSegment {
211 fn as_ref(&self) -> &[Asn] {
212 let (AsPathSegment::AsSequence(x)
213 | AsPathSegment::AsSet(x)
214 | AsPathSegment::ConfedSequence(x)
215 | AsPathSegment::ConfedSet(x)) = self;
216 x
217 }
218}
219
220impl Hash for AsPathSegment {
221 fn hash<H: Hasher>(&self, state: &mut H) {
222 discriminant(self).hash(state);
224
225 let set = match self {
226 AsPathSegment::AsSequence(x) | AsPathSegment::ConfedSequence(x) => {
227 return x.hash(state)
228 }
229 AsPathSegment::AsSet(x) | AsPathSegment::ConfedSet(x) => x,
230 };
231
232 if set.len() <= 32 {
234 let mut buffer = [Asn::new_32bit(0); 32];
235 set.iter()
236 .zip(&mut buffer)
237 .for_each(|(asn, buffer)| *buffer = *asn);
238
239 let slice = &mut buffer[..set.len()];
240 slice.sort_unstable();
241 Asn::hash_slice(slice, state);
242 return;
243 }
244
245 set.iter().sorted().for_each(|x| x.hash(state));
247 }
248}
249
250impl PartialEq for AsPathSegment {
265 fn eq(&self, other: &Self) -> bool {
266 let (x, y) = match (self, other) {
267 (AsPathSegment::AsSequence(x), AsPathSegment::AsSequence(y))
268 | (AsPathSegment::ConfedSequence(x), AsPathSegment::ConfedSequence(y)) => {
269 return x == y
270 }
271 (AsPathSegment::AsSet(x), AsPathSegment::AsSet(y))
272 | (AsPathSegment::ConfedSet(x), AsPathSegment::ConfedSet(y)) => (x, y),
273 _ => return false,
274 };
275
276 if x.len() != y.len() {
278 return false;
279 } else if x == y {
280 return true;
281 }
282
283 if x.len() <= 32 {
284 let mut x_buffer = [Asn::new_32bit(0); 32];
285 let mut y_buffer = [Asn::new_32bit(0); 32];
286 x.iter()
287 .zip(&mut x_buffer)
288 .for_each(|(asn, buffer)| *buffer = *asn);
289 y.iter()
290 .zip(&mut y_buffer)
291 .for_each(|(asn, buffer)| *buffer = *asn);
292
293 x_buffer[..x.len()].sort_unstable();
294 y_buffer[..y.len()].sort_unstable();
295 return x_buffer[..x.len()] == y_buffer[..y.len()];
296 }
297
298 x.iter()
299 .sorted()
300 .zip(y.iter().sorted())
301 .all(|(a, b)| a == b)
302 }
303}
304
305impl Eq for AsPathSegment {}
306
307struct AsPathNumberedRouteIter<'a> {
311 path: &'a [AsPathSegment],
312 index: usize,
313 route_num: u64,
314}
315
316impl Iterator for AsPathNumberedRouteIter<'_> {
317 type Item = Asn;
318
319 fn next(&mut self) -> Option<Self::Item> {
320 loop {
321 match self.path.first()? {
322 AsPathSegment::AsSequence(x) => match x.get(self.index) {
323 None => {
324 self.index = 0;
325 self.path = &self.path[1..];
326 }
327 Some(asn) => {
328 self.index += 1;
329 return Some(*asn);
330 }
331 },
332 AsPathSegment::AsSet(x) => {
333 self.path = &self.path[1..];
334 if x.is_empty() {
335 return Some(Asn::RESERVED);
336 }
337
338 let asn = x[(self.route_num % x.len() as u64) as usize];
339 self.route_num /= x.len() as u64;
340 return Some(asn);
341 }
342 _ => self.path = &self.path[1..],
343 }
344 }
345 }
346}
347
348pub struct AsPathRouteIter<'a, D> {
349 path: Cow<'a, [AsPathSegment]>,
350 route_num: u64,
351 total_routes: u64,
352 _phantom: PhantomData<D>,
353}
354
355impl<D> Iterator for AsPathRouteIter<'_, D>
356where
357 D: FromIterator<Asn>,
358{
359 type Item = D;
360
361 fn next(&mut self) -> Option<Self::Item> {
362 if self.route_num >= self.total_routes {
363 return None;
364 }
365
366 if self.route_num == 0 && self.path.len() == 1 {
368 if let AsPathSegment::AsSequence(sequence) = &self.path[0] {
369 let route = D::from_iter(sequence.iter().copied());
370 self.route_num += 1;
371 return Some(route);
372 }
373 }
374
375 let route_asn_iter = AsPathNumberedRouteIter {
376 path: self.path.as_ref(),
377 index: 0,
378 route_num: self.route_num,
379 };
380
381 self.route_num += 1;
382 Some(D::from_iter(route_asn_iter))
383 }
384}
385
386#[derive(Debug, PartialEq, Clone, Eq, Default, Hash)]
391pub struct AsPath {
392 pub segments: SmallVec<[AsPathSegment; 1]>,
394}
395
396pub type SegmentIter<'a> = std::slice::Iter<'a, AsPathSegment>;
399pub type SegmentIterMut<'a> = std::slice::IterMut<'a, AsPathSegment>;
400pub type SegmentIntoIter = smallvec::IntoIter<[AsPathSegment; 1]>;
401
402impl AsPath {
403 pub fn new() -> AsPath {
404 AsPath {
405 segments: SmallVec::new(),
406 }
407 }
408
409 pub fn from_sequence<S: AsRef<[u32]>>(seq: S) -> Self {
411 let segment = AsPathSegment::AsSequence(seq.as_ref().iter().copied().map_into().collect());
412
413 AsPath {
414 segments: SmallVec::from_buf([segment]),
415 }
416 }
417
418 pub fn from_segments<S: Into<SmallVec<[AsPathSegment; 1]>>>(segments: S) -> AsPath {
419 AsPath {
420 segments: segments.into(),
421 }
422 }
423
424 pub fn append_segment(&mut self, segment: AsPathSegment) {
427 self.segments.push(segment);
428 }
429
430 pub fn is_empty(&self) -> bool {
433 self.segments.is_empty()
434 }
435
436 pub fn route_len(&self) -> usize {
443 self.segments.iter().map(AsPathSegment::route_len).sum()
444 }
445
446 pub fn len(&self) -> usize {
449 self.segments.len()
450 }
451
452 pub fn num_route_variations(&self) -> u64 {
455 let mut variations: u64 = 1;
456
457 for segment in &self.segments {
458 if let AsPathSegment::AsSet(x) = segment {
459 variations *= x.len() as u64;
460 }
461 }
462
463 variations
464 }
465
466 pub fn contains_asn(&self, x: Asn) -> bool {
468 self.iter_segments().flatten().contains(&x)
469 }
470
471 pub fn coalesce(&mut self) {
503 let mut end_index = 0;
504 let mut scan_index = 1;
505
506 while scan_index < self.segments.len() {
507 let (a, b) = self.segments.split_at_mut(scan_index);
508 if !AsPathSegment::merge_in_place(&mut a[end_index], &mut b[0]) {
509 end_index += 1;
510 self.segments.swap(end_index, scan_index);
511 }
512 scan_index += 1;
513 }
514
515 self.segments.truncate(end_index + 1);
516 }
517
518 pub fn dedup_coalesce(&mut self) {
551 if !self.segments.is_empty() {
552 self.segments[0].dedup();
553 }
554 let mut end_index = 0;
555 let mut scan_index = 1;
556
557 while scan_index < self.segments.len() {
558 let (a, b) = self.segments.split_at_mut(scan_index);
559 if !AsPathSegment::dedup_merge_in_place(&mut a[end_index], &mut b[0]) {
560 end_index += 1;
561 self.segments.swap(end_index, scan_index);
562 }
563 scan_index += 1;
564 }
565
566 self.segments.truncate(end_index + 1);
567 }
568
569 pub fn has_equivalent_routing(&self, other: &Self) -> bool {
574 let mut a = self.to_owned();
575 let mut b = other.to_owned();
576
577 a.dedup_coalesce();
578 b.dedup_coalesce();
579
580 a == b
581 }
582
583 pub fn required_asn_length(&self) -> AsnLength {
585 self.iter_segments().flatten().map(Asn::required_len).fold(
586 AsnLength::Bits16,
587 |a, b| match (a, b) {
588 (AsnLength::Bits16, AsnLength::Bits16) => AsnLength::Bits16,
589 _ => AsnLength::Bits32,
590 },
591 )
592 }
593
594 pub fn iter_segments(&self) -> SegmentIter<'_> {
595 self.segments.iter()
596 }
597
598 pub fn iter_segments_mut(&mut self) -> SegmentIterMut<'_> {
599 self.segments.iter_mut()
600 }
601
602 pub fn into_segments_iter(self) -> SegmentIntoIter {
603 self.segments.into_iter()
604 }
605
606 pub fn iter_routes<D>(&self) -> AsPathRouteIter<'_, D>
608 where
609 D: FromIterator<Asn>,
610 {
611 AsPathRouteIter {
612 path: Cow::Borrowed(&self.segments),
613 route_num: 0,
614 total_routes: self.num_route_variations(),
615 _phantom: PhantomData,
616 }
617 }
618
619 pub fn merge_aspath_as4path(aspath: &AsPath, as4path: &AsPath) -> AsPath {
641 if aspath.route_len() < as4path.route_len() {
642 return aspath.clone();
644 }
645
646 let mut as4iter = as4path.segments.iter();
647 let mut new_segs: Vec<AsPathSegment> = vec![];
648
649 for seg in &aspath.segments {
650 match as4iter.next() {
651 None => {
652 new_segs.push(seg.clone());
653 }
654 Some(as4seg_unwrapped) => {
655 if let (AsPathSegment::AsSequence(seq), AsPathSegment::AsSequence(seq4)) =
656 (seg, as4seg_unwrapped)
657 {
658 let diff_len = seq.len() as i32 - seq4.len() as i32;
659 match diff_len {
660 d if d > 0 => {
661 let mut new_seq: Vec<Asn> = vec![];
664 new_seq.extend(seq.iter().take(d as usize));
665 new_seq.extend(seq4);
666 new_segs.push(AsPathSegment::AsSequence(new_seq.into()));
667 }
668 d if d < 0 => {
669 new_segs.push(AsPathSegment::AsSequence(seq.clone()));
670 }
671 _ => {
672 new_segs.push(AsPathSegment::AsSequence(seq4.clone()));
673 }
674 }
675 } else {
676 new_segs.push(as4seg_unwrapped.clone());
677 }
678 }
679 };
680 }
681
682 AsPath {
683 segments: new_segs.into(),
684 }
685 }
686
687 pub fn iter_origins(&self) -> impl '_ + Iterator<Item = Asn> {
690 let origin_slice = match self.segments.last() {
691 Some(AsPathSegment::AsSequence(v)) => v.last().map(std::slice::from_ref).unwrap_or(&[]),
692 Some(AsPathSegment::AsSet(v)) => v.as_ref(),
693 _ => &[],
694 };
695
696 origin_slice.iter().copied()
697 }
698
699 pub fn get_origin_opt(&self) -> Option<Asn> {
703 match self.segments.last() {
704 Some(AsPathSegment::AsSequence(v)) => v.last().copied(),
705 Some(AsPathSegment::AsSet(v)) if v.len() == 1 => Some(v[0]),
706 _ => None,
707 }
708 }
709
710 pub fn get_collector_opt(&self) -> Option<Asn> {
713 match self.segments.first() {
714 Some(AsPathSegment::AsSequence(v)) => v.first().copied(),
715 Some(AsPathSegment::AsSet(v)) if v.len() == 1 => Some(v[0]),
716 _ => None,
717 }
718 }
719
720 pub fn to_u32_vec_opt(&self, dedup: bool) -> Option<Vec<u32>> {
721 let mut path = vec![];
722
723 for seg in self.segments.iter().rev() {
725 let p = seg.to_u32_vec_opt(dedup)?;
728 path.extend(p.iter().rev());
730 }
731
732 match path.is_empty() {
733 true => {
734 None
736 }
737 false => {
738 path.reverse();
740 Some(path)
741 }
742 }
743 }
744}
745
746impl<'a> IntoIterator for &'a AsPath {
748 type Item = Vec<Asn>;
749 type IntoIter = AsPathRouteIter<'a, Vec<Asn>>;
750
751 fn into_iter(self) -> Self::IntoIter {
752 self.iter_routes()
753 }
754}
755
756impl IntoIterator for AsPath {
758 type Item = Vec<Asn>;
759 type IntoIter = AsPathRouteIter<'static, Vec<Asn>>;
760
761 fn into_iter(self) -> Self::IntoIter {
762 AsPathRouteIter {
763 total_routes: self.num_route_variations(),
764 path: Cow::Owned(self.segments.into_vec()),
765 route_num: 0,
766 _phantom: PhantomData,
767 }
768 }
769}
770
771impl Display for AsPath {
772 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
773 for (index, segment) in self.iter_segments().enumerate() {
774 if index != 0 {
775 write!(f, " ")?;
776 }
777
778 match segment {
779 AsPathSegment::AsSequence(v) | AsPathSegment::ConfedSequence(v) => {
780 let mut asn_iter = v.iter();
781 if let Some(first_element) = asn_iter.next() {
782 write!(f, "{first_element}")?;
783
784 for asn in asn_iter {
785 write!(f, " {asn}")?;
786 }
787 }
788 }
789 AsPathSegment::AsSet(v) | AsPathSegment::ConfedSet(v) => {
790 write!(f, "{{")?;
791 let mut asn_iter = v.iter();
792 if let Some(first_element) = asn_iter.next() {
793 write!(f, "{first_element}")?;
794
795 for asn in asn_iter {
796 write!(f, ",{asn}")?;
797 }
798 }
799 write!(f, "}}")?;
800 }
801 }
802 }
803
804 Ok(())
805 }
806}
807
808#[cfg(feature = "serde")]
809mod serde_impl {
810 use super::*;
811 use serde::de::{SeqAccess, Visitor};
812 use serde::ser::SerializeSeq;
813 use serde::{Deserialize, Deserializer, Serialize, Serializer};
814 use std::borrow::Cow;
815
816 #[allow(non_camel_case_types)]
820 #[derive(Serialize, Deserialize)]
821 enum SegmentType {
822 AS_SET,
823 AS_SEQUENCE,
824 AS_CONFED_SEQUENCE,
825 AS_CONFED_SET,
826 }
827
828 #[derive(Serialize, Deserialize)]
829 struct VerboseSegment<'s> {
830 ty: SegmentType,
831 values: Cow<'s, [Asn]>,
832 }
833
834 impl Serialize for AsPathSegment {
835 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
836 where
837 S: Serializer,
838 {
839 let (ty, elements) = match self {
840 AsPathSegment::AsSequence(x) => (SegmentType::AS_SEQUENCE, x.as_ref()),
841 AsPathSegment::AsSet(x) => (SegmentType::AS_SET, x.as_ref()),
842 AsPathSegment::ConfedSequence(x) => (SegmentType::AS_CONFED_SEQUENCE, x.as_ref()),
843 AsPathSegment::ConfedSet(x) => (SegmentType::AS_CONFED_SET, x.as_ref()),
844 };
845
846 let verbose = VerboseSegment {
847 ty,
848 values: Cow::Borrowed(elements),
849 };
850
851 verbose.serialize(serializer)
852 }
853 }
854
855 impl<'de> Deserialize<'de> for AsPathSegment {
856 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
857 where
858 D: Deserializer<'de>,
859 {
860 let verbose = VerboseSegment::deserialize(deserializer)?;
861
862 let values: SmallVec<[Asn; 6]> = verbose.values.into_owned().into();
863 match verbose.ty {
864 SegmentType::AS_SET => Ok(AsPathSegment::AsSet(values)),
865 SegmentType::AS_SEQUENCE => Ok(AsPathSegment::AsSequence(values)),
866 SegmentType::AS_CONFED_SEQUENCE => Ok(AsPathSegment::ConfedSequence(values)),
867 SegmentType::AS_CONFED_SET => Ok(AsPathSegment::ConfedSet(values)),
868 }
869 }
870 }
871
872 fn simplified_format_len(segments: &[AsPathSegment]) -> Option<usize> {
876 let mut elements = 0;
877 let mut prev_was_sequence = false;
878 for segment in segments {
879 match segment {
880 AsPathSegment::AsSequence(seq) if !prev_was_sequence => {
881 prev_was_sequence = true;
882 elements += seq.len();
883 }
884 AsPathSegment::AsSet(_) => {
885 prev_was_sequence = false;
886 elements += 1;
887 }
888 _ => return None,
889 }
890 }
891
892 Some(elements)
893 }
894
895 impl Serialize for AsPath {
944 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
945 where
946 S: Serializer,
947 {
948 if let Some(num_elements) = simplified_format_len(&self.segments) {
949 let mut seq_serializer = serializer.serialize_seq(Some(num_elements))?;
951
952 for segment in &self.segments {
953 match segment {
954 AsPathSegment::AsSequence(elements) => {
955 elements
956 .iter()
957 .try_for_each(|x| seq_serializer.serialize_element(x))?;
958 }
959 AsPathSegment::AsSet(x) => seq_serializer.serialize_element(x)?,
960 _ => unreachable!("simplified_format_len checked for confed segments"),
961 }
962 }
963 return seq_serializer.end();
964 }
965
966 serializer.collect_seq(&self.segments)
968 }
969 }
970
971 struct AsPathVisitor;
972
973 impl<'de> Visitor<'de> for AsPathVisitor {
974 type Value = AsPath;
975
976 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
977 formatter.write_str("list of AS_PATH segments")
978 }
979
980 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
981 where
982 A: SeqAccess<'de>,
983 {
984 #[derive(Deserialize)]
987 #[serde(untagged)]
988 enum PathElement {
989 SequenceElement(Asn),
990 Set(Vec<Asn>),
991 Verbose(AsPathSegment),
992 }
993
994 let mut append_new_sequence = false;
995 let mut segments: SmallVec<[AsPathSegment; 1]> = SmallVec::new();
996 while let Some(element) = seq.next_element()? {
997 match element {
998 PathElement::SequenceElement(x) => {
999 if append_new_sequence {
1000 append_new_sequence = false;
1003 segments.push(AsPathSegment::AsSequence(SmallVec::new()));
1004 }
1005
1006 if let Some(AsPathSegment::AsSequence(last_sequence)) = segments.last_mut()
1007 {
1008 last_sequence.push(x);
1009 } else {
1010 let mut new_seq: SmallVec<[Asn; 6]> = SmallVec::new();
1011 new_seq.push(x);
1012 segments.push(AsPathSegment::AsSequence(new_seq));
1013 }
1014 }
1015 PathElement::Set(values) => {
1016 segments.push(AsPathSegment::AsSet(values.into()));
1017 }
1018 PathElement::Verbose(verbose) => {
1019 segments.push(verbose);
1020 }
1021 }
1022 }
1023
1024 Ok(AsPath { segments })
1025 }
1026 }
1027
1028 impl<'de> Deserialize<'de> for AsPath {
1029 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1030 where
1031 D: Deserializer<'de>,
1032 {
1033 deserializer.deserialize_seq(AsPathVisitor)
1034 }
1035 }
1036}
1037
1038#[cfg(test)]
1039mod tests {
1040 use crate::models::*;
1041 use itertools::Itertools;
1042 use std::collections::HashSet;
1043
1044 #[test]
1045 fn test_aspath_as4path_merge() {
1046 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
1047 let as4path = AsPath::from_sequence([2, 3, 7]);
1048 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1049 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2, 3, 7]));
1050
1051 let aspath = AsPath::from_sequence([1, 2]);
1052 let as4path = AsPath::from_sequence([2, 3, 7]);
1053 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1054 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2]));
1055
1056 let aspath = AsPath::from_sequence([1, 2]);
1058 let as4path = AsPath::from_sequence([3, 4]);
1059 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1060 assert_eq!(newpath.segments[0], AsPathSegment::sequence([3, 4]));
1061
1062 let aspath = AsPath::from_segments(vec![
1063 AsPathSegment::sequence([1, 2, 3, 5]),
1064 AsPathSegment::set([7, 8]),
1065 ]);
1066 let as4path = AsPath::from_sequence([6, 7, 8]);
1067 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1068 assert_eq!(newpath.segments.len(), 2);
1069 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 6, 7, 8]));
1070 assert_eq!(newpath.segments[1], AsPathSegment::set([7, 8]));
1071
1072 let aspath = AsPath::from_segments(vec![
1073 AsPathSegment::sequence([1, 2]),
1074 AsPathSegment::sequence([3, 5]),
1075 AsPathSegment::set([13, 14]),
1076 ]);
1077 let as4path = AsPath::from_segments(vec![
1078 AsPathSegment::sequence([8, 4, 6]),
1079 AsPathSegment::set([11, 12]),
1080 ]);
1081 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1082 assert_eq!(newpath.segments.len(), 3);
1083 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2]));
1084 assert_eq!(newpath.segments[1], AsPathSegment::set([11, 12]));
1085 assert_eq!(newpath.segments[2], AsPathSegment::set([13, 14]));
1086
1087 let aspath = AsPath::from_segments(vec![
1088 AsPathSegment::sequence([1, 2, 3]),
1089 AsPathSegment::sequence([5]),
1090 AsPathSegment::set([13, 14]),
1091 ]);
1092 let as4path = AsPath::from_segments(vec![
1093 AsPathSegment::sequence([7, 8]),
1094 AsPathSegment::set([11, 12]),
1095 ]);
1096 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1097 assert_eq!(newpath.segments.len(), 3);
1098 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 7, 8]));
1099 assert_eq!(newpath.segments[1], AsPathSegment::set([11, 12]));
1100 assert_eq!(newpath.segments[2], AsPathSegment::set([13, 14]));
1101 }
1102
1103 #[test]
1104 fn test_get_origin() {
1105 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
1106 let origin = aspath.get_origin_opt();
1107 assert_eq!(origin.unwrap(), 5);
1108
1109 let aspath = AsPath::from_segments(vec![AsPathSegment::set([1, 2, 3, 5])]);
1110 let origin = aspath.get_origin_opt();
1111 assert!(origin.is_none());
1112
1113 let aspath = AsPath::from_segments(vec![AsPathSegment::set([1])]);
1114 let origin = aspath.get_origin_opt();
1115 assert_eq!(origin.unwrap(), 1);
1116
1117 let aspath = AsPath::from_segments(vec![
1118 AsPathSegment::sequence([1, 2, 3, 5]),
1119 AsPathSegment::set([7, 8]),
1120 ]);
1121 let origins = aspath.iter_origins().map_into::<u32>().collect::<Vec<_>>();
1122 assert_eq!(origins, vec![7, 8]);
1123
1124 let aspath = AsPath::from_segments(vec![
1125 AsPathSegment::sequence([1, 2, 3, 5]),
1126 AsPathSegment::ConfedSet(vec![Asn::new_32bit(9)].into()),
1127 ]);
1128 let origins = aspath.iter_origins().map_into::<u32>().collect::<Vec<_>>();
1129 assert_eq!(origins, Vec::<u32>::new());
1130 }
1131
1132 #[test]
1133 fn test_get_collector() {
1134 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
1135 let collector = aspath.get_collector_opt();
1136 assert_eq!(collector.unwrap(), 1);
1137
1138 let aspath = AsPath::from_segments(vec![AsPathSegment::set([7])]);
1139 let collector = aspath.get_collector_opt();
1140 assert_eq!(collector.unwrap(), 7);
1141
1142 let aspath = AsPath::from_segments(vec![AsPathSegment::set([7, 8])]);
1143 let collector = aspath.get_collector_opt();
1144 assert!(collector.is_none());
1145 }
1146
1147 #[test]
1148 fn test_aspath_route_iter() {
1149 let path = AsPath::from_segments(vec![AsPathSegment::sequence([3, 4])]);
1150 let mut routes = HashSet::new();
1151 for route in &path {
1152 assert!(routes.insert(route));
1153 }
1154 assert_eq!(1, routes.len());
1155
1156 let path = AsPath::from_segments(vec![
1157 AsPathSegment::set([3, 4]),
1158 AsPathSegment::set([5, 6]),
1159 AsPathSegment::sequence([7, 8]),
1160 AsPathSegment::ConfedSet(vec![Asn::new_32bit(9)].into()),
1161 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(9)].into()),
1162 ]);
1163 assert_eq!(path.route_len(), 4);
1164
1165 let mut routes = HashSet::new();
1166 for route in &path {
1167 assert!(routes.insert(route));
1168 }
1169
1170 assert_eq!(routes.len(), 4);
1171 assert!(routes.contains(&vec![
1172 Asn::from(3),
1173 Asn::from(5),
1174 Asn::from(7),
1175 Asn::from(8)
1176 ]));
1177 assert!(routes.contains(&vec![
1178 Asn::from(3),
1179 Asn::from(6),
1180 Asn::from(7),
1181 Asn::from(8)
1182 ]));
1183 assert!(routes.contains(&vec![
1184 Asn::from(4),
1185 Asn::from(5),
1186 Asn::from(7),
1187 Asn::from(8)
1188 ]));
1189 assert!(routes.contains(&vec![
1190 Asn::from(4),
1191 Asn::from(6),
1192 Asn::from(7),
1193 Asn::from(8)
1194 ]));
1195 }
1196
1197 #[test]
1198 fn test_segment() {
1199 let path_segment = AsPathSegment::sequence([1, 2, 3, 4]);
1200 assert_eq!(path_segment.len(), 4);
1201
1202 let mut iter = path_segment.iter();
1204 assert_eq!(iter.next(), Some(&Asn::new_32bit(1)));
1205 assert_eq!(iter.next(), Some(&Asn::new_32bit(2)));
1206 assert_eq!(iter.next(), Some(&Asn::new_32bit(3)));
1207 assert_eq!(iter.next(), Some(&Asn::new_32bit(4)));
1208 assert_eq!(iter.next(), None);
1209
1210 let mut path_segment = AsPathSegment::sequence([1]);
1212 let mut iter_mut = path_segment.iter_mut();
1213 assert_eq!(iter_mut.next(), Some(&mut Asn::new_32bit(1)));
1214 assert_eq!(iter_mut.next(), None);
1215
1216 assert!(AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1)].into()).is_confed());
1218 assert!(AsPathSegment::ConfedSet(vec![Asn::new_32bit(1)].into()).is_confed());
1219 }
1220
1221 #[test]
1222 fn test_coalesce() {
1223 let mut a = AsPath::from_segments(vec![
1224 AsPathSegment::sequence([]),
1225 AsPathSegment::sequence([1, 2]),
1226 AsPathSegment::sequence([]),
1227 AsPathSegment::sequence([2]),
1228 AsPathSegment::set([2]),
1229 AsPathSegment::set([5, 3, 3, 2]),
1230 ]);
1231
1232 let expected = AsPath::from_segments(vec![
1233 AsPathSegment::sequence([1, 2, 2]),
1234 AsPathSegment::set([2]),
1235 AsPathSegment::set([5, 3, 3, 2]),
1236 ]);
1237
1238 a.coalesce();
1239 assert_eq!(a, expected);
1240 }
1241
1242 #[test]
1243 fn test_confed_set_dedup() {
1244 let mut path_segment =
1245 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(1)].into());
1246 path_segment.dedup();
1247 assert_eq!(
1248 path_segment,
1249 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1)].into())
1250 );
1251
1252 let mut path_segment = AsPathSegment::ConfedSet(
1253 vec![Asn::new_32bit(1), Asn::new_32bit(2), Asn::new_32bit(2)].into(),
1254 );
1255 path_segment.dedup();
1256 assert_eq!(
1257 path_segment,
1258 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into())
1259 );
1260 }
1261
1262 #[test]
1263 fn test_path_to_u32() {
1264 let path_segment = AsPathSegment::sequence([1, 2, 3, 3]);
1266 assert_eq!(path_segment.to_u32_vec_opt(false), Some(vec![1, 2, 3, 3]));
1267 assert_eq!(path_segment.to_u32_vec_opt(true), Some(vec![1, 2, 3]));
1268
1269 let path_segment = AsPathSegment::set([1, 2, 3, 3]);
1271 assert_eq!(path_segment.to_u32_vec_opt(false), None);
1272 assert_eq!(path_segment.to_u32_vec_opt(true), None);
1273
1274 let path_segment = AsPathSegment::set([1]);
1276 assert_eq!(path_segment.to_u32_vec_opt(false), Some(vec![1]));
1277 assert_eq!(path_segment.to_u32_vec_opt(true), Some(vec![1]));
1278
1279 let as_path = AsPath::from_segments(vec![
1281 AsPathSegment::set([4]),
1282 AsPathSegment::sequence([2, 3, 3]),
1283 AsPathSegment::set([1]),
1284 ]);
1285 assert_eq!(as_path.to_u32_vec_opt(false), Some(vec![4, 2, 3, 3, 1]));
1286 assert_eq!(as_path.to_u32_vec_opt(true), Some(vec![4, 2, 3, 1]));
1287
1288 let as_path = AsPath::from_segments(vec![
1290 AsPathSegment::set([4, 2]),
1291 AsPathSegment::sequence([2, 3, 3]),
1292 AsPathSegment::set([1]),
1293 ]);
1294 assert_eq!(as_path.to_u32_vec_opt(false), None);
1295 assert_eq!(as_path.to_u32_vec_opt(true), None);
1296
1297 let as_path = AsPath::from_segments(vec![]);
1301 assert_eq!(as_path.to_u32_vec_opt(false), None);
1302 assert_eq!(as_path.to_u32_vec_opt(true), None);
1303
1304 let as_path = AsPath::from_segments(vec![
1306 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into()),
1307 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(3), Asn::new_32bit(4)].into()),
1308 ]);
1309 assert_eq!(as_path.to_u32_vec_opt(false), None);
1310 assert_eq!(as_path.to_u32_vec_opt(true), None);
1311 }
1312
1313 #[test]
1314 fn test_as_ref() {
1315 let path_segment = AsPathSegment::sequence([1, 2]);
1316 assert_eq!(
1317 path_segment.as_ref(),
1318 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1319 );
1320
1321 let path_segment = AsPathSegment::set([1, 2]);
1322 assert_eq!(
1323 path_segment.as_ref(),
1324 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1325 );
1326
1327 let path_segment =
1328 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into());
1329 assert_eq!(
1330 path_segment.as_ref(),
1331 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1332 );
1333
1334 let path_segment =
1335 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into());
1336 assert_eq!(
1337 path_segment.as_ref(),
1338 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1339 );
1340 }
1341
1342 #[test]
1343 fn test_hashing() {
1344 let path_segment = AsPathSegment::sequence([1, 2]);
1345 let path_segment2 = AsPathSegment::sequence([1, 2]);
1346
1347 let hashset = std::iter::once(path_segment).collect::<HashSet<_>>();
1348 assert!(hashset.contains(&path_segment2));
1349 }
1350
1351 #[test]
1352 fn test_equality() {
1353 let path_segment = AsPathSegment::sequence([1, 2]);
1354 let path_segment2 = AsPathSegment::sequence([1, 2]);
1355
1356 assert_eq!(path_segment, path_segment2);
1357
1358 let path_segment = AsPathSegment::sequence([1, 2]);
1359 let path_segment2 = AsPathSegment::set([1, 2, 3]);
1360 assert_ne!(path_segment, path_segment2);
1361
1362 let path_segment = AsPathSegment::sequence((1..33).collect::<Vec<_>>());
1364 let path_segment2 = AsPathSegment::sequence((1..33).collect::<Vec<_>>());
1365 assert_eq!(path_segment, path_segment2);
1366 }
1367
1368 #[test]
1369 fn test_as_path_display() {
1370 let path = AsPath::from_segments(vec![
1371 AsPathSegment::sequence([1, 2]),
1372 AsPathSegment::set([3, 4]),
1373 AsPathSegment::sequence([5, 6]),
1374 AsPathSegment::ConfedSet(vec![Asn::new_32bit(7)].into()),
1375 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(8)].into()),
1376 ]);
1377
1378 assert_eq!(path.to_string(), "1 2 {3,4} 5 6 {7} 8");
1379 }
1380}