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.is_sorted() {
235 Asn::hash_slice(set, state);
236 return;
237 }
238
239 if set.len() <= 32 {
240 let mut buffer = [Asn::new_32bit(0); 32];
241 set.iter()
242 .zip(&mut buffer)
243 .for_each(|(asn, buffer)| *buffer = *asn);
244
245 let slice = &mut buffer[..set.len()];
246 slice.sort_unstable();
247 Asn::hash_slice(slice, state);
248 return;
249 }
250
251 set.iter().sorted().for_each(|x| x.hash(state));
253 }
254}
255
256impl PartialEq for AsPathSegment {
271 fn eq(&self, other: &Self) -> bool {
272 let (x, y) = match (self, other) {
273 (AsPathSegment::AsSequence(x), AsPathSegment::AsSequence(y))
274 | (AsPathSegment::ConfedSequence(x), AsPathSegment::ConfedSequence(y)) => {
275 return x == y
276 }
277 (AsPathSegment::AsSet(x), AsPathSegment::AsSet(y))
278 | (AsPathSegment::ConfedSet(x), AsPathSegment::ConfedSet(y)) => (x, y),
279 _ => return false,
280 };
281
282 if x.len() != y.len() {
284 return false;
285 } else if x == y {
286 return true;
287 }
288
289 if x.len() <= 32 {
290 let mut x_buffer = [Asn::new_32bit(0); 32];
291 let mut y_buffer = [Asn::new_32bit(0); 32];
292 x.iter()
293 .zip(&mut x_buffer)
294 .for_each(|(asn, buffer)| *buffer = *asn);
295 y.iter()
296 .zip(&mut y_buffer)
297 .for_each(|(asn, buffer)| *buffer = *asn);
298
299 x_buffer[..x.len()].sort_unstable();
300 y_buffer[..y.len()].sort_unstable();
301 return x_buffer[..x.len()] == y_buffer[..y.len()];
302 }
303
304 x.iter()
305 .sorted()
306 .zip(y.iter().sorted())
307 .all(|(a, b)| a == b)
308 }
309}
310
311impl Eq for AsPathSegment {}
312
313struct AsPathNumberedRouteIter<'a> {
317 path: &'a [AsPathSegment],
318 index: usize,
319 route_num: u64,
320}
321
322impl Iterator for AsPathNumberedRouteIter<'_> {
323 type Item = Asn;
324
325 fn next(&mut self) -> Option<Self::Item> {
326 loop {
327 match self.path.first()? {
328 AsPathSegment::AsSequence(x) => match x.get(self.index) {
329 None => {
330 self.index = 0;
331 self.path = &self.path[1..];
332 }
333 Some(asn) => {
334 self.index += 1;
335 return Some(*asn);
336 }
337 },
338 AsPathSegment::AsSet(x) => {
339 self.path = &self.path[1..];
340 if x.is_empty() {
341 return Some(Asn::RESERVED);
342 }
343
344 let asn = x[(self.route_num % x.len() as u64) as usize];
345 self.route_num /= x.len() as u64;
346 return Some(asn);
347 }
348 _ => self.path = &self.path[1..],
349 }
350 }
351 }
352}
353
354pub struct AsPathRouteIter<'a, D> {
355 path: Cow<'a, [AsPathSegment]>,
356 route_num: u64,
357 total_routes: u64,
358 _phantom: PhantomData<D>,
359}
360
361impl<D> Iterator for AsPathRouteIter<'_, D>
362where
363 D: FromIterator<Asn>,
364{
365 type Item = D;
366
367 fn next(&mut self) -> Option<Self::Item> {
368 if self.route_num >= self.total_routes {
369 return None;
370 }
371
372 if self.route_num == 0 && self.path.len() == 1 {
374 if let AsPathSegment::AsSequence(sequence) = &self.path[0] {
375 let route = D::from_iter(sequence.iter().copied());
376 self.route_num += 1;
377 return Some(route);
378 }
379 }
380
381 let route_asn_iter = AsPathNumberedRouteIter {
382 path: self.path.as_ref(),
383 index: 0,
384 route_num: self.route_num,
385 };
386
387 self.route_num += 1;
388 Some(D::from_iter(route_asn_iter))
389 }
390}
391
392#[derive(Debug, PartialEq, Clone, Eq, Default, Hash)]
397pub struct AsPath {
398 pub segments: SmallVec<[AsPathSegment; 1]>,
400}
401
402#[cfg(feature = "ts-rs")]
408#[derive(ts_rs::TS)]
409#[ts(
410 export,
411 type = "(number | number[] | { ty: \"AS_SET\" | \"AS_SEQUENCE\" | \"AS_CONFED_SEQUENCE\" | \"AS_CONFED_SET\", values: number[] })[]"
412)]
413pub struct AsPathWire;
414
415pub type SegmentIter<'a> = std::slice::Iter<'a, AsPathSegment>;
418pub type SegmentIterMut<'a> = std::slice::IterMut<'a, AsPathSegment>;
419pub type SegmentIntoIter = smallvec::IntoIter<[AsPathSegment; 1]>;
420
421impl AsPath {
422 pub fn new() -> AsPath {
423 AsPath {
424 segments: SmallVec::new(),
425 }
426 }
427
428 pub fn from_sequence<S: AsRef<[u32]>>(seq: S) -> Self {
430 let segment = AsPathSegment::AsSequence(seq.as_ref().iter().copied().map_into().collect());
431
432 AsPath {
433 segments: SmallVec::from_buf([segment]),
434 }
435 }
436
437 pub fn from_segments<S: Into<SmallVec<[AsPathSegment; 1]>>>(segments: S) -> AsPath {
438 AsPath {
439 segments: segments.into(),
440 }
441 }
442
443 pub fn append_segment(&mut self, segment: AsPathSegment) {
446 self.segments.push(segment);
447 }
448
449 pub fn is_empty(&self) -> bool {
452 self.segments.is_empty()
453 }
454
455 pub fn route_len(&self) -> usize {
462 self.segments.iter().map(AsPathSegment::route_len).sum()
463 }
464
465 pub fn len(&self) -> usize {
468 self.segments.len()
469 }
470
471 pub fn num_route_variations(&self) -> u64 {
474 let mut variations: u64 = 1;
475
476 for segment in &self.segments {
477 if let AsPathSegment::AsSet(x) = segment {
478 variations *= x.len() as u64;
479 }
480 }
481
482 variations
483 }
484
485 pub fn contains_asn(&self, x: Asn) -> bool {
487 self.iter_segments().flatten().contains(&x)
488 }
489
490 pub fn coalesce(&mut self) {
522 let mut end_index = 0;
523 let mut scan_index = 1;
524
525 while scan_index < self.segments.len() {
526 let (a, b) = self.segments.split_at_mut(scan_index);
527 if !AsPathSegment::merge_in_place(&mut a[end_index], &mut b[0]) {
528 end_index += 1;
529 self.segments.swap(end_index, scan_index);
530 }
531 scan_index += 1;
532 }
533
534 self.segments.truncate(end_index + 1);
535 }
536
537 pub fn dedup_coalesce(&mut self) {
570 if !self.segments.is_empty() {
571 self.segments[0].dedup();
572 }
573 let mut end_index = 0;
574 let mut scan_index = 1;
575
576 while scan_index < self.segments.len() {
577 let (a, b) = self.segments.split_at_mut(scan_index);
578 if !AsPathSegment::dedup_merge_in_place(&mut a[end_index], &mut b[0]) {
579 end_index += 1;
580 self.segments.swap(end_index, scan_index);
581 }
582 scan_index += 1;
583 }
584
585 self.segments.truncate(end_index + 1);
586 }
587
588 pub fn has_equivalent_routing(&self, other: &Self) -> bool {
593 let mut a = self.to_owned();
594 let mut b = other.to_owned();
595
596 a.dedup_coalesce();
597 b.dedup_coalesce();
598
599 a == b
600 }
601
602 pub fn required_asn_length(&self) -> AsnLength {
604 self.iter_segments().flatten().map(Asn::required_len).fold(
605 AsnLength::Bits16,
606 |a, b| match (a, b) {
607 (AsnLength::Bits16, AsnLength::Bits16) => AsnLength::Bits16,
608 _ => AsnLength::Bits32,
609 },
610 )
611 }
612
613 pub fn iter_segments(&self) -> SegmentIter<'_> {
614 self.segments.iter()
615 }
616
617 pub fn iter_segments_mut(&mut self) -> SegmentIterMut<'_> {
618 self.segments.iter_mut()
619 }
620
621 pub fn into_segments_iter(self) -> SegmentIntoIter {
622 self.segments.into_iter()
623 }
624
625 pub fn iter_routes<D>(&self) -> AsPathRouteIter<'_, D>
627 where
628 D: FromIterator<Asn>,
629 {
630 AsPathRouteIter {
631 path: Cow::Borrowed(&self.segments),
632 route_num: 0,
633 total_routes: self.num_route_variations(),
634 _phantom: PhantomData,
635 }
636 }
637
638 pub fn merge_aspath_as4path(aspath: &AsPath, as4path: &AsPath) -> AsPath {
660 if aspath.route_len() < as4path.route_len() {
661 return aspath.clone();
663 }
664
665 let mut leading = aspath.route_len() - as4path.route_len();
671 let mut new_segs: Vec<AsPathSegment> = vec![];
672 for seg in &aspath.segments {
673 if leading == 0 {
674 break;
675 }
676 match seg.route_len() {
677 0 => new_segs.push(seg.clone()),
681 n if n <= leading => {
682 new_segs.push(seg.clone());
683 leading -= n;
684 }
685 _ => {
686 let AsPathSegment::AsSequence(v) = seg else {
690 unreachable!("only an AS_SEQUENCE can exceed the leading count");
691 };
692 new_segs.push(AsPathSegment::AsSequence(
693 v.iter().take(leading).copied().collect(),
694 ));
695 leading = 0;
696 }
697 }
698 }
699 new_segs.extend(as4path.segments.iter().cloned());
700
701 let mut merged = AsPath {
702 segments: new_segs.into(),
703 };
704 merged.coalesce();
705 merged
706 }
707
708 pub fn iter_origins(&self) -> impl '_ + Iterator<Item = Asn> {
711 let origin_slice = match self.segments.last() {
712 Some(AsPathSegment::AsSequence(v)) => v.last().map(std::slice::from_ref).unwrap_or(&[]),
713 Some(AsPathSegment::AsSet(v)) => v.as_ref(),
714 _ => &[],
715 };
716
717 origin_slice.iter().copied()
718 }
719
720 pub fn get_origin_opt(&self) -> Option<Asn> {
724 match self.segments.last() {
725 Some(AsPathSegment::AsSequence(v)) => v.last().copied(),
726 Some(AsPathSegment::AsSet(v)) if v.len() == 1 => Some(v[0]),
727 _ => None,
728 }
729 }
730
731 pub fn get_collector_opt(&self) -> Option<Asn> {
734 match self.segments.first() {
735 Some(AsPathSegment::AsSequence(v)) => v.first().copied(),
736 Some(AsPathSegment::AsSet(v)) if v.len() == 1 => Some(v[0]),
737 _ => None,
738 }
739 }
740
741 pub fn to_u32_vec_opt(&self, dedup: bool) -> Option<Vec<u32>> {
742 let mut path = vec![];
743
744 for seg in self.segments.iter().rev() {
746 let p = seg.to_u32_vec_opt(dedup)?;
749 path.extend(p.iter().rev());
751 }
752
753 match path.is_empty() {
754 true => {
755 None
757 }
758 false => {
759 path.reverse();
761 Some(path)
762 }
763 }
764 }
765}
766
767impl<'a> IntoIterator for &'a AsPath {
769 type Item = Vec<Asn>;
770 type IntoIter = AsPathRouteIter<'a, Vec<Asn>>;
771
772 fn into_iter(self) -> Self::IntoIter {
773 self.iter_routes()
774 }
775}
776
777impl IntoIterator for AsPath {
779 type Item = Vec<Asn>;
780 type IntoIter = AsPathRouteIter<'static, Vec<Asn>>;
781
782 fn into_iter(self) -> Self::IntoIter {
783 AsPathRouteIter {
784 total_routes: self.num_route_variations(),
785 path: Cow::Owned(self.segments.into_vec()),
786 route_num: 0,
787 _phantom: PhantomData,
788 }
789 }
790}
791
792impl Display for AsPath {
793 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
794 for (index, segment) in self.iter_segments().enumerate() {
795 if index != 0 {
796 write!(f, " ")?;
797 }
798
799 match segment {
800 AsPathSegment::AsSequence(v) | AsPathSegment::ConfedSequence(v) => {
801 let mut asn_iter = v.iter();
802 if let Some(first_element) = asn_iter.next() {
803 write!(f, "{first_element}")?;
804
805 for asn in asn_iter {
806 write!(f, " {asn}")?;
807 }
808 }
809 }
810 AsPathSegment::AsSet(v) | AsPathSegment::ConfedSet(v) => {
811 write!(f, "{{")?;
812 let mut asn_iter = v.iter();
813 if let Some(first_element) = asn_iter.next() {
814 write!(f, "{first_element}")?;
815
816 for asn in asn_iter {
817 write!(f, ",{asn}")?;
818 }
819 }
820 write!(f, "}}")?;
821 }
822 }
823 }
824
825 Ok(())
826 }
827}
828
829#[cfg(feature = "serde")]
830mod serde_impl {
831 use super::*;
832 use serde::de::{SeqAccess, Visitor};
833 use serde::ser::SerializeSeq;
834 use serde::{Deserialize, Deserializer, Serialize, Serializer};
835 use std::borrow::Cow;
836
837 #[allow(non_camel_case_types)]
841 #[derive(Serialize, Deserialize)]
842 enum SegmentType {
843 AS_SET,
844 AS_SEQUENCE,
845 AS_CONFED_SEQUENCE,
846 AS_CONFED_SET,
847 }
848
849 #[derive(Serialize, Deserialize)]
850 struct VerboseSegment<'s> {
851 ty: SegmentType,
852 values: Cow<'s, [Asn]>,
853 }
854
855 impl Serialize for AsPathSegment {
856 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
857 where
858 S: Serializer,
859 {
860 let (ty, elements) = match self {
861 AsPathSegment::AsSequence(x) => (SegmentType::AS_SEQUENCE, x.as_ref()),
862 AsPathSegment::AsSet(x) => (SegmentType::AS_SET, x.as_ref()),
863 AsPathSegment::ConfedSequence(x) => (SegmentType::AS_CONFED_SEQUENCE, x.as_ref()),
864 AsPathSegment::ConfedSet(x) => (SegmentType::AS_CONFED_SET, x.as_ref()),
865 };
866
867 let verbose = VerboseSegment {
868 ty,
869 values: Cow::Borrowed(elements),
870 };
871
872 verbose.serialize(serializer)
873 }
874 }
875
876 impl<'de> Deserialize<'de> for AsPathSegment {
877 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
878 where
879 D: Deserializer<'de>,
880 {
881 let verbose = VerboseSegment::deserialize(deserializer)?;
882
883 let values: SmallVec<[Asn; 6]> = verbose.values.into_owned().into();
884 match verbose.ty {
885 SegmentType::AS_SET => Ok(AsPathSegment::AsSet(values)),
886 SegmentType::AS_SEQUENCE => Ok(AsPathSegment::AsSequence(values)),
887 SegmentType::AS_CONFED_SEQUENCE => Ok(AsPathSegment::ConfedSequence(values)),
888 SegmentType::AS_CONFED_SET => Ok(AsPathSegment::ConfedSet(values)),
889 }
890 }
891 }
892
893 fn simplified_format_len(segments: &[AsPathSegment]) -> Option<usize> {
897 let mut elements = 0;
898 let mut prev_was_sequence = false;
899 for segment in segments {
900 match segment {
901 AsPathSegment::AsSequence(seq) if !prev_was_sequence => {
902 prev_was_sequence = true;
903 elements += seq.len();
904 }
905 AsPathSegment::AsSet(_) => {
906 prev_was_sequence = false;
907 elements += 1;
908 }
909 _ => return None,
910 }
911 }
912
913 Some(elements)
914 }
915
916 impl Serialize for AsPath {
965 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
966 where
967 S: Serializer,
968 {
969 if let Some(num_elements) = simplified_format_len(&self.segments) {
970 let mut seq_serializer = serializer.serialize_seq(Some(num_elements))?;
972
973 for segment in &self.segments {
974 match segment {
975 AsPathSegment::AsSequence(elements) => {
976 elements
977 .iter()
978 .try_for_each(|x| seq_serializer.serialize_element(x))?;
979 }
980 AsPathSegment::AsSet(x) => seq_serializer.serialize_element(x)?,
981 _ => unreachable!("simplified_format_len checked for confed segments"),
982 }
983 }
984 return seq_serializer.end();
985 }
986
987 serializer.collect_seq(&self.segments)
989 }
990 }
991
992 struct AsPathVisitor;
993
994 impl<'de> Visitor<'de> for AsPathVisitor {
995 type Value = AsPath;
996
997 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
998 formatter.write_str("list of AS_PATH segments")
999 }
1000
1001 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1002 where
1003 A: SeqAccess<'de>,
1004 {
1005 #[derive(Deserialize)]
1008 #[serde(untagged)]
1009 enum PathElement {
1010 SequenceElement(Asn),
1011 Set(Vec<Asn>),
1012 Verbose(AsPathSegment),
1013 }
1014
1015 let mut append_new_sequence = false;
1016 let mut segments: SmallVec<[AsPathSegment; 1]> = SmallVec::new();
1017 while let Some(element) = seq.next_element()? {
1018 match element {
1019 PathElement::SequenceElement(x) => {
1020 if append_new_sequence {
1021 append_new_sequence = false;
1024 segments.push(AsPathSegment::AsSequence(SmallVec::new()));
1025 }
1026
1027 if let Some(AsPathSegment::AsSequence(last_sequence)) = segments.last_mut()
1028 {
1029 last_sequence.push(x);
1030 } else {
1031 let mut new_seq: SmallVec<[Asn; 6]> = SmallVec::new();
1032 new_seq.push(x);
1033 segments.push(AsPathSegment::AsSequence(new_seq));
1034 }
1035 }
1036 PathElement::Set(values) => {
1037 segments.push(AsPathSegment::AsSet(values.into()));
1038 }
1039 PathElement::Verbose(verbose) => {
1040 segments.push(verbose);
1041 }
1042 }
1043 }
1044
1045 Ok(AsPath { segments })
1046 }
1047 }
1048
1049 impl<'de> Deserialize<'de> for AsPath {
1050 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1051 where
1052 D: Deserializer<'de>,
1053 {
1054 deserializer.deserialize_seq(AsPathVisitor)
1055 }
1056 }
1057}
1058
1059#[cfg(test)]
1060mod tests {
1061 use crate::models::*;
1062 use itertools::Itertools;
1063 use std::collections::hash_map::DefaultHasher;
1064 use std::collections::HashSet;
1065 use std::hash::{Hash, Hasher};
1066
1067 #[test]
1068 fn test_aspath_as4path_merge() {
1069 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
1070 let as4path = AsPath::from_sequence([2, 3, 7]);
1071 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1072 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2, 3, 7]));
1073
1074 let aspath = AsPath::from_sequence([1, 2]);
1075 let as4path = AsPath::from_sequence([2, 3, 7]);
1076 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1077 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2]));
1078
1079 let aspath = AsPath::from_sequence([1, 2]);
1081 let as4path = AsPath::from_sequence([3, 4]);
1082 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1083 assert_eq!(newpath.segments[0], AsPathSegment::sequence([3, 4]));
1084
1085 let aspath = AsPath::from_segments(vec![
1086 AsPathSegment::sequence([1, 2, 3, 5]),
1087 AsPathSegment::set([7, 8]),
1088 ]);
1089 let as4path = AsPath::from_sequence([6, 7, 8]);
1090 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1091 assert_eq!(newpath.segments.len(), 1);
1094 assert_eq!(
1095 newpath.segments[0],
1096 AsPathSegment::sequence([1, 2, 6, 7, 8])
1097 );
1098
1099 let aspath = AsPath::from_segments(vec![
1100 AsPathSegment::sequence([1, 2]),
1101 AsPathSegment::sequence([3, 5]),
1102 AsPathSegment::set([13, 14]),
1103 ]);
1104 let as4path = AsPath::from_segments(vec![
1105 AsPathSegment::sequence([8, 4, 6]),
1106 AsPathSegment::set([11, 12]),
1107 ]);
1108 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1109 assert_eq!(newpath.segments.len(), 2);
1111 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 8, 4, 6]));
1112 assert_eq!(newpath.segments[1], AsPathSegment::set([11, 12]));
1113
1114 let aspath = AsPath::from_segments(vec![
1115 AsPathSegment::sequence([1, 2, 3]),
1116 AsPathSegment::sequence([5]),
1117 AsPathSegment::set([13, 14]),
1118 ]);
1119 let as4path = AsPath::from_segments(vec![
1120 AsPathSegment::sequence([7, 8]),
1121 AsPathSegment::set([11, 12]),
1122 ]);
1123 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1124 assert_eq!(newpath.segments.len(), 2);
1126 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2, 7, 8]));
1127 assert_eq!(newpath.segments[1], AsPathSegment::set([11, 12]));
1128
1129 let aspath = AsPath::from_segments(vec![
1132 AsPathSegment::sequence([1, 2]),
1133 AsPathSegment::sequence([3, 4]),
1134 ]);
1135 let as4path = AsPath::from_sequence([9, 10]);
1136 let newpath = AsPath::merge_aspath_as4path(&aspath, &as4path);
1137 assert_eq!(newpath.segments.len(), 1);
1138 assert_eq!(newpath.segments[0], AsPathSegment::sequence([1, 2, 9, 10]));
1139 }
1140
1141 #[test]
1142 fn test_get_origin() {
1143 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
1144 let origin = aspath.get_origin_opt();
1145 assert_eq!(origin.unwrap(), 5);
1146
1147 let aspath = AsPath::from_segments(vec![AsPathSegment::set([1, 2, 3, 5])]);
1148 let origin = aspath.get_origin_opt();
1149 assert!(origin.is_none());
1150
1151 let aspath = AsPath::from_segments(vec![AsPathSegment::set([1])]);
1152 let origin = aspath.get_origin_opt();
1153 assert_eq!(origin.unwrap(), 1);
1154
1155 let aspath = AsPath::from_segments(vec![
1156 AsPathSegment::sequence([1, 2, 3, 5]),
1157 AsPathSegment::set([7, 8]),
1158 ]);
1159 let origins = aspath.iter_origins().map_into::<u32>().collect::<Vec<_>>();
1160 assert_eq!(origins, vec![7, 8]);
1161
1162 let aspath = AsPath::from_segments(vec![
1163 AsPathSegment::sequence([1, 2, 3, 5]),
1164 AsPathSegment::ConfedSet(vec![Asn::new_32bit(9)].into()),
1165 ]);
1166 let origins = aspath.iter_origins().map_into::<u32>().collect::<Vec<_>>();
1167 assert_eq!(origins, Vec::<u32>::new());
1168 }
1169
1170 #[test]
1171 fn test_get_collector() {
1172 let aspath = AsPath::from_sequence([1, 2, 3, 5]);
1173 let collector = aspath.get_collector_opt();
1174 assert_eq!(collector.unwrap(), 1);
1175
1176 let aspath = AsPath::from_segments(vec![AsPathSegment::set([7])]);
1177 let collector = aspath.get_collector_opt();
1178 assert_eq!(collector.unwrap(), 7);
1179
1180 let aspath = AsPath::from_segments(vec![AsPathSegment::set([7, 8])]);
1181 let collector = aspath.get_collector_opt();
1182 assert!(collector.is_none());
1183 }
1184
1185 #[test]
1186 fn test_aspath_route_iter() {
1187 let path = AsPath::from_segments(vec![AsPathSegment::sequence([3, 4])]);
1188 let mut routes = HashSet::new();
1189 for route in &path {
1190 assert!(routes.insert(route));
1191 }
1192 assert_eq!(1, routes.len());
1193
1194 let path = AsPath::from_segments(vec![
1195 AsPathSegment::set([3, 4]),
1196 AsPathSegment::set([5, 6]),
1197 AsPathSegment::sequence([7, 8]),
1198 AsPathSegment::ConfedSet(vec![Asn::new_32bit(9)].into()),
1199 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(9)].into()),
1200 ]);
1201 assert_eq!(path.route_len(), 4);
1202
1203 let mut routes = HashSet::new();
1204 for route in &path {
1205 assert!(routes.insert(route));
1206 }
1207
1208 assert_eq!(routes.len(), 4);
1209 assert!(routes.contains(&vec![
1210 Asn::from(3),
1211 Asn::from(5),
1212 Asn::from(7),
1213 Asn::from(8)
1214 ]));
1215 assert!(routes.contains(&vec![
1216 Asn::from(3),
1217 Asn::from(6),
1218 Asn::from(7),
1219 Asn::from(8)
1220 ]));
1221 assert!(routes.contains(&vec![
1222 Asn::from(4),
1223 Asn::from(5),
1224 Asn::from(7),
1225 Asn::from(8)
1226 ]));
1227 assert!(routes.contains(&vec![
1228 Asn::from(4),
1229 Asn::from(6),
1230 Asn::from(7),
1231 Asn::from(8)
1232 ]));
1233 }
1234
1235 #[test]
1236 fn test_segment() {
1237 let path_segment = AsPathSegment::sequence([1, 2, 3, 4]);
1238 assert_eq!(path_segment.len(), 4);
1239
1240 let mut iter = path_segment.iter();
1242 assert_eq!(iter.next(), Some(&Asn::new_32bit(1)));
1243 assert_eq!(iter.next(), Some(&Asn::new_32bit(2)));
1244 assert_eq!(iter.next(), Some(&Asn::new_32bit(3)));
1245 assert_eq!(iter.next(), Some(&Asn::new_32bit(4)));
1246 assert_eq!(iter.next(), None);
1247
1248 let mut path_segment = AsPathSegment::sequence([1]);
1250 let mut iter_mut = path_segment.iter_mut();
1251 assert_eq!(iter_mut.next(), Some(&mut Asn::new_32bit(1)));
1252 assert_eq!(iter_mut.next(), None);
1253
1254 assert!(AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1)].into()).is_confed());
1256 assert!(AsPathSegment::ConfedSet(vec![Asn::new_32bit(1)].into()).is_confed());
1257 }
1258
1259 #[test]
1260 fn test_coalesce() {
1261 let mut a = AsPath::from_segments(vec![
1262 AsPathSegment::sequence([]),
1263 AsPathSegment::sequence([1, 2]),
1264 AsPathSegment::sequence([]),
1265 AsPathSegment::sequence([2]),
1266 AsPathSegment::set([2]),
1267 AsPathSegment::set([5, 3, 3, 2]),
1268 ]);
1269
1270 let expected = AsPath::from_segments(vec![
1271 AsPathSegment::sequence([1, 2, 2]),
1272 AsPathSegment::set([2]),
1273 AsPathSegment::set([5, 3, 3, 2]),
1274 ]);
1275
1276 a.coalesce();
1277 assert_eq!(a, expected);
1278 }
1279
1280 #[test]
1281 fn test_confed_set_dedup() {
1282 let mut path_segment =
1283 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(1)].into());
1284 path_segment.dedup();
1285 assert_eq!(
1286 path_segment,
1287 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1)].into())
1288 );
1289
1290 let mut path_segment = AsPathSegment::ConfedSet(
1291 vec![Asn::new_32bit(1), Asn::new_32bit(2), Asn::new_32bit(2)].into(),
1292 );
1293 path_segment.dedup();
1294 assert_eq!(
1295 path_segment,
1296 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into())
1297 );
1298 }
1299
1300 #[test]
1301 fn test_path_to_u32() {
1302 let path_segment = AsPathSegment::sequence([1, 2, 3, 3]);
1304 assert_eq!(path_segment.to_u32_vec_opt(false), Some(vec![1, 2, 3, 3]));
1305 assert_eq!(path_segment.to_u32_vec_opt(true), Some(vec![1, 2, 3]));
1306
1307 let path_segment = AsPathSegment::set([1, 2, 3, 3]);
1309 assert_eq!(path_segment.to_u32_vec_opt(false), None);
1310 assert_eq!(path_segment.to_u32_vec_opt(true), None);
1311
1312 let path_segment = AsPathSegment::set([1]);
1314 assert_eq!(path_segment.to_u32_vec_opt(false), Some(vec![1]));
1315 assert_eq!(path_segment.to_u32_vec_opt(true), Some(vec![1]));
1316
1317 let as_path = AsPath::from_segments(vec![
1319 AsPathSegment::set([4]),
1320 AsPathSegment::sequence([2, 3, 3]),
1321 AsPathSegment::set([1]),
1322 ]);
1323 assert_eq!(as_path.to_u32_vec_opt(false), Some(vec![4, 2, 3, 3, 1]));
1324 assert_eq!(as_path.to_u32_vec_opt(true), Some(vec![4, 2, 3, 1]));
1325
1326 let as_path = AsPath::from_segments(vec![
1328 AsPathSegment::set([4, 2]),
1329 AsPathSegment::sequence([2, 3, 3]),
1330 AsPathSegment::set([1]),
1331 ]);
1332 assert_eq!(as_path.to_u32_vec_opt(false), None);
1333 assert_eq!(as_path.to_u32_vec_opt(true), None);
1334
1335 let as_path = AsPath::from_segments(vec![]);
1339 assert_eq!(as_path.to_u32_vec_opt(false), None);
1340 assert_eq!(as_path.to_u32_vec_opt(true), None);
1341
1342 let as_path = AsPath::from_segments(vec![
1344 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into()),
1345 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(3), Asn::new_32bit(4)].into()),
1346 ]);
1347 assert_eq!(as_path.to_u32_vec_opt(false), None);
1348 assert_eq!(as_path.to_u32_vec_opt(true), None);
1349 }
1350
1351 #[test]
1352 fn test_as_ref() {
1353 let path_segment = AsPathSegment::sequence([1, 2]);
1354 assert_eq!(
1355 path_segment.as_ref(),
1356 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1357 );
1358
1359 let path_segment = AsPathSegment::set([1, 2]);
1360 assert_eq!(
1361 path_segment.as_ref(),
1362 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1363 );
1364
1365 let path_segment =
1366 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into());
1367 assert_eq!(
1368 path_segment.as_ref(),
1369 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1370 );
1371
1372 let path_segment =
1373 AsPathSegment::ConfedSet(vec![Asn::new_32bit(1), Asn::new_32bit(2)].into());
1374 assert_eq!(
1375 path_segment.as_ref(),
1376 &[Asn::new_32bit(1), Asn::new_32bit(2)]
1377 );
1378 }
1379
1380 #[test]
1381 fn test_hashing() {
1382 let path_segment = AsPathSegment::sequence([1, 2]);
1383 let path_segment2 = AsPathSegment::sequence([1, 2]);
1384
1385 let hashset = std::iter::once(path_segment).collect::<HashSet<_>>();
1386 assert!(hashset.contains(&path_segment2));
1387 }
1388
1389 #[test]
1390 fn test_set_hashing_is_order_independent() {
1391 fn hash_of(segment: &AsPathSegment) -> u64 {
1392 let mut hasher = DefaultHasher::new();
1393 segment.hash(&mut hasher);
1394 hasher.finish()
1395 }
1396
1397 let sorted = AsPathSegment::set([1, 2, 3]);
1399 let unsorted = AsPathSegment::set([3, 1, 2]);
1400 assert_eq!(hash_of(&sorted), hash_of(&unsorted));
1401
1402 let big_sorted = AsPathSegment::set((1u32..40).collect::<Vec<_>>());
1404 let big_unsorted = AsPathSegment::set((1u32..40).rev().collect::<Vec<_>>());
1405 assert_eq!(hash_of(&big_sorted), hash_of(&big_unsorted));
1406 }
1407
1408 #[test]
1409 fn test_equality() {
1410 let path_segment = AsPathSegment::sequence([1, 2]);
1411 let path_segment2 = AsPathSegment::sequence([1, 2]);
1412
1413 assert_eq!(path_segment, path_segment2);
1414
1415 let path_segment = AsPathSegment::sequence([1, 2]);
1416 let path_segment2 = AsPathSegment::set([1, 2, 3]);
1417 assert_ne!(path_segment, path_segment2);
1418
1419 let path_segment = AsPathSegment::sequence((1..33).collect::<Vec<_>>());
1421 let path_segment2 = AsPathSegment::sequence((1..33).collect::<Vec<_>>());
1422 assert_eq!(path_segment, path_segment2);
1423 }
1424
1425 #[test]
1426 fn test_as_path_display() {
1427 let path = AsPath::from_segments(vec![
1428 AsPathSegment::sequence([1, 2]),
1429 AsPathSegment::set([3, 4]),
1430 AsPathSegment::sequence([5, 6]),
1431 AsPathSegment::ConfedSet(vec![Asn::new_32bit(7)].into()),
1432 AsPathSegment::ConfedSequence(vec![Asn::new_32bit(8)].into()),
1433 ]);
1434
1435 assert_eq!(path.to_string(), "1 2 {3,4} 5 6 {7} 8");
1436 }
1437}