use std::collections::HashMap;
use super::error::SubnetError;
use super::id::SubnetId;
use crate::adapter::net::behavior::capability::CapabilitySet;
use crate::adapter::net::behavior::tag::Tag;
#[derive(Debug, Clone)]
pub struct SubnetPolicy {
rules: Vec<SubnetRule>,
}
#[derive(Debug, Clone)]
pub struct SubnetRule {
pub tag_prefix: String,
pub level: u8,
pub values: HashMap<String, u8>,
}
impl SubnetPolicy {
pub fn new() -> Self {
Self { rules: Vec::new() }
}
#[expect(
clippy::expect_used,
reason = "documented panicking variant; try_add_rule is the fallible alternative for untrusted input"
)]
pub fn add_rule(self, rule: SubnetRule) -> Self {
self.try_add_rule(rule)
.expect("SubnetPolicy::add_rule: invalid rule (use try_add_rule for fallible)")
}
pub fn try_add_rule(mut self, rule: SubnetRule) -> Result<Self, SubnetError> {
if rule.level >= 4 {
return Err(SubnetError::LevelOutOfRange { got: rule.level });
}
self.rules.push(rule);
Ok(self)
}
pub fn can_assign_non_global(&self) -> bool {
self.rules.iter().any(|rule| {
rule.values.iter().any(|(value, &level_value)| {
let matches_only_the_empty_tag = rule.tag_prefix.is_empty() && value.is_empty();
level_value != 0 && !matches_only_the_empty_tag
})
})
}
pub fn assign(&self, caps: &CapabilitySet) -> SubnetId {
let tags: Vec<std::borrow::Cow<'_, str>> = caps.tags.iter().map(Tag::as_wire).collect();
self.assign_from_tag_strs(&tags)
}
pub fn assign_from_rendered_tags(&self, tags: &[String]) -> SubnetId {
self.assign_from_tag_strs(tags)
}
fn assign_from_tag_strs<S: AsRef<str>>(&self, tags: &[S]) -> SubnetId {
let mut levels = [0u8; 4];
for rule in &self.rules {
let mut winner: Option<(&str, u8)> = None;
for tag in tags {
let tag = tag.as_ref();
if tag.is_empty() {
continue;
}
let Some(value) = tag.strip_prefix(&rule.tag_prefix) else {
continue;
};
let Some(&level_value) = rule.values.get(value) else {
continue;
};
if level_value == 0 {
continue;
}
let better = match winner {
Some((current, _)) => tag < current,
None => true,
};
if better {
winner = Some((tag, level_value));
}
}
if let Some((_, level_value)) = winner {
levels[rule.level as usize] = level_value;
}
}
SubnetId::new(&levels)
}
}
impl Default for SubnetPolicy {
fn default() -> Self {
Self::new()
}
}
impl SubnetRule {
pub fn new(tag_prefix: impl Into<String>, level: u8) -> Self {
Self {
tag_prefix: tag_prefix.into(),
level,
values: HashMap::new(),
}
}
#[expect(
clippy::expect_used,
reason = "documented panicking variant; try_map is the fallible alternative for untrusted input"
)]
pub fn map(self, tag_value: impl Into<String>, level_value: u8) -> Self {
self.try_map(tag_value, level_value)
.expect("SubnetRule::map: level_value 0 is reserved (use try_map for fallible)")
}
pub fn try_map(
mut self,
tag_value: impl Into<String>,
level_value: u8,
) -> Result<Self, SubnetError> {
if level_value == 0 {
return Err(SubnetError::LevelValueReserved);
}
self.values.insert(tag_value.into(), level_value);
Ok(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::adapter::net::behavior::capability::CapabilitySet;
fn caps_with_tags(tags: &[&str]) -> CapabilitySet {
let mut caps = CapabilitySet::new();
for tag in tags {
caps = caps.add_tag(*tag);
}
caps
}
#[test]
fn test_empty_policy() {
let policy = SubnetPolicy::new();
let caps = caps_with_tags(&["region:us-west"]);
assert_eq!(policy.assign(&caps), SubnetId::GLOBAL);
}
#[test]
fn assign_from_rendered_tags_agrees_with_assign() {
let policy = SubnetPolicy::new()
.add_rule(SubnetRule::new("region:", 0).map("us", 3).map("eu", 4))
.add_rule(SubnetRule::new("fleet:", 1).map("blue", 7).map("green", 8))
.add_rule(SubnetRule::new("unit:", 2).map("alpha", 2));
let tag_sets: Vec<Vec<&str>> = vec![
vec![],
vec!["region:us"],
vec!["region:eu", "fleet:green"],
vec!["region:us", "fleet:blue", "unit:alpha"],
vec!["region:antarctica"],
vec!["gpu", "hardware.gpu", "region:us", "scope:tenant:oem-123"],
vec!["region:us", "region:eu"],
vec!["region:eu", "region:us"],
];
for tags in tag_sets {
let caps = caps_with_tags(&tags);
let rendered: Vec<String> = caps.tags.iter().map(|t| t.to_string()).collect();
assert_eq!(
policy.assign_from_rendered_tags(&rendered),
policy.assign(&caps),
"divergence for tags {tags:?}"
);
}
}
#[test]
fn assign_from_rendered_tags_is_order_independent() {
let policy = SubnetPolicy::new().add_rule(
SubnetRule::new("region:", 0)
.map("us", 3)
.map("eu", 4)
.map("ap", 5),
);
let forward: Vec<String> = ["region:us", "region:eu", "region:ap"]
.iter()
.map(|s| s.to_string())
.collect();
let reversed: Vec<String> = forward.iter().rev().cloned().collect();
assert_eq!(
policy.assign_from_rendered_tags(&forward),
policy.assign_from_rendered_tags(&reversed),
"tag order must not change the assigned subnet"
);
}
#[test]
fn a_zero_mapping_cannot_erase_a_real_assignment() {
let mut zeroing = SubnetRule::new("region:", 0);
zeroing.values.insert("us".to_string(), 0);
let policy = SubnetPolicy::new()
.add_rule(SubnetRule::new("region:", 0).map("us", 3))
.add_rule(zeroing);
let tags = vec!["region:us".to_string()];
assert_eq!(
policy.assign_from_rendered_tags(&tags),
SubnetId::new(&[3]),
"a later rule mapping to the reserved 0 must not zero out an \
earlier rule's assignment"
);
assert!(
policy.can_assign_non_global(),
"and the predicate must agree — this policy really can scope"
);
}
#[test]
fn an_empty_prefix_and_value_cannot_match_any_tag() {
let impossible = SubnetPolicy::new().add_rule(SubnetRule::new("", 0).map("", 5));
for tag in ["gpu", "region:us", "hardware.gpu", "scope:tenant:acme"] {
assert_eq!(
impossible.assign_from_rendered_tags(&[tag.to_string()]),
SubnetId::GLOBAL,
"{tag} must not match an empty-prefix empty-value mapping"
);
}
assert!(
!impossible.can_assign_non_global(),
"a mapping that can never fire must not be reported as scoping"
);
assert_eq!(
impossible.assign_from_rendered_tags(&[String::new()]),
SubnetId::GLOBAL,
"an empty tag off the wire must not scope, or the predicate and \
the helper disagree about the same policy"
);
let prefix_only = SubnetPolicy::new().add_rule(SubnetRule::new("region:", 0).map("", 6));
assert_eq!(
prefix_only.assign_from_rendered_tags(&["region:".to_string()]),
SubnetId::new(&[6]),
"`region:` is a legal tag, so prefix + empty value is reachable"
);
assert!(prefix_only.can_assign_non_global());
}
#[test]
fn a_rule_with_only_zero_values_maps_nothing() {
let mut zero_only = SubnetRule::new("region:", 0);
zero_only.values.insert("us".to_string(), 0);
zero_only.values.insert("eu".to_string(), 0);
let policy = SubnetPolicy::new().add_rule(zero_only);
for tag in ["region:us", "region:eu"] {
assert_eq!(
policy.assign_from_rendered_tags(&[tag.to_string()]),
SubnetId::GLOBAL,
"{tag} maps only to the reserved 0, so nothing is assigned"
);
}
assert!(!policy.can_assign_non_global());
}
#[test]
fn test_single_level() {
let policy = SubnetPolicy::new().add_rule(
SubnetRule::new("region:", 0)
.map("us-west", 1)
.map("eu-central", 2),
);
let caps = caps_with_tags(&["region:us-west"]);
assert_eq!(policy.assign(&caps), SubnetId::new(&[1]));
let caps = caps_with_tags(&["region:eu-central"]);
assert_eq!(policy.assign(&caps), SubnetId::new(&[2]));
}
#[test]
fn test_multi_level() {
let policy = SubnetPolicy::new()
.add_rule(
SubnetRule::new("region:", 0)
.map("us-west", 1)
.map("eu-central", 2),
)
.add_rule(SubnetRule::new("fleet:", 1).map("alpha", 1).map("beta", 2));
let caps = caps_with_tags(&["region:us-west", "fleet:beta"]);
assert_eq!(policy.assign(&caps), SubnetId::new(&[1, 2]));
}
#[test]
fn test_unmatched_tag() {
let policy = SubnetPolicy::new().add_rule(SubnetRule::new("region:", 0).map("us-west", 1));
let caps = caps_with_tags(&["region:unknown"]);
assert_eq!(policy.assign(&caps), SubnetId::GLOBAL);
let caps = caps_with_tags(&["fleet:alpha"]);
assert_eq!(policy.assign(&caps), SubnetId::GLOBAL);
}
#[test]
fn test_partial_match() {
let policy = SubnetPolicy::new()
.add_rule(SubnetRule::new("region:", 0).map("us-west", 3))
.add_rule(SubnetRule::new("fleet:", 1).map("alpha", 7));
let caps = caps_with_tags(&["region:us-west"]);
assert_eq!(policy.assign(&caps), SubnetId::new(&[3]));
}
#[test]
fn test_four_levels() {
let policy = SubnetPolicy::new()
.add_rule(SubnetRule::new("region:", 0).map("us", 1))
.add_rule(SubnetRule::new("fleet:", 1).map("f1", 2))
.add_rule(SubnetRule::new("vehicle:", 2).map("v42", 3))
.add_rule(SubnetRule::new("subsystem:", 3).map("lidar", 4));
let caps = caps_with_tags(&["region:us", "fleet:f1", "vehicle:v42", "subsystem:lidar"]);
assert_eq!(policy.assign(&caps), SubnetId::new(&[1, 2, 3, 4]));
}
#[test]
fn duplicate_prefix_same_level_later_rule_wins() {
let policy = SubnetPolicy::new()
.add_rule(SubnetRule::new("region:", 0).map("us", 1))
.add_rule(SubnetRule::new("region:", 0).map("us", 9));
let caps = caps_with_tags(&["region:us"]);
assert_eq!(
policy.assign(&caps),
SubnetId::new(&[9]),
"a later rule with the same prefix + level must overwrite \
the earlier rule's value — pinned as last-write-wins",
);
}
#[test]
fn duplicate_prefix_different_levels_both_apply() {
let policy = SubnetPolicy::new()
.add_rule(SubnetRule::new("region:", 0).map("us", 1))
.add_rule(SubnetRule::new("region:", 2).map("us", 5));
let caps = caps_with_tags(&["region:us"]);
assert_eq!(
policy.assign(&caps),
SubnetId::new(&[1, 0, 5, 0]),
"two rules sharing a prefix but targeting different \
levels must both fire; level 1 + 3 remain unset",
);
}
#[test]
fn rule_order_dependency_later_rule_overwrites_earlier_level_write() {
let policy = SubnetPolicy::new()
.add_rule(SubnetRule::new("region:", 0).map("us", 1))
.add_rule(SubnetRule::new("zone:", 0).map("west", 4));
let caps = caps_with_tags(&["region:us", "zone:west"]);
assert_eq!(
policy.assign(&caps),
SubnetId::new(&[4]),
"later rule targeting the same level must overwrite earlier one",
);
let caps = caps_with_tags(&["region:us"]);
assert_eq!(
policy.assign(&caps),
SubnetId::new(&[1]),
"later rule does not clobber when it has no matching tag",
);
}
#[test]
fn partial_prefix_on_value_does_not_match() {
let policy = SubnetPolicy::new().add_rule(SubnetRule::new("region:", 0).map("us", 1));
let caps = caps_with_tags(&["region:us"]);
assert_eq!(policy.assign(&caps), SubnetId::new(&[1]));
let caps = caps_with_tags(&["region:us:extra"]);
assert_eq!(
policy.assign(&caps),
SubnetId::GLOBAL,
"values map is exact-match; suffixes after the matching \
inner token must not partial-match against the map key",
);
let policy = SubnetPolicy::new().add_rule(SubnetRule::new("region:", 0).map("us-west", 1));
let caps = caps_with_tags(&["region:us"]);
assert_eq!(
policy.assign(&caps),
SubnetId::GLOBAL,
"stripped value \"us\" is a prefix of \"us-west\" but \
must not partial-match the values map key",
);
}
#[test]
fn smallest_matching_tag_wins_within_a_single_rule() {
let policy =
SubnetPolicy::new().add_rule(SubnetRule::new("region:", 0).map("us", 1).map("eu", 2));
let caps = caps_with_tags(&["region:us", "region:eu"]);
assert_eq!(
policy.assign(&caps),
SubnetId::new(&[2]),
"lexicographically-first matching tag wins (`region:eu` < `region:us`)",
);
let caps = caps_with_tags(&["region:eu", "region:us"]);
assert_eq!(
policy.assign(&caps),
SubnetId::new(&[2]),
"insertion order is irrelevant — the same tag still wins",
);
}
#[test]
fn try_add_rule_rejects_level_out_of_range() {
let policy = SubnetPolicy::new();
let err = policy
.try_add_rule(SubnetRule::new("region:", 4).map("us", 1))
.unwrap_err();
assert!(
matches!(err, SubnetError::LevelOutOfRange { got: 4 }),
"expected LevelOutOfRange{{got: 4}}, got {:?}",
err
);
}
#[test]
fn try_add_rule_accepts_max_level() {
let policy = SubnetPolicy::new();
policy
.try_add_rule(SubnetRule::new("level3:", 3).map("x", 1))
.expect("level=3 must be accepted (boundary)");
}
#[test]
fn try_map_rejects_reserved_zero() {
let rule = SubnetRule::new("region:", 0);
let err = rule.try_map("us", 0).unwrap_err();
assert!(
matches!(err, SubnetError::LevelValueReserved),
"expected LevelValueReserved, got {:?}",
err
);
}
#[test]
fn try_map_accepts_one() {
SubnetRule::new("region:", 0)
.try_map("us", 1)
.expect("level_value=1 must be accepted (boundary)");
}
}