///|
fn parse_decimal_portion(
input : String,
offset : Int,
kind : ProxyErrorKind,
) -> Result[Int, ProxyError] {
let chars = input.to_array()
if chars.length() == 0 {
return Err(proxy_error(kind, offset, "empty decimal component"))
}
let mut value = 0
for i = 0; i < chars.length(); i = i + 1 {
let code = chars[i].to_int()
if code < '0'.to_int() || code > '9'.to_int() {
return Err(proxy_error(kind, offset + i, "decimal digits only"))
}
value = value * 10 + code - '0'.to_int()
if value > 65535 {
return Err(proxy_error(kind, offset + i, "decimal value out of range"))
}
}
Ok(value)
}
///|
pub fn parse_port_text(input : String) -> Result[Int, ProxyError] {
match parse_decimal_portion(input, 0, InvalidPort) {
Err(err) => Err(err)
Ok(port) =>
if port > 65535 {
Err(proxy_error(InvalidPort, 0, "port must be in 0..65535"))
} else {
Ok(port)
}
}
}
///|
pub fn parse_ipv4_text(input : String) -> Result[Ipv4Address, ProxyError] {
let pieces = input.split(".").to_array()
if pieces.length() != 4 {
return Err(
proxy_error(
InvalidIpv4,
0,
"IPv4 requires exactly four decimal components",
),
)
}
let values = Array::make(4, b'\x00')
let mut offset = 0
for i = 0; i < 4; i = i + 1 {
let part = pieces[i].to_owned()
match parse_decimal_portion(part, offset, InvalidIpv4) {
Err(err) => return Err(err)
Ok(value) => {
if value > 255 {
return Err(
proxy_error(InvalidIpv4, offset, "IPv4 component is out of range"),
)
}
// Decimal leading zeroes are accepted by the PROXY v1 grammar; values stay decimal.
values[i] = value.to_byte()
}
}
offset = offset + part.length() + 1
}
Ipv4Address::new(Bytes::from_array(values).to_fixedarray())
}
///|
pub fn format_ipv4(address : Ipv4Address) -> String {
"\{address.octets[0].to_int()}.\{address.octets[1].to_int()}.\{address.octets[2].to_int()}.\{address.octets[3].to_int()}"
}