///|
fn decimal(text : StringView, maximum : Int) -> Int raise ParseError {
  if text.is_empty() {
    raise Invalid(0, "缺少十进制数字")
  }
  let mut value = 0
  for ch in text {
    if ch < '0' || ch > '9' {
      raise Invalid(0, "十进制数字无效")
    }
    value = value * 10 + ch.to_int() - 48
    if value > maximum {
      raise Invalid(0, "十进制数字超出范围")
    }
  }
  value
}

///|
fn ipv4_bytes(text : String) -> Bytes raise ParseError {
  let parts = text.split(".").to_array()
  if parts.length() != 4 {
    raise Invalid(0, "IPv4 地址必须包含四段")
  }
  let result = []
  for part in parts {
    if part.length() > 1 && part.has_prefix("0") {
      raise Invalid(0, "IPv4 地址不接受前导零")
    }
    result.push(decimal(part, 255).to_byte())
  }
  Bytes::from_array(result)
}

///|
fn hex_groups(text : StringView) -> Array[Int] raise ParseError {
  if text.is_empty() {
    return []
  }
  let groups = []
  for part in text.split(":") {
    if part.is_empty() || part.length() > 4 {
      raise Invalid(0, "IPv6 分组无效")
    }
    let mut value = 0
    for ch in part {
      let digit = if ch >= '0' && ch <= '9' {
        ch.to_int() - 48
      } else if ch >= 'a' && ch <= 'f' {
        ch.to_int() - 87
      } else {
        raise Invalid(0, "IPv6 十六进制数字无效")
      }
      value = value * 16 + digit
    }
    groups.push(value)
  }
  groups
}

///|
fn ip_bytes(text : String) -> (Int, Bytes) raise ParseError {
  if !text.contains(":") {
    return (1, ipv4_bytes(text))
  }
  let mut input = text.to_lower()
  if input.contains(".") {
    let (head, tail) = input.rev_split_once(":").unwrap()
    let bytes = ipv4_bytes(tail.to_owned())
    let a = (bytes[0].to_int() << 8) | bytes[1].to_int()
    let b = (bytes[2].to_int() << 8) | bytes[3].to_int()
    input = head.to_owned() +
      ":" +
      a.to_string(radix=16) +
      ":" +
      b.to_string(radix=16)
  }
  let parts = input.split("::").to_array()
  if parts.length() > 2 {
    raise Invalid(0, "IPv6 只能压缩一次")
  }
  let left = hex_groups(parts[0])
  let right = if parts.length() == 2 { hex_groups(parts[1]) } else { [] }
  let count = left.length() + right.length()
  if (parts.length() == 1 && count != 8) || (parts.length() == 2 && count >= 8) {
    raise Invalid(0, "IPv6 地址长度无效")
  }
  let groups = left + Array::make(8 - count, 0) + right
  let bytes = []
  for group in groups {
    bytes.push((group >> 8).to_byte())
    bytes.push(group.to_byte())
  }
  (2, Bytes::from_array(bytes))
}

///|
/// 库和 CLI 共用的文本解析;没有掩码的地址表示主机前缀。
pub fn parse_prefix_text(text : String) -> Prefix raise ParseError {
  let parts = text.split("/").to_array()
  if parts.length() > 2 || text.is_empty() {
    raise Invalid(0, "前缀文本无效")
  }
  let (afi, address) = ip_bytes(parts[0].to_owned())
  let length = if parts.length() == 2 {
    decimal(parts[1], address.length() * 8)
  } else {
    address.length() * 8
  }
  let bytes = [length.to_byte()]
  for i = 0; i < (length + 7) / 8; i = i + 1 {
    bytes.push(address[i])
  }
  parse_prefix(Bytes::from_array(bytes), afi)
}

///|
pub fn Prefix::contains(self : Prefix, other : Prefix) -> Bool {
  if self.afi != other.afi || self.length > other.length {
    return false
  }
  for i = 0; i < (self.length + 7) / 8; i = i + 1 {
    let remaining = self.length - i * 8
    let mask = if remaining >= 8 { 255 } else { 255 << (8 - remaining) }
    if (self.address[i].to_int() & mask) != (other.address[i].to_int() & mask) {
      return false
    }
  }
  true
}