///|
fn read_stdin_all_internal() -> String {
  let bytes = []
  for ch = getchar() {
    if ch == -1 {
      break
    } else {
      bytes.push(ch)
      continue getchar()
    }
  }
  let buf = StringBuilder()
  let mut i = 0
  while i < bytes.length() {
    match utf8_decode_next_strict(bytes, i) {
      Some((code, width)) => {
        buf.write_char(code.unsafe_to_char())
        i += width
      }
      None => {
        buf.write_char('\u{fffd}')
        i += 1
      }
    }
  }
  buf.to_string()
}

///|
extern "c" fn getchar() -> Int32 = "getchar"

///|
fn utf8_is_continuation_byte(b : Int32) -> Bool {
  b >= 0x80 && b <= 0xBF
}

///|
fn utf8_decode_next_strict(bytes : Array[Int32], i : Int32) -> (Int32, Int32)? {
  guard i < bytes.length() else { return None }
  let b0 = bytes[i]
  if b0 <= 0x7F {
    return Some((b0, 1))
  }
  if b0 < 0xC2 || b0 > 0xF4 {
    return None
  }
  if b0 <= 0xDF {
    guard i + 1 < bytes.length() else { return None }
    let b1 = bytes[i + 1]
    guard utf8_is_continuation_byte(b1) else { return None }
    let code = ((b0 & 0x1F) << 6) | (b1 & 0x3F)
    return Some((code, 2))
  }
  if b0 <= 0xEF {
    guard i + 2 < bytes.length() else { return None }
    let b1 = bytes[i + 1]
    let b2 = bytes[i + 2]
    guard utf8_is_continuation_byte(b1) && utf8_is_continuation_byte(b2) else {
      return None
    }
    if b0 == 0xE0 && b1 < 0xA0 {
      return None
    }
    if b0 == 0xED && b1 > 0x9F {
      return None
    }
    let code = ((b0 & 0x0F) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F)
    return Some((code, 3))
  }
  guard i + 3 < bytes.length() else { return None }
  let b1 = bytes[i + 1]
  let b2 = bytes[i + 2]
  let b3 = bytes[i + 3]
  guard utf8_is_continuation_byte(b1) &&
    utf8_is_continuation_byte(b2) &&
    utf8_is_continuation_byte(b3) else {
    return None
  }
  if b0 == 0xF0 && b1 < 0x90 {
    return None
  }
  if b0 == 0xF4 && b1 > 0x8F {
    return None
  }
  let code = ((b0 & 0x07) << 18) |
    ((b1 & 0x3F) << 12) |
    ((b2 & 0x3F) << 6) |
    (b3 & 0x3F)
  Some((code, 4))
}