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}