///|
pub fn normalize_line_endings(input : String) -> String {
  let mut out = ""
  let mut previous_cr = false
  for ch in input {
    if ch == '\r' {
      out = out + "\n"
      previous_cr = true
    } else if ch == '\n' {
      if !previous_cr {
        out = out + "\n"
      }
      previous_cr = false
    } else {
      out = out + ch.to_string()
      previous_cr = false
    }
  }
  out
}

///|
pub fn normalize_to_crlf(input : String) -> String {
  let lines = split_lines(normalize_line_endings(input))
  let mut out = ""
  for line in lines {
    out = out + line + "\r\n"
  }
  out
}

///|
pub fn remove_bom(input : String) -> String {
  if input.length() > 0 && input[0] == '\u{feff}' {
    slice(input, 1, input.length())
  } else {
    input
  }
}

///|
pub fn prepare_raw_message(input : String) -> String {
  normalize_to_crlf(remove_bom(input))
}

///|
pub fn parse_prepared_message(input : String) -> ParseResult {
  parse_message(prepare_raw_message(input))
}