1use std::cmp::Ordering;
4use std::convert::TryInto;
5use std::iter::Peekable;
6use std::str::FromStr;
7use std::{error, fmt, iter, ops, slice};
8
9#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
13#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
14#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
15#[repr(transparent)]
16pub struct Asn(u32);
17
18impl Asn {
19 pub const MIN: Asn = Asn(u32::MIN);
20 pub const MAX: Asn = Asn(u32::MAX);
21
22 pub fn from_u32(value: u32) -> Self {
24 Asn(value)
25 }
26
27 pub fn into_u32(self) -> u32 {
29 self.0
30 }
31
32 pub fn try_into_u16(self) -> Result<u16, LargeAsnError> {
34 self.0.try_into().map_err(|_| LargeAsnError)
35 }
36
37 pub fn try_into_asn16(self) -> Result<Asn16, LargeAsnError> {
39 Ok(Asn16(self.try_into_u16()?))
40 }
41
42 pub fn to_raw(self) -> [u8; 4] {
44 self.0.to_be_bytes()
45 }
46
47 #[cfg(feature = "octseq")]
48 pub fn compose<Target: octseq::OctetsBuilder>(
49 self,
50 target: &mut Target,
51 ) -> Result<(), Target::AppendError> {
52 target.append_slice(&self.to_raw())
53 }
54
55 }
63
64impl From<u32> for Asn {
67 fn from(id: u32) -> Self {
68 Asn(id)
69 }
70}
71
72impl From<Asn> for u32 {
73 fn from(id: Asn) -> Self {
74 id.0
75 }
76}
77
78impl FromStr for Asn {
81 type Err = ParseAsnError;
82
83 fn from_str(s: &str) -> Result<Self, Self::Err> {
84 let s = if s.len() > 2 && s[..2].eq_ignore_ascii_case("as") {
85 &s[2..]
86 } else {
87 s
88 };
89
90 u32::from_str(s).map(Asn).map_err(|_| ParseAsnError)
91 }
92}
93
94#[cfg(feature = "serde")]
106impl Asn {
107 pub fn serialize_as_u32<S: serde::Serializer>(
114 &self,
115 serializer: S,
116 ) -> Result<S::Ok, S::Error> {
117 serializer.serialize_u32(self.0)
118 }
119
120 pub fn serialize_as_bare_str<S: serde::Serializer>(
122 &self,
123 serializer: S,
124 ) -> Result<S::Ok, S::Error> {
125 serializer.collect_str(&format_args!("{}", self.0))
126 }
127
128 pub fn serialize_as_str<S: serde::Serializer>(
130 &self,
131 serializer: S,
132 ) -> Result<S::Ok, S::Error> {
133 serializer.collect_str(&format_args!("AS{}", self.0))
134 }
135
136 pub fn deserialize_from_u32<'de, D: serde::Deserializer<'de>>(
143 deserializer: D,
144 ) -> Result<Self, D::Error> {
145 <u32 as serde::Deserialize>::deserialize(deserializer).map(Into::into)
146 }
147
148 pub fn deserialize_from_str<'de, D: serde::de::Deserializer<'de>>(
152 deserializer: D,
153 ) -> Result<Self, D::Error> {
154 struct Visitor;
155
156 impl<'de> serde::de::Visitor<'de> for Visitor {
157 type Value = Asn;
158
159 fn expecting(
160 &self,
161 formatter: &mut fmt::Formatter,
162 ) -> fmt::Result {
163 write!(formatter, "an AS number")
164 }
165
166 fn visit_str<E: serde::de::Error>(
167 self,
168 v: &str,
169 ) -> Result<Self::Value, E> {
170 Asn::from_str(v).map_err(E::custom)
171 }
172 }
173 deserializer.deserialize_str(Visitor)
174 }
175
176 pub fn deserialize_from_any<'de, D: serde::de::Deserializer<'de>>(
183 deserializer: D,
184 ) -> Result<Self, D::Error> {
185 struct Visitor;
186
187 impl<'de> serde::de::Visitor<'de> for Visitor {
188 type Value = Asn;
189
190 fn expecting(
191 &self,
192 formatter: &mut fmt::Formatter,
193 ) -> fmt::Result {
194 write!(formatter, "an AS number")
195 }
196
197 fn visit_u8<E: serde::de::Error>(
198 self,
199 v: u8,
200 ) -> Result<Self::Value, E> {
201 Ok(Asn(v.into()))
202 }
203
204 fn visit_u16<E: serde::de::Error>(
205 self,
206 v: u16,
207 ) -> Result<Self::Value, E> {
208 Ok(Asn(v.into()))
209 }
210
211 fn visit_u32<E: serde::de::Error>(
212 self,
213 v: u32,
214 ) -> Result<Self::Value, E> {
215 Ok(Asn(v))
216 }
217
218 fn visit_u64<E: serde::de::Error>(
219 self,
220 v: u64,
221 ) -> Result<Self::Value, E> {
222 Ok(Asn(v.try_into().map_err(E::custom)?))
223 }
224
225 fn visit_i8<E: serde::de::Error>(
226 self,
227 v: i8,
228 ) -> Result<Self::Value, E> {
229 Ok(Asn(v.try_into().map_err(E::custom)?))
230 }
231
232 fn visit_i16<E: serde::de::Error>(
233 self,
234 v: i16,
235 ) -> Result<Self::Value, E> {
236 Ok(Asn(v.try_into().map_err(E::custom)?))
237 }
238
239 fn visit_i32<E: serde::de::Error>(
240 self,
241 v: i32,
242 ) -> Result<Self::Value, E> {
243 Ok(Asn(v.try_into().map_err(E::custom)?))
244 }
245
246 fn visit_i64<E: serde::de::Error>(
247 self,
248 v: i64,
249 ) -> Result<Self::Value, E> {
250 Ok(Asn(v.try_into().map_err(E::custom)?))
251 }
252
253 fn visit_str<E: serde::de::Error>(
254 self,
255 v: &str,
256 ) -> Result<Self::Value, E> {
257 Asn::from_str(v).map_err(E::custom)
258 }
259 }
260 deserializer.deserialize_any(Visitor)
261 }
262}
263
264impl ops::Add<u32> for Asn {
267 type Output = Self;
268
269 fn add(self, rhs: u32) -> Self {
270 Asn(self.0.checked_add(rhs).unwrap())
271 }
272}
273
274impl fmt::Display for Asn {
277 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
278 write!(f, "AS{}", self.0)
279 }
280}
281
282#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
289#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
290pub struct Asn16(u16);
291
292impl Asn16 {
293 pub fn from_u16(u: u16) -> Self {
294 Self(u)
295 }
296 pub fn to_u16(self) -> u16 {
297 self.0
298 }
299 pub fn into_asn32(self) -> Asn {
300 Asn::from_u32(self.0 as u32)
301 }
302 pub fn to_raw(self) -> [u8; 2] {
303 self.0.to_be_bytes()
304 }
305}
306
307impl fmt::Display for Asn16 {
310 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
311 write!(f, "AS{}", self.0)
312 }
313}
314
315impl From<u16> for Asn16 {
318 fn from(n: u16) -> Self {
319 Self(n)
320 }
321}
322
323fn strip_as(s: &str) -> &str {
324 s.strip_prefix("AS")
325 .or_else(|| s.strip_prefix("as"))
326 .or_else(|| s.strip_prefix("As"))
327 .or_else(|| s.strip_prefix("aS"))
328 .unwrap_or(s)
329}
330
331impl FromStr for Asn16 {
332 type Err = ParseAsnError;
333
334 fn from_str(s: &str) -> Result<Self, Self::Err> {
335 u16::from_str(strip_as(s))
336 .map_err(|_| ParseAsnError)
337 .map(Asn16::from_u16)
338
339 }
348}
349
350#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
358#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
359pub struct SmallAsnSet(Vec<Asn>);
360
361impl SmallAsnSet {
362 pub fn iter(&self) -> SmallSetIter {
363 self.0.iter().cloned()
364 }
365
366 pub fn len(&self) -> usize {
367 self.0.len()
368 }
369
370 pub fn is_empty(&self) -> bool {
371 self.0.is_empty()
372 }
373
374 pub fn difference<'a>(
375 &'a self,
376 other: &'a Self,
377 ) -> SmallSetDifference<'a> {
378 SmallSetDifference {
379 left: self.iter().peekable(),
380 right: other.iter().peekable(),
381 }
382 }
383
384 pub fn symmetric_difference<'a>(
385 &'a self,
386 other: &'a Self,
387 ) -> SmallSetSymmetricDifference<'a> {
388 SmallSetSymmetricDifference {
389 left: self.iter().peekable(),
390 right: other.iter().peekable(),
391 }
392 }
393
394 pub fn intersection<'a>(
395 &'a self,
396 other: &'a Self,
397 ) -> SmallSetIntersection<'a> {
398 SmallSetIntersection {
399 left: self.iter().peekable(),
400 right: other.iter().peekable(),
401 }
402 }
403
404 pub fn union<'a>(&'a self, other: &'a Self) -> SmallSetUnion<'a> {
405 SmallSetUnion {
406 left: self.iter().peekable(),
407 right: other.iter().peekable(),
408 }
409 }
410
411 pub fn contains(&self, asn: Asn) -> bool {
412 self.0.binary_search(&asn).is_ok()
413 }
414
415 }
417
418impl iter::FromIterator<Asn> for SmallAsnSet {
419 fn from_iter<T: IntoIterator<Item = Asn>>(iter: T) -> Self {
420 let mut res = Self(iter.into_iter().collect());
421 res.0.sort();
422 res
423 }
424}
425
426impl<'a> IntoIterator for &'a SmallAsnSet {
427 type Item = Asn;
428 type IntoIter = SmallSetIter<'a>;
429
430 fn into_iter(self) -> Self::IntoIter {
431 self.0.iter().cloned()
432 }
433}
434
435pub type SmallSetIter<'a> = iter::Cloned<slice::Iter<'a, Asn>>;
438
439pub struct SmallSetDifference<'a> {
442 left: Peekable<SmallSetIter<'a>>,
443 right: Peekable<SmallSetIter<'a>>,
444}
445
446impl<'a> Iterator for SmallSetDifference<'a> {
447 type Item = Asn;
448
449 fn next(&mut self) -> Option<Self::Item> {
450 loop {
451 match (self.left.peek(), self.right.peek()) {
452 (None, _) => return None,
453 (Some(_), None) => return self.left.next(),
454 (Some(left), Some(right)) => match left.cmp(right) {
455 Ordering::Less => return self.left.next(),
456 Ordering::Equal => {
457 let _ = self.left.next();
458 let _ = self.right.next();
459 }
460 Ordering::Greater => {
461 let _ = self.right.next();
462 }
463 },
464 }
465 }
466 }
467}
468
469pub struct SmallSetSymmetricDifference<'a> {
472 left: Peekable<SmallSetIter<'a>>,
473 right: Peekable<SmallSetIter<'a>>,
474}
475
476impl<'a> Iterator for SmallSetSymmetricDifference<'a> {
477 type Item = Asn;
478
479 fn next(&mut self) -> Option<Self::Item> {
480 loop {
481 match (self.left.peek(), self.right.peek()) {
482 (None, None) => return None,
483 (Some(_), None) => return self.left.next(),
484 (None, Some(_)) => return self.right.next(),
485 (Some(left), Some(right)) => match left.cmp(right) {
486 Ordering::Equal => {
487 let _ = self.left.next();
488 let _ = self.right.next();
489 }
490 Ordering::Less => return self.left.next(),
491 Ordering::Greater => return self.right.next(),
492 },
493 }
494 }
495 }
496}
497
498pub struct SmallSetIntersection<'a> {
501 left: Peekable<SmallSetIter<'a>>,
502 right: Peekable<SmallSetIter<'a>>,
503}
504
505impl<'a> Iterator for SmallSetIntersection<'a> {
506 type Item = Asn;
507
508 fn next(&mut self) -> Option<Self::Item> {
509 loop {
510 match (self.left.peek(), self.right.peek()) {
511 (None, _) | (_, None) => return None,
512 (Some(left), Some(right)) => match left.cmp(right) {
513 Ordering::Equal => {
514 let _ = self.left.next();
515 return self.right.next();
516 }
517 Ordering::Less => {
518 let _ = self.left.next();
519 }
520 Ordering::Greater => {
521 let _ = self.right.next();
522 }
523 },
524 }
525 }
526 }
527}
528
529pub struct SmallSetUnion<'a> {
532 left: Peekable<SmallSetIter<'a>>,
533 right: Peekable<SmallSetIter<'a>>,
534}
535
536impl<'a> Iterator for SmallSetUnion<'a> {
537 type Item = Asn;
538
539 fn next(&mut self) -> Option<Self::Item> {
540 match (self.left.peek(), self.right.peek()) {
541 (None, None) => None,
542 (Some(_), None) => self.left.next(),
543 (None, Some(_)) => self.right.next(),
544 (Some(left), Some(right)) => match left.cmp(right) {
545 Ordering::Less => self.left.next(),
546 Ordering::Equal => {
547 let _ = self.left.next();
548 self.right.next()
549 }
550 Ordering::Greater => self.right.next(),
551 },
552 }
553 }
554}
555
556#[derive(Clone, Copy, Debug, Eq, PartialEq)]
561pub struct ParseAsnError;
562
563impl fmt::Display for ParseAsnError {
564 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
565 f.write_str("invalid AS number")
566 }
567}
568
569impl error::Error for ParseAsnError {}
570
571#[derive(Clone, Copy, Debug, Eq, PartialEq)]
574pub struct LargeAsnError;
575
576impl fmt::Display for LargeAsnError {
577 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
578 f.write_str("ASN too large")
579 }
580}
581
582impl error::Error for LargeAsnError {}
583
584#[derive(Clone, Copy, Debug)]
587pub struct LongSegmentError;
588
589impl fmt::Display for LongSegmentError {
590 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
591 f.write_str("path segment too long")
592 }
593}
594
595impl error::Error for LongSegmentError {}
596
597#[derive(Clone, Copy, Debug)]
600pub struct InvalidSegmentTypeError;
601
602impl fmt::Display for InvalidSegmentTypeError {
603 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
604 f.write_str("invalid segment type")
605 }
606}
607
608impl error::Error for InvalidSegmentTypeError {}
609
610#[cfg(all(test, feature = "serde"))]
613mod test_serde {
614 use super::*;
615 use serde_test::{assert_de_tokens, assert_tokens, Token};
616
617 #[test]
618 fn asn() {
619 #[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)]
620 struct AsnTest(
621 Asn,
622 #[serde(
623 deserialize_with = "Asn::deserialize_from_u32",
624 serialize_with = "Asn::serialize_as_u32"
625 )]
626 Asn,
627 #[serde(
628 deserialize_with = "Asn::deserialize_from_str",
629 serialize_with = "Asn::serialize_as_str"
630 )]
631 Asn,
632 );
633
634 assert_tokens(
635 &AsnTest(Asn(0), Asn(0), Asn(0)),
636 &[
637 Token::TupleStruct {
638 name: "AsnTest",
639 len: 3,
640 },
641 Token::NewtypeStruct { name: "Asn" },
642 Token::U32(0),
643 Token::U32(0),
644 Token::Str("AS0"),
645 Token::TupleStructEnd,
646 ],
647 );
648 }
649
650 #[test]
651 fn asn_any() {
652 #[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)]
653 struct AsnTest(
654 #[serde(deserialize_with = "Asn::deserialize_from_any")] Asn,
655 #[serde(deserialize_with = "Asn::deserialize_from_any")] Asn,
656 #[serde(deserialize_with = "Asn::deserialize_from_any")] Asn,
657 #[serde(deserialize_with = "Asn::deserialize_from_any")] Asn,
658 #[serde(deserialize_with = "Asn::deserialize_from_any")] Asn,
659 #[serde(deserialize_with = "Asn::deserialize_from_any")] Asn,
660 );
661
662 assert_de_tokens(
663 &AsnTest(Asn(0), Asn(0), Asn(0), Asn(0), Asn(0), Asn(0)),
664 &[
665 Token::TupleStruct {
666 name: "AsnTest",
667 len: 5,
668 },
669 Token::U32(0),
670 Token::U64(0),
671 Token::I64(0),
672 Token::Str("0"),
673 Token::Str("AS0"),
674 Token::Str("As0"),
675 Token::TupleStructEnd,
676 ],
677 );
678 }
679}
680
681#[cfg(test)]
682mod tests {
683 use super::*;
684 use std::collections::HashSet;
685
686 #[test]
687 fn asn() {
688 assert_eq!(Asn::from_u32(1234), Asn(1234));
689 assert_eq!(Asn(1234).into_u32(), 1234);
690
691 assert_eq!(Asn::from(1234_u32), Asn(1234));
692 assert_eq!(u32::from(Asn(1234)), 1234_u32);
693
694 assert_eq!(format!("{}", Asn(1234)).as_str(), "AS1234");
695
696 assert_eq!("0".parse::<Asn>(), Ok(Asn(0)));
697 assert_eq!("AS1234".parse::<Asn>(), Ok(Asn(1234)));
698 assert_eq!("as1234".parse::<Asn>(), Ok(Asn(1234)));
699 assert_eq!("As1234".parse::<Asn>(), Ok(Asn(1234)));
700 assert_eq!("aS1234".parse::<Asn>(), Ok(Asn(1234)));
701 assert_eq!("1234".parse::<Asn>(), Ok(Asn(1234)));
702
703 assert_eq!("".parse::<Asn>(), Err(ParseAsnError));
704 assert_eq!("-1234".parse::<Asn>(), Err(ParseAsnError));
705 assert_eq!("4294967296".parse::<Asn>(), Err(ParseAsnError));
706 }
707
708 macro_rules! check_set_fn {
713 ( $fn:ident, $left:expr, $right:expr $(,)? ) => {{
714 let left = Vec::from_iter($left.into_iter().map(Asn::from_u32));
715 let right = Vec::from_iter($right.into_iter().map(Asn::from_u32));
716
717 let set_fn = {
718 let left = SmallAsnSet::from_iter(left.clone().into_iter());
719 let right = SmallAsnSet::from_iter(right.clone().into_iter());
720 left.$fn(&right).collect::<HashSet<Asn>>()
721 };
722 let hash_fn: HashSet<Asn> = {
723 let left: HashSet<Asn> =
724 HashSet::from_iter(left.clone().into_iter());
725 let right: HashSet<Asn> =
726 HashSet::from_iter(right.clone().into_iter());
727 left.$fn(&right).cloned().collect()
728 };
729 assert_eq!(set_fn, hash_fn);
730 }};
731 }
732
733 macro_rules! check_all_set_fns {
734 ( $left:expr, $right:expr $(,)? ) => {{
735 check_set_fn!(difference, $left, $right);
736 check_set_fn!(symmetric_difference, $left, $right);
737 check_set_fn!(intersection, $left, $right);
738 check_set_fn!(union, $left, $right);
739 }};
740 }
741
742 #[test]
743 fn small_set_operations() {
744 check_all_set_fns!([0, 1, 2, 3], [0, 1, 2, 3]);
745 check_all_set_fns!([0, 1, 2], [0, 1, 2, 3]);
746 check_all_set_fns!([0, 1, 2, 3], [0, 1, 2]);
747 check_all_set_fns!([0, 1, 2, 3], [0, 1, 2]);
748 check_all_set_fns!([], []);
749 check_all_set_fns!([1, 2, 3], []);
750 check_all_set_fns!([], [1, 2, 3]);
751 }
752}