Skip to main content

sciparse/proto/dataplane_path/
types.rs

1// Copyright 2026 Anapaya Systems
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//   http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Standard SCION path types and related structures.
16
17use std::{borrow::Cow, fmt::Debug};
18
19/// Path types used in SCION packets.
20///
21/// See the [IETF SCION-dataplane RFC draft][rfc] for possible values.
22///
23///[rfc]: https://www.ietf.org/archive/id/draft-dekater-scion-dataplane-00.html#name-common-header
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
25#[repr(u8)]
26pub enum PathType {
27    /// The empty path type.
28    Empty = 0,
29    /// The standard SCION path type.
30    Scion = 1,
31    /// One-hop paths between neighboring border routers.
32    OneHop = 2,
33    /// Experimental Epic path type.
34    Epic = 3,
35    /// Experimental Colibri path type.
36    Colibri = 4,
37    /// Other, unrecognized path types.
38    Other(u8),
39}
40impl From<u8> for PathType {
41    #[inline]
42    fn from(value: u8) -> Self {
43        match value {
44            0 => PathType::Empty,
45            1 => PathType::Scion,
46            2 => PathType::OneHop,
47            3 => PathType::Epic,
48            4 => PathType::Colibri,
49            other => PathType::Other(other),
50        }
51    }
52}
53impl From<PathType> for u8 {
54    #[inline]
55    fn from(val: PathType) -> Self {
56        match val {
57            PathType::Empty => 0,
58            PathType::Scion => 1,
59            PathType::OneHop => 2,
60            PathType::Epic => 3,
61            PathType::Colibri => 4,
62            PathType::Other(other) => other,
63        }
64    }
65}
66
67/// Support for [`proptest::arbitrary`].
68#[cfg(feature = "proptest")]
69pub mod ptest {
70    use ::proptest::prelude::*;
71
72    use super::*;
73
74    /// Configuration for generating arbitrary [`PathType`] values.
75    ///
76    /// Controls the relative probability of each variant being generated.
77    ///
78    /// Default weights: `empty = 1, scion = 4, one_hop = 2, epic = 1, colibri = 1, other = 1`.
79    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
80    pub struct ArbitraryPathTypeParams {
81        /// Weight for generating Empty path type.
82        pub empty: u32,
83        /// Weight for generating Scion (standard) path type.
84        pub scion: u32,
85        /// Weight for generating OneHop path type.
86        pub one_hop: u32,
87        /// Weight for generating Epic path type.
88        pub epic: u32,
89        /// Weight for generating Colibri path type.
90        pub colibri: u32,
91        /// Weight for generating Other (unknown) path types.
92        pub other: u32,
93    }
94    impl Default for ArbitraryPathTypeParams {
95        fn default() -> Self {
96            Self {
97                empty: 1,
98                scion: 4,
99                one_hop: 2,
100                epic: 1,
101                colibri: 1,
102                other: 1,
103            }
104        }
105    }
106
107    impl Arbitrary for PathType {
108        type Parameters = ArbitraryPathTypeParams;
109        type Strategy = BoxedStrategy<Self>;
110
111        fn arbitrary_with(params: Self::Parameters) -> Self::Strategy {
112            prop_oneof![
113                params.empty => Just(PathType::Empty),
114                params.scion => Just(PathType::Scion),
115                params.one_hop => Just(PathType::OneHop),
116                params.epic => Just(PathType::Epic),
117                params.colibri => Just(PathType::Colibri),
118                params.other => (5u8..=255).prop_map(PathType::Other),
119            ]
120            .boxed()
121        }
122    }
123}
124
125/// Error type for path reversal failures.
126#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
127#[error("Cannot reverse path: {reason}")]
128pub struct PathReverseError {
129    /// A human-readable reason for the failure.
130    pub reason: Cow<'static, str>,
131}
132impl PathReverseError {
133    /// Creates a new `PathReverseError` with the given reason.
134    #[inline]
135    pub fn new(reason: impl Into<Cow<'static, str>>) -> Self {
136        Self {
137            reason: reason.into(),
138        }
139    }
140}