pub use crate::generated::route_registry::{
KnownRoute, RouteDescriptor, RouteFamily, RouteImplementation, RouteLocality, RouteMaturity,
KNOWN_ROUTE_DESCRIPTORS,
};
pub fn normalize_route(value: &str) -> Option<KnownRoute> {
let normalized = value.trim().to_ascii_lowercase();
KNOWN_ROUTE_DESCRIPTORS
.iter()
.find(|descriptor| descriptor.id == normalized)
.map(|descriptor| descriptor.route)
}
pub fn rank_routes(configured_priority: &[String], candidates: &[String]) -> Vec<String> {
let configured = unique_known(configured_priority);
let priority = if configured.is_empty() {
KnownRoute::DEFAULT_PRIORITY.to_vec()
} else {
configured
};
let candidates = unique_known(candidates);
let mut ranked: Vec<(KnownRoute, usize)> = candidates
.into_iter()
.enumerate()
.map(|(candidate_index, route)| (route, candidate_index))
.collect();
ranked.sort_by(|(left, left_index), (right, right_index)| {
route_sort_key(*left, *left_index, &priority).cmp(&route_sort_key(
*right,
*right_index,
&priority,
))
});
ranked
.into_iter()
.map(|(route, _)| route.as_str().to_string())
.collect()
}
fn unique_known(values: &[String]) -> Vec<KnownRoute> {
let mut result = Vec::new();
for value in values {
let Some(route) = normalize_route(value) else {
continue;
};
if !result.contains(&route) {
result.push(route);
}
}
result
}
fn route_sort_key(
route: KnownRoute,
candidate_index: usize,
configured_priority: &[KnownRoute],
) -> (u8, usize, u8, usize) {
match configured_priority
.iter()
.position(|candidate| *candidate == route)
{
Some(configured_index) => (0, configured_index, route.default_rank(), candidate_index),
None => (1, 0, route.default_rank(), candidate_index),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct PolicyVectors {
routes: Vec<RegistryRoute>,
default_priority: Vec<String>,
rank_routes: Vec<RankRoutesVector>,
}
#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct RegistryRoute {
id: String,
base_protocol: String,
family: String,
implementation: String,
locality: String,
maturity: String,
default_rank: u8,
browser: bool,
native: bool,
independently_instantiable: bool,
}
#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct RankRoutesVector {
configured_priority: Vec<String>,
candidates: Vec<String>,
expected: Vec<String>,
}
#[test]
fn known_route_descriptors_have_unique_stable_ranks() {
let mut ranks: Vec<_> = KNOWN_ROUTE_DESCRIPTORS
.iter()
.map(|descriptor| descriptor.default_rank)
.collect();
ranks.sort_unstable();
ranks.dedup();
assert_eq!(ranks, (0..9).collect::<Vec<_>>());
}
#[test]
fn generated_descriptors_match_the_canonical_registry() {
let registry: PolicyVectors =
serde_json::from_str(crate::generated::route_registry::TRANSPORT_REGISTRY_JSON)
.expect("transport registry");
assert_eq!(registry.routes.len(), KNOWN_ROUTE_DESCRIPTORS.len());
for descriptor in KNOWN_ROUTE_DESCRIPTORS {
let expected = registry
.routes
.iter()
.find(|route| route.id == descriptor.id)
.unwrap_or_else(|| panic!("missing registry route {}", descriptor.id));
assert_eq!(expected.base_protocol, descriptor.base_protocol);
assert_eq!(expected.default_rank, descriptor.default_rank);
assert_eq!(expected.browser, descriptor.browser);
assert_eq!(expected.native, descriptor.native);
assert_eq!(
expected.independently_instantiable,
descriptor.independently_instantiable
);
assert_eq!(expected.family, serialized_name(descriptor.family));
assert_eq!(
expected.implementation,
serialized_name(descriptor.implementation)
);
assert_eq!(expected.locality, serialized_name(descriptor.locality));
assert_eq!(expected.maturity, serialized_name(descriptor.maturity));
}
assert_eq!(
registry.default_priority,
KnownRoute::DEFAULT_PRIORITY
.iter()
.map(|route| route.as_str().to_string())
.collect::<Vec<_>>()
);
}
fn serialized_name<T: serde::Serialize>(value: T) -> String {
serde_json::to_value(value)
.expect("serialize registry enum")
.as_str()
.expect("registry enum serializes as string")
.to_string()
}
#[test]
fn normalization_is_case_and_whitespace_insensitive() {
assert_eq!(normalize_route(" IROH-QUIC "), Some(KnownRoute::IrohQuic));
assert_eq!(normalize_route("WebRTC-LAN"), Some(KnownRoute::WebRtcLan));
assert_eq!(normalize_route(" webtransport "), None);
}
#[test]
fn ranking_deduplicates_and_ignores_unknown_routes() {
let configured = strings(["webrtc", "iroh-lan"]);
let candidates = strings([" IROH-LAN ", "unknown", "webrtc", "webrtc", "moq"]);
assert_eq!(
rank_routes(&configured, &candidates),
strings(["webrtc", "iroh-lan", "moq"])
);
}
#[test]
fn empty_priority_preserves_the_public_default_order() {
let candidates = strings([
"iroh",
"moq",
"webrtc",
"ble",
"webrtc-lan",
"iroh-lan",
"iroh-quic",
"iroh-relay",
"webrtc-turn",
]);
assert_eq!(
rank_routes(&[], &candidates),
strings([
"iroh-lan",
"webrtc-lan",
"ble",
"webrtc",
"moq",
"iroh",
"iroh-quic",
"iroh-relay",
"webrtc-turn",
])
);
}
#[test]
fn vectors_are_shared_with_other_language_consumers() {
let vectors: PolicyVectors =
serde_json::from_str(crate::generated::route_registry::TRANSPORT_REGISTRY_JSON)
.expect("transport policy vectors");
for vector in vectors.rank_routes {
assert_eq!(
rank_routes(&vector.configured_priority, &vector.candidates),
vector.expected,
"configured={:?} candidates={:?}",
vector.configured_priority,
vector.candidates
);
}
}
fn strings<const N: usize>(values: [&str; N]) -> Vec<String> {
values.into_iter().map(str::to_string).collect()
}
}