///|
fn linkify_validate_candidate(
  candidate : StringView,
  source : StringView,
  start : Int,
  config : LinkifyConfig,
) -> Bool {
  let is_scheme = linkify_is_scheme(candidate)
  let is_scheme_url = linkify_is_scheme_url(candidate)
  let is_www = @syn.starts_with_case_insensitive(candidate, 0, "www.")
  let is_proto_rel = @syn.starts_with_case_insensitive(candidate, 0, "//")
  let has_at = string_view_contains(candidate, "@")
  if @syn.starts_with_case_insensitive(candidate, 0, "mailto:") {
    let address = candidate[7:candidate.length()]
    return linkify_validate_email_address(address, config, true)
  }
  if !is_scheme && !is_proto_rel && !is_www && !has_at {
    if linkify_broken_schema_context(source, start) {
      return false
    }
  }
  if linkify_starts_with_digit(candidate) &&
    string_view_contains(candidate, ".") &&
    !is_scheme_url &&
    !is_proto_rel {
    guard linkify_host_view(candidate) is Some(host) else { return false }
    if linkify_all_digits_or_dots(host) &&
      linkify_valid_ipv4(host) &&
      !config.fuzzy_ip {
      return false
    }
  }
  if is_proto_rel &&
    !linkify_validate_protocol_relative(candidate, source, start) {
    return false
  }
  if !is_scheme && !is_proto_rel && !is_www && !has_at {
    guard linkify_host_view(candidate) is Some(host) else { return false }
    if string_view_contains(host, "_") {
      return false
    }
    if string_view_contains(host, ":") {
      return false
    }
    if string_view_contains(host, ".") &&
      linkify_all_digits_or_dots(host) &&
      linkify_valid_ipv4(host) {
      return true
    }
    guard linkify_split_domain_for_tld(host) is Some((_base, tld)) else {
      return false
    }
    if !linkify_valid_tld(tld, config.extra_tlds) {
      return false
    }
  }
  if has_at &&
    !is_scheme_url &&
    !is_proto_rel &&
    !@syn.starts_with_case_insensitive(candidate, 0, "mailto:") {
    if !linkify_validate_email_address(candidate, config, false) {
      return false
    }
  }
  if is_scheme_url && !linkify_validate_scheme_url(candidate) {
    return false
  }
  true
}

///|
fn linkify_validate_email_address(
  address : StringView,
  config : LinkifyConfig,
  allow_tldless_domain : Bool,
) -> Bool {
  guard linkify_last_char_index(address, '@') is Some(at) else { return false }
  if at == 0 || at + 1 >= address.length() {
    return false
  }
  let domain = address[at + 1:address.length()]
  guard linkify_host_view(domain) is Some(host) else { return false }
  if string_view_contains(host, "_") {
    return false
  }
  match linkify_split_domain_for_tld(host) {
    Some((_base, tld)) => linkify_valid_tld(tld, config.extra_tlds)
    None => allow_tldless_domain && !host.is_empty()
  }
}

///|
fn linkify_broken_schema_context(source : StringView, start : Int) -> Bool {
  if start >= 3 {
    match source.get_view(start=start - 3, end=start) {
      Some("://") => return true
      _ => ()
    }
  }
  if start > 0 {
    match source.get_char(start - 1) {
      Some('/') | Some(':') | Some('@') => return true
      _ => ()
    }
  }
  false
}

///|
fn linkify_validate_protocol_relative(
  candidate : StringView,
  source : StringView,
  start : Int,
) -> Bool {
  if start > 0 {
    match source.get_char(start - 1) {
      Some(':') | Some('/') => return false
      _ => ()
    }
  }
  let after = candidate[2:candidate.length()]
  guard linkify_host_view(after) is Some(hostport) else { return false }
  if hostport.is_empty() || hostport.has_prefix("[") {
    return false
  }
  let host = linkify_host_without_userinfo_port(hostport)
  if host.is_empty() {
    return false
  }
  if @syn.lower_ascii(host) != "localhost" && !string_view_contains(host, ".") {
    return false
  }
  !string_view_contains(host, "_")
}

///|
fn linkify_validate_scheme_url(candidate : StringView) -> Bool {
  guard linkify_after_url_scheme(candidate) is Some(after) else { return false }
  guard linkify_host_view(after) is Some(hostport) else { return false }
  if hostport.is_empty() {
    return false
  }
  let hostport = linkify_strip_userinfo(hostport)
  let (host, port) = linkify_split_host_port(hostport)
  if port != "" {
    guard linkify_parse_uint(port) is Some(port_value) else { return false }
    if port_value > 65535 {
      return false
    }
  }
  if host.is_empty() ||
    host.has_prefix("-") ||
    host.has_prefix(".") ||
    host.has_suffix("-") ||
    host.has_suffix(".") ||
    string_view_contains(host, "..") ||
    string_view_contains(host, "_") {
    return false
  }
  if string_view_contains(host, ".") &&
    linkify_all_digits_or_dots(host) &&
    !linkify_valid_ipv4(host) {
    return false
  }
  true
}