///|
/// Inclusive transport port interval. Construction rejects invalid endpoints.
pub struct Ports {
low : Int
high : Int
} derive(Eq, Debug)
///|
pub fn Ports::new(low : Int, high : Int) -> Ports raise PolicyError {
if low < 0 || high > 65535 || low > high {
raise Invalid("port interval must satisfy 0 <= low <= high <= 65535")
}
{ low, high }
}
///|
pub fn Ports::any() -> Ports {
{ low: 0, high: 65535 }
}
///|
pub fn Ports::contains(self : Ports, port : Int) -> Bool {
self.low <= port && port <= self.high
}
///|
pub fn Ports::bounds(self : Ports) -> (Int, Int) {
(self.low, self.high)
}
///|
fn decimal(s : String) -> Int raise PolicyError {
if s.length() == 0 || s.length() > 5 {
raise Invalid("invalid port number")
}
let mut n = 0
for c in s.iter() {
if c < '0' || c > '9' {
raise Invalid("expected decimal digits")
}
n = n * 10 + c.to_int() - 48
}
n
}
///|
pub fn Ports::parse(s : String) -> Ports raise PolicyError {
if s == "*" {
return Ports::any()
}
let parts = s.split("-").map(x => x.to_owned()).to_array()
match parts {
[a] => {
let n = decimal(a)
Ports::new(n, n)
}
[a, b] => Ports::new(decimal(a), decimal(b))
_ => raise Invalid("expected *, port or low-high")
}
}
///|
pub fn Ports::render(self : Ports) -> String {
if self == Ports::any() {
"*"
} else if self.low == self.high {
self.low.to_string()
} else {
"\{self.low}-\{self.high}"
}
}