///|
pub fn normalize_scanner_input(input : String) -> String {
  let mut cleaned = ""
  for ch in input {
    if ch != '\r' && ch != '\n' {
      cleaned = cleaned + "\{ch}"
    }
  }
  let mut start = 0
  let mut end = cleaned.length()
  while start < end && cleaned.get_char(start) == Some('\u{1D}') {
    start = start + 1
  }
  while end > start && cleaned.get_char(end - 1) == Some('\u{1D}') {
    end = end - 1
  }
  cleaned.unsafe_substring(start~, end~)
}

///|
pub fn scanner_lines(input : String) -> Array[String] {
  let lines : Array[String] = []
  let mut start = 0
  for pos = 0; pos < input.length(); pos = pos + 1 {
    if input.get_char(pos) == Some('\n') {
      lines.push(input.unsafe_substring(start~, end=pos).trim().to_owned())
      start = pos + 1
    }
  }
  if start < input.length() {
    lines.push(
      input.unsafe_substring(start~, end=input.length()).trim().to_owned(),
    )
  }
  lines
}

///|
pub fn scanner_payloads(input : String) -> Array[String] {
  scanner_lines(input)
  .filter(fn(line) { !line.is_empty() })
  .map(normalize_scanner_input)
}