///|
pub(all) struct Route {
id : Int32
address : String
} derive(Eq, Debug)
///|
pub extend Route with Eq::{equal, not_equal}
///|
pub extend Route with @debug.Debug::{to_repr}
///|
pub struct Router {
priv routes : Array[Route]
priv capacity : Int32
}
///|
pub fn Router::new(capacity~ : Int32 = 256) -> Router raise OscError {
if capacity < 1 || capacity > 4096 {
raise Limit("route capacity must be 1..4096")
}
{ routes: [], capacity, }
}
///|
pub fn Router::add(
self : Router,
id : Int32,
address : String,
) -> Unit raise OscError {
validate_method(address)
if address.length() > 4096 {
raise Limit("method length")
}
if id < 0 {
raise Invalid("route id must be nonnegative", 0)
}
for route in self.routes {
if route.id == id || route.address == address {
raise Invalid("duplicate route id or address", 0)
}
}
if self.routes.length() >= self.capacity {
raise Limit("route capacity")
}
self.routes.push({ id, address, })
}
///|
pub fn Router::remove(self : Router, id : Int32) -> Bool {
for i in 0.. Array[Route] {
self.routes.copy()
}
///|
pub fn Router::len(self : Router) -> Int32 {
self.routes.length()
}
///|
/// The message supplies the pattern; registered destinations are literal paths.
pub fn Router::resolve(
self : Router,
address : String,
work_limit~ : Int32 = 1000000,
) -> Array[Route] raise OscError {
let pattern = compile_pattern(address)
let work = Ref(0)
let out : Array[Route] = []
for route in self.routes {
if pattern.match_budget(route.address, work_limit, work) {
out.push(route)
}
}
out
}