use crate::route_policy::{KnownRoute, RouteFamily, RouteLocality};
pub(crate) const IROH: &str = KnownRoute::Iroh.as_str();
pub(crate) const IROH_QUIC: &str = KnownRoute::IrohQuic.as_str();
pub(crate) const IROH_RELAY: &str = KnownRoute::IrohRelay.as_str();
pub(crate) const IROH_LAN: &str = KnownRoute::IrohLan.as_str();
pub(crate) const BLE: &str = KnownRoute::Ble.as_str();
pub(crate) const WEBRTC: &str = KnownRoute::WebRtc.as_str();
pub(crate) const WEBRTC_LAN: &str = KnownRoute::WebRtcLan.as_str();
pub(crate) const WEBRTC_TURN: &str = KnownRoute::WebRtcTurn.as_str();
pub(crate) const MOQ: &str = KnownRoute::Moq.as_str();
pub(crate) fn normalize(value: &str) -> Option<&'static str> {
crate::route_policy::normalize_route(value).map(KnownRoute::as_str)
}
#[allow(dead_code)]
pub(crate) fn is_iroh_base(value: &str) -> bool {
crate::route_policy::normalize_route(value)
.map(|route| route.descriptor().base_protocol == IROH)
.unwrap_or(false)
}
#[allow(dead_code)]
pub(crate) fn is_direct_iroh(value: &str) -> bool {
crate::route_policy::normalize_route(value)
.map(|route| {
let descriptor = route.descriptor();
descriptor.base_protocol == IROH
&& matches!(
descriptor.locality,
RouteLocality::Nearby | RouteLocality::DirectInternet
)
})
.unwrap_or(false)
}
#[allow(dead_code)]
pub(crate) fn is_optional(value: &str) -> bool {
crate::route_policy::normalize_route(value)
.map(|route| route.descriptor().family == RouteFamily::OptionalRoute)
.unwrap_or(false)
}
#[allow(dead_code)]
pub(crate) fn is_webrtc(value: &str) -> bool {
crate::route_policy::normalize_route(value)
.map(|route| route.descriptor().base_protocol == WEBRTC)
.unwrap_or(false)
}
pub(crate) fn is_independent_transport(value: &str) -> bool {
crate::route_policy::normalize_route(value)
.map(|route| route.descriptor().independently_instantiable)
.unwrap_or(false)
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct TransportPolicyVectors {
labels: Vec<LabelVector>,
}
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct LabelVector {
input: String,
normalized: Option<String>,
iroh_base: bool,
direct_iroh: bool,
optional: bool,
web_rtc: bool,
independent: bool,
}
#[test]
fn normalizes_official_labels_case_insensitively() {
for (input, expected) in [
("iroh", IROH),
(" IROH-QUIC ", IROH_QUIC),
("iroh-relay", IROH_RELAY),
("iroh-lan", IROH_LAN),
("ble", BLE),
("webrtc", WEBRTC),
("webrtc-lan", WEBRTC_LAN),
("webrtc-turn", WEBRTC_TURN),
("moq", MOQ),
] {
assert_eq!(normalize(input), Some(expected));
}
assert_eq!(normalize("lan"), None);
assert_eq!(normalize("webtransport"), None);
}
#[test]
fn classifies_transport_families() {
assert!(is_iroh_base(IROH));
assert!(is_iroh_base(IROH_QUIC));
assert!(is_iroh_base(IROH_LAN));
assert!(is_iroh_base(IROH_RELAY));
assert!(is_iroh_base(BLE));
assert!(!is_iroh_base(WEBRTC));
assert!(is_direct_iroh(IROH_QUIC));
assert!(is_direct_iroh(IROH_LAN));
assert!(is_direct_iroh(BLE));
assert!(!is_direct_iroh(IROH_RELAY));
assert!(is_optional(WEBRTC));
assert!(is_optional(WEBRTC_LAN));
assert!(is_optional(WEBRTC_TURN));
assert!(is_optional(MOQ));
assert!(!is_optional(IROH_QUIC));
assert!(is_webrtc(WEBRTC));
assert!(is_webrtc(WEBRTC_LAN));
assert!(is_webrtc(WEBRTC_TURN));
assert!(!is_webrtc(MOQ));
assert!(is_independent_transport(WEBRTC));
assert!(is_independent_transport(MOQ));
assert!(!is_independent_transport(WEBRTC_LAN));
}
#[test]
fn matches_shared_transport_policy_vectors() {
let vectors: TransportPolicyVectors =
serde_json::from_str(crate::generated::route_registry::TRANSPORT_REGISTRY_JSON)
.expect("transport policy vectors");
for vector in vectors.labels {
assert_eq!(
normalize(&vector.input),
vector.normalized.as_deref(),
"normalize({:?})",
vector.input
);
assert_eq!(
is_iroh_base(&vector.input),
vector.iroh_base,
"is_iroh_base({:?})",
vector.input
);
assert_eq!(
is_direct_iroh(&vector.input),
vector.direct_iroh,
"is_direct_iroh({:?})",
vector.input
);
assert_eq!(
is_optional(&vector.input),
vector.optional,
"is_optional({:?})",
vector.input
);
assert_eq!(
is_webrtc(&vector.input),
vector.web_rtc,
"is_webrtc({:?})",
vector.input
);
assert_eq!(
is_independent_transport(&vector.input),
vector.independent,
"is_independent_transport({:?})",
vector.input
);
}
}
}