///|
/// Encodes `text` as UTF-8, writing each lone surrogate as U+FFFD, as the
/// WHATWG Encoding Standard's UTF-8 encoder and `TextEncoder` do.
/// `@utf8.encode` aborts the process on a lone surrogate instead, so it is
/// unsafe for strings that came from outside.
///
/// ```mbt check
/// test {
///   let lone = String::from_array([(0xD800).unsafe_to_char()])
///   assert_eq(@http.encode_utf8("é" + lone), b"\xC3\xA9\xEF\xBF\xBD")
/// }
/// ```
pub fn encode_utf8(text : String) -> Bytes {
  let buffer = Buffer(size_hint=text.length())
  let units = text.length()
  for i = 0; i < units; {
    let unit = text.code_unit_at(i).to_int()
    let (code_point, width) = if unit >= 0xD800 &&
      unit < 0xDC00 &&
      i + 1 < units &&
      text.code_unit_at(i + 1).to_int() is (0xDC00..<0xE000 as low) {
      (0x10000 + ((unit - 0xD800) << 10) + (low - 0xDC00), 2)
    } else if unit >= 0xD800 && unit < 0xE000 {
      (0xFFFD, 1)
    } else {
      (unit, 1)
    }
    if code_point < 0x80 {
      buffer.write_byte(code_point.to_byte())
    } else if code_point < 0x800 {
      buffer.write_byte((0xC0 | (code_point >> 6)).to_byte())
      buffer.write_byte((0x80 | (code_point & 0x3F)).to_byte())
    } else if code_point < 0x10000 {
      buffer.write_byte((0xE0 | (code_point >> 12)).to_byte())
      buffer.write_byte((0x80 | ((code_point >> 6) & 0x3F)).to_byte())
      buffer.write_byte((0x80 | (code_point & 0x3F)).to_byte())
    } else {
      buffer.write_byte((0xF0 | (code_point >> 18)).to_byte())
      buffer.write_byte((0x80 | ((code_point >> 12) & 0x3F)).to_byte())
      buffer.write_byte((0x80 | ((code_point >> 6) & 0x3F)).to_byte())
      buffer.write_byte((0x80 | (code_point & 0x3F)).to_byte())
    }
    continue i + width
  }
  buffer.to_bytes()
}