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 if let Some(p) = seg.to_u32_vec_opt(dedup) {
726 path.extend(p.iter().rev());
729 } else {
730 return None;
734 }
735 }
736
737 match path.is_empty() {
738 true => {
739 None
741 }
742 false => {
743 path.reverse();
745 Some(path)
746 }
747 }
748 }
749}
750
751impl<'a> IntoIterator for &'a AsPath {
753 type Item = Vec<Asn>;
754 type IntoIter = AsPathRouteIter<'a, Vec<Asn>>;
755
756 fn into_iter(self) -> Self::IntoIter {
757 self.iter_routes()
758 }
759}
760
761impl IntoIterator for AsPath {
763 type Item = Vec<Asn>;
764 type IntoIter = AsPathRouteIter<'static, Vec<Asn>>;
765
766 fn into_iter(self) -> Self::IntoIter {
767 AsPathRouteIter {
768 total_routes: self.num_route_variations(),
769 path: Cow::Owned(self.segments.into_vec()),
770 route_num: 0,
771 _phantom: PhantomData,
772 }
773 }
774}
775
776impl Display for AsPath {
777 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
778 for (index, segment) in self.iter_segments().enumerate() {
779 if index != 0 {
780 write!(f, " ")?;
781 }
782
783 match segment {
784 AsPathSegment::AsSequence(v) | AsPathSegment::ConfedSequence(v) => {
785 let mut asn_iter = v.iter();
786 if let Some(first_element) = asn_iter.next() {
787 write!(f, "{first_element}")?;
788
789 for asn in asn_iter {
790 write!(f, " {asn}")?;
791 }
792 }
793 }
794 AsPathSegment::AsSet(v) | AsPathSegment::ConfedSet(v) => {
795 write!(f, "{{")?;
796 let mut asn_iter = v.iter();
797 if let Some(first_element) = asn_iter.next() {
798 write!(f, "{first_element}")?;
799
800 for asn in asn_iter {
801 write!(f, ",{asn}")?;
802 }
803 }
804 write!(f, "}}")?;
805 }
806 }
807 }
808
809 Ok(())
810 }
811}
812
813#[cfg(feature = "serde")]
814mod serde_impl {
815 use super::*;
816 use serde::de::{SeqAccess, Visitor};
817 use serde::ser::SerializeSeq;
818 use serde::{Deserialize, Deserializer, Serialize, Serializer};
819 use std::borrow::Cow;
820
821 #[allow(non_camel_case_types)]
825 #[derive(Serialize, Deserialize)]
826 enum SegmentType {
827 AS_SET,
828 AS_SEQUENCE,
829 AS_CONFED_SEQUENCE,
830 AS_CONFED_SET,
831 }
832
833 #[derive(Serialize, Deserialize)]
834 struct VerboseSegment<'s> {
835 ty: SegmentType,
836 values: Cow<'s, [Asn]>,
837 }
838
839 impl Serialize for AsPathSegment {
840 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
841 where
842 S: Serializer,
843 {
844 let (ty, elements) = match self {
845 AsPathSegment::AsSequence(x) => (SegmentType::AS_SEQUENCE, x.as_ref()),
846 AsPathSegment::AsSet(x) => (SegmentType::AS_SET, x.as_ref()),
847 AsPathSegment::ConfedSequence(x) => (SegmentType::AS_CONFED_SEQUENCE, x.as_ref()),
848 AsPathSegment::ConfedSet(x) => (SegmentType::AS_CONFED_SET, x.as_ref()),
849 };
850
851 let verbose = VerboseSegment {
852 ty,
853 values: Cow::Borrowed(elements),
854 };
855
856 verbose.serialize(serializer)
857 }
858 }
859
860 impl<'de> Deserialize<'de> for AsPathSegment {
861 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
862 where
863 D: Deserializer<'de>,
864 {
865 let verbose = VerboseSegment::deserialize(deserializer)?;
866
867 let values: SmallVec<[Asn; 6]> = verbose.values.into_owned().into();
868 match verbose.ty {
869 SegmentType::AS_SET => Ok(AsPathSegment::AsSet(values)),
870 SegmentType::AS_SEQUENCE => Ok(AsPathSegment::AsSequence(values)),
871 SegmentType::AS_CONFED_SEQUENCE => Ok(AsPathSegment::ConfedSequence(values)),
872 SegmentType::AS_CONFED_SET => Ok(AsPathSegment::ConfedSet(values)),
873 }
874 }
875 }
876
877 fn simplified_format_len(segments: &[AsPathSegment]) -> Option<usize> {
881 let mut elements = 0;
882 let mut prev_was_sequence = false;
883 for segment in segments {
884 match segment {
885 AsPathSegment::AsSequence(seq) if !prev_was_sequence => {
886 prev_was_sequence = true;
887 elements += seq.len();
888 }
889 AsPathSegment::AsSet(_) => {
890 prev_was_sequence = false;
891 elements += 1;
892 }
893 _ => return None,
894 }
895 }
896
897 Some(elements)
898 }
899
900 impl Serialize for AsPath {
949 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
950 where
951 S: Serializer,
952 {
953 if let Some(num_elements) = simplified_format_len(&self.segments) {
954 let mut seq_serializer = serializer.serialize_seq(Some(num_elements))?;
956
957 for segment in &self.segments {
958 match segment {
959 AsPathSegment::AsSequence(elements) => {
960 elements
961 .iter()
962 .try_for_each(|x| seq_serializer.serialize_element(x))?;
963 }
964 AsPathSegment::AsSet(x) => seq_serializer.serialize_element(x)?,
965 _ => unreachable!("simplified_format_len checked for confed segments"),
966 }
967 }
968 return seq_serializer.end();
969 }
970
971 serializer.collect_seq(&self.segments)
973 }
974 }
975
976 struct AsPathVisitor;
977
978 impl<'de> Visitor<'de> for AsPathVisitor {
979 type Value = AsPath;
980
981 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
982 formatter.write_str("list of AS_PATH segments")
983 }
984
985 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
986 where
987 A: SeqAccess<'de>,
988 {
989 #[derive(Deserialize)]
992 #[serde(untagged)]
993 enum PathElement {
994 SequenceElement(Asn),
995 Set(Vec<Asn>),
996 Verbose(AsPathSegment),
997 }
998
999 let mut append_new_sequence = false;
1000 let mut segments: SmallVec<[AsPathSegment; 1]> = SmallVec::new();
1001 while let Some(element) = seq.next_element()? {
1002 match element {
1003 PathElement::SequenceElement(x) => {
1004 if append_new_sequence {
1005 append_new_sequence = false;
1008 segments.push(AsPathSegment::AsSequence(SmallVec::new()));
1009 }
1010
1011 if let Some(AsPathSegment::AsSequence(last_sequence)) = segments.last_mut()
1012 {
1013 last_sequence.push(x);
1014 } else {
1015 let mut new_seq: SmallVec<[Asn; 6]> = SmallVec::new();
1016 new_seq.push(x);
1017 segments.push(AsPathSegment::AsSequence(new_seq));
1018 }
1019 }
1020 PathElement::Set(values) => {
1021 segments.push(AsPathSegment::AsSet(values.into()));
1022 }
1023 PathElement::Verbose(verbose) => {
1024 segments.push(verbose);
1025 }
1026 }
1027 }
1028
1029 Ok(AsPath { segments })
1030 }
1031 }
1032
1033 impl<'de> Deserialize<'de> for AsPath {
1034 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1035 where
1036 D: Deserializer<'de>,
1037 {
1038 deserializer.deserialize_seq(AsPathVisitor)
1039 }
1040 }
1041}
1042
1043#[cfg(test)]
1044mod tests {
1045 use crate::models::*;
1046 use itertools::Itertools;
1047 use std::collections::HashSet;
1048
1049 #[test]
1050 fn test_aspath_as4path_merge() {
1051 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
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, 3, 7]));
1055
1056 let aspath = AsPath::from_sequence([1, 2]);
1057 let as4path = AsPath::from_sequence([2, 3, 7]);
1058 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1059 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2]));
1060
1061 let aspath = AsPath::from_sequence([1, 2]);
1063 let as4path = AsPath::from_sequence([3, 4]);
1064 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1065 assert_eq!(newpath.segments[0], AsPathSegment::sequence([3, 4]));
1066
1067 let aspath = AsPath::from_segments(vec![
1068 AsPathSegment::sequence([1, 2, 3, 5]),
1069 AsPathSegment::set([7, 8]),
1070 ]);
1071 let as4path = AsPath::from_sequence([6, 7, 8]);
1072 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1073 assert_eq!(newpath.segments.len(), 2);
1074 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 6, 7, 8]));
1075 assert_eq!(newpath.segments[1], AsPathSegment::set([7, 8]));
1076
1077 let aspath = AsPath::from_segments(vec![
1078 AsPathSegment::sequence([1, 2]),
1079 AsPathSegment::sequence([3, 5]),
1080 AsPathSegment::set([13, 14]),
1081 ]);
1082 let as4path = AsPath::from_segments(vec![
1083 AsPathSegment::sequence([8, 4, 6]),
1084 AsPathSegment::set([11, 12]),
1085 ]);
1086 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1087 assert_eq!(newpath.segments.len(), 3);
1088 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2]));
1089 assert_eq!(newpath.segments[1], AsPathSegment::set([11, 12]));
1090 assert_eq!(newpath.segments[2], AsPathSegment::set([13, 14]));
1091
1092 let aspath = AsPath::from_segments(vec![
1093 AsPathSegment::sequence([1, 2, 3]),
1094 AsPathSegment::sequence([5]),
1095 AsPathSegment::set([13, 14]),
1096 ]);
1097 let as4path = AsPath::from_segments(vec![
1098 AsPathSegment::sequence([7, 8]),
1099 AsPathSegment::set([11, 12]),
1100 ]);
1101 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1102 assert_eq!(newpath.segments.len(), 3);
1103 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 7, 8]));
1104 assert_eq!(newpath.segments[1], AsPathSegment::set([11, 12]));
1105 assert_eq!(newpath.segments[2], AsPathSegment::set([13, 14]));
1106 }
1107
1108 #[test]
1109 fn test_get_origin() {
1110 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
1111 let origin = aspath.get_origin_opt();
1112 assert_eq!(origin.unwrap(), 5);
1113
1114 let aspath = AsPath::from_segments(vec![AsPathSegment::set([1, 2, 3, 5])]);
1115 let origin = aspath.get_origin_opt();
1116 assert!(origin.is_none());
1117
1118 let aspath = AsPath::from_segments(vec![AsPathSegment::set([1])]);
1119 let origin = aspath.get_origin_opt();
1120 assert_eq!(origin.unwrap(), 1);
1121
1122 let aspath = AsPath::from_segments(vec![
1123 AsPathSegment::sequence([1, 2, 3, 5]),
1124 AsPathSegment::set([7, 8]),
1125 ]);
1126 let origins = aspath.iter_origins().map_into::<u32>().collect::<Vec<_>>();
1127 assert_eq!(origins, vec![7, 8]);
1128
1129 let aspath = AsPath::from_segments(vec![
1130 AsPathSegment::sequence([1, 2, 3, 5]),
1131 AsPathSegment::ConfedSet(vec![Asn::new_32bit(9)].into()),
1132 ]);
1133 let origins = aspath.iter_origins().map_into::<u32>().collect::<Vec<_>>();
1134 assert_eq!(origins, Vec::<u32>::new());
1135 }
1136
1137 #[test]
1138 fn test_get_collector() {
1139 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
1140 let collector = aspath.get_collector_opt();
1141 assert_eq!(collector.unwrap(), 1);
1142
1143 let aspath = AsPath::from_segments(vec![AsPathSegment::set([7])]);
1144 let collector = aspath.get_collector_opt();
1145 assert_eq!(collector.unwrap(), 7);
1146
1147 let aspath = AsPath::from_segments(vec![AsPathSegment::set([7, 8])]);
1148 let collector = aspath.get_collector_opt();
1149 assert!(collector.is_none());
1150 }
1151
1152 #[test]
1153 fn test_aspath_route_iter() {
1154 let path = AsPath::from_segments(vec![AsPathSegment::sequence([3, 4])]);
1155 let mut routes = HashSet::new();
1156 for route in &path {
1157 assert!(routes.insert(route));
1158 }
1159 assert_eq!(1, routes.len());
1160
1161 let path = AsPath::from_segments(vec![
1162 AsPathSegment::set([3, 4]),
1163 AsPathSegment::set([5, 6]),
1164 AsPathSegment::sequence([7, 8]),
1165 AsPathSegment::ConfedSet(vec![Asn::new_32bit(9)].into()),
1166 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(9)].into()),
1167 ]);
1168 assert_eq!(path.route_len(), 4);
1169
1170 let mut routes = HashSet::new();
1171 for route in &path {
1172 assert!(routes.insert(route));
1173 }
1174
1175 assert_eq!(routes.len(), 4);
1176 assert!(routes.contains(&vec![
1177 Asn::from(3),
1178 Asn::from(5),
1179 Asn::from(7),
1180 Asn::from(8)
1181 ]));
1182 assert!(routes.contains(&vec![
1183 Asn::from(3),
1184 Asn::from(6),
1185 Asn::from(7),
1186 Asn::from(8)
1187 ]));
1188 assert!(routes.contains(&vec![
1189 Asn::from(4),
1190 Asn::from(5),
1191 Asn::from(7),
1192 Asn::from(8)
1193 ]));
1194 assert!(routes.contains(&vec![
1195 Asn::from(4),
1196 Asn::from(6),
1197 Asn::from(7),
1198 Asn::from(8)
1199 ]));
1200 }
1201
1202 #[test]
1203 fn test_segment() {
1204 let path_segment = AsPathSegment::sequence([1, 2, 3, 4]);
1205 assert_eq!(path_segment.len(), 4);
1206
1207 let mut iter = path_segment.iter();
1209 assert_eq!(iter.next(), Some(&Asn::new_32bit(1)));
1210 assert_eq!(iter.next(), Some(&Asn::new_32bit(2)));
1211 assert_eq!(iter.next(), Some(&Asn::new_32bit(3)));
1212 assert_eq!(iter.next(), Some(&Asn::new_32bit(4)));
1213 assert_eq!(iter.next(), None);
1214
1215 let mut path_segment = AsPathSegment::sequence([1]);
1217 let mut iter_mut = path_segment.iter_mut();
1218 assert_eq!(iter_mut.next(), Some(&mut Asn::new_32bit(1)));
1219 assert_eq!(iter_mut.next(), None);
1220
1221 assert!(AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1)].into()).is_confed());
1223 assert!(AsPathSegment::ConfedSet(vec![Asn::new_32bit(1)].into()).is_confed());
1224 }
1225
1226 #[test]
1227 fn test_coalesce() {
1228 let mut a = AsPath::from_segments(vec![
1229 AsPathSegment::sequence([]),
1230 AsPathSegment::sequence([1, 2]),
1231 AsPathSegment::sequence([]),
1232 AsPathSegment::sequence([2]),
1233 AsPathSegment::set([2]),
1234 AsPathSegment::set([5, 3, 3, 2]),
1235 ]);
1236
1237 let expected = AsPath::from_segments(vec![
1238 AsPathSegment::sequence([1, 2, 2]),
1239 AsPathSegment::set([2]),
1240 AsPathSegment::set([5, 3, 3, 2]),
1241 ]);
1242
1243 a.coalesce();
1244 assert_eq!(a, expected);
1245 }
1246
1247 #[test]
1248 fn test_confed_set_dedup() {
1249 let mut path_segment =
1250 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(1)].into());
1251 path_segment.dedup();
1252 assert_eq!(
1253 path_segment,
1254 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1)].into())
1255 );
1256
1257 let mut path_segment = AsPathSegment::ConfedSet(
1258 vec![Asn::new_32bit(1), Asn::new_32bit(2), Asn::new_32bit(2)].into(),
1259 );
1260 path_segment.dedup();
1261 assert_eq!(
1262 path_segment,
1263 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into())
1264 );
1265 }
1266
1267 #[test]
1268 fn test_path_to_u32() {
1269 let path_segment = AsPathSegment::sequence([1, 2, 3, 3]);
1271 assert_eq!(path_segment.to_u32_vec_opt(false), Some(vec![1, 2, 3, 3]));
1272 assert_eq!(path_segment.to_u32_vec_opt(true), Some(vec![1, 2, 3]));
1273
1274 let path_segment = AsPathSegment::set([1, 2, 3, 3]);
1276 assert_eq!(path_segment.to_u32_vec_opt(false), None);
1277 assert_eq!(path_segment.to_u32_vec_opt(true), None);
1278
1279 let path_segment = AsPathSegment::set([1]);
1281 assert_eq!(path_segment.to_u32_vec_opt(false), Some(vec![1]));
1282 assert_eq!(path_segment.to_u32_vec_opt(true), Some(vec![1]));
1283
1284 let as_path = AsPath::from_segments(vec![
1286 AsPathSegment::set([4]),
1287 AsPathSegment::sequence([2, 3, 3]),
1288 AsPathSegment::set([1]),
1289 ]);
1290 assert_eq!(as_path.to_u32_vec_opt(false), Some(vec![4, 2, 3, 3, 1]));
1291 assert_eq!(as_path.to_u32_vec_opt(true), Some(vec![4, 2, 3, 1]));
1292
1293 let as_path = AsPath::from_segments(vec![
1295 AsPathSegment::set([4, 2]),
1296 AsPathSegment::sequence([2, 3, 3]),
1297 AsPathSegment::set([1]),
1298 ]);
1299 assert_eq!(as_path.to_u32_vec_opt(false), None);
1300 assert_eq!(as_path.to_u32_vec_opt(true), None);
1301
1302 let as_path = AsPath::from_segments(vec![]);
1306 assert_eq!(as_path.to_u32_vec_opt(false), None);
1307 assert_eq!(as_path.to_u32_vec_opt(true), None);
1308
1309 let as_path = AsPath::from_segments(vec![
1311 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into()),
1312 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(3), Asn::new_32bit(4)].into()),
1313 ]);
1314 assert_eq!(as_path.to_u32_vec_opt(false), None);
1315 assert_eq!(as_path.to_u32_vec_opt(true), None);
1316 }
1317
1318 #[test]
1319 fn test_as_ref() {
1320 let path_segment = AsPathSegment::sequence([1, 2]);
1321 assert_eq!(
1322 path_segment.as_ref(),
1323 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1324 );
1325
1326 let path_segment = AsPathSegment::set([1, 2]);
1327 assert_eq!(
1328 path_segment.as_ref(),
1329 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1330 );
1331
1332 let path_segment =
1333 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into());
1334 assert_eq!(
1335 path_segment.as_ref(),
1336 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1337 );
1338
1339 let path_segment =
1340 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into());
1341 assert_eq!(
1342 path_segment.as_ref(),
1343 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1344 );
1345 }
1346
1347 #[test]
1348 fn test_hashing() {
1349 let path_segment = AsPathSegment::sequence([1, 2]);
1350 let path_segment2 = AsPathSegment::sequence([1, 2]);
1351
1352 let hashset = std::iter::once(path_segment).collect::<HashSet<_>>();
1353 assert!(hashset.contains(&path_segment2));
1354 }
1355
1356 #[test]
1357 fn test_equality() {
1358 let path_segment = AsPathSegment::sequence([1, 2]);
1359 let path_segment2 = AsPathSegment::sequence([1, 2]);
1360
1361 assert_eq!(path_segment, path_segment2);
1362
1363 let path_segment = AsPathSegment::sequence([1, 2]);
1364 let path_segment2 = AsPathSegment::set([1, 2, 3]);
1365 assert_ne!(path_segment, path_segment2);
1366
1367 let path_segment = AsPathSegment::sequence((1..33).collect::<Vec<_>>());
1369 let path_segment2 = AsPathSegment::sequence((1..33).collect::<Vec<_>>());
1370 assert_eq!(path_segment, path_segment2);
1371 }
1372
1373 #[test]
1374 fn test_as_path_display() {
1375 let path = AsPath::from_segments(vec![
1376 AsPathSegment::sequence([1, 2]),
1377 AsPathSegment::set([3, 4]),
1378 AsPathSegment::sequence([5, 6]),
1379 AsPathSegment::ConfedSet(vec![Asn::new_32bit(7)].into()),
1380 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(8)].into()),
1381 ]);
1382
1383 assert_eq!(path.to_string(), "1 2 {3,4} 5 6 {7} 8");
1384 }
1385}