decodeOneRuneAt function

({int consumed, bool ok, int rune}) decodeOneRuneAt(
  1. List<int> buf,
  2. int offset
)

Implementation

({int consumed, int rune, bool ok}) decodeOneRuneAt(List<int> buf, int offset) {
  if (offset >= buf.length) return (consumed: 0, rune: 0, ok: false);
  final b0 = buf[offset] & 0xff;
  if (b0 < 0x80) return (consumed: 1, rune: b0, ok: true);

  int need;
  int min;
  int rune;
  if ((b0 & 0xE0) == 0xC0) {
    need = 2;
    min = 0x80;
    rune = b0 & 0x1F;
  } else if ((b0 & 0xF0) == 0xE0) {
    need = 3;
    min = 0x800;
    rune = b0 & 0x0F;
  } else if ((b0 & 0xF8) == 0xF0) {
    need = 4;
    min = 0x10000;
    rune = b0 & 0x07;
  } else {
    return (consumed: 1, rune: b0, ok: false);
  }

  if (offset + need > buf.length) return (consumed: 0, rune: 0, ok: false);

  for (var i = 1; i < need; i++) {
    final bx = buf[offset + i] & 0xff;
    if ((bx & 0xC0) != 0x80) return (consumed: 1, rune: b0, ok: false);
    rune = (rune << 6) | (bx & 0x3F);
  }

  // Reject overlongs, surrogates, and out-of-range code points.
  if (rune < min) return (consumed: 1, rune: b0, ok: false);
  if (rune > 0x10ffff) return (consumed: 1, rune: b0, ok: false);
  if (rune >= 0xD800 && rune <= 0xDFFF) {
    return (consumed: 1, rune: b0, ok: false);
  }

  return (consumed: need, rune: rune, ok: true);
}