chunkLuaString function

List<String> chunkLuaString(
  1. List<int> payload,
  2. int maxChunkBytes
)

Splits payload (the UTF-8 bytes of an escaped Lua string literal) into chunks of at most maxChunkBytes bytes, without splitting a multi-byte UTF-8 sequence or a Lua escape sequence across two chunks.

Implementation

List<String> chunkLuaString(List<int> payload, int maxChunkBytes) {
  if (maxChunkBytes <= 0) {
    throw ArgumentError.value(
        maxChunkBytes, 'maxChunkBytes', 'must be positive');
  }

  final chunks = <String>[];
  int index = 0;

  while (index < payload.length) {
    int end = index + maxChunkBytes;

    if (end >= payload.length) {
      end = payload.length;
    } else {
      // Don't split a multi-byte UTF-8 sequence: back up while the byte at
      // the split point is a continuation byte (0b10xxxxxx)
      while (end > index && (payload[end] & 0xC0) == 0x80) {
        end--;
      }

      // Don't split an escape sequence: an odd number of trailing
      // backslashes means the last one starts an escape whose second
      // character would land in the next chunk
      int trailingBackslashes = 0;
      while (end - 1 - trailingBackslashes >= index &&
          payload[end - 1 - trailingBackslashes] == 0x5C) {
        trailingBackslashes++;
      }
      if (trailingBackslashes.isOdd) {
        end--;
      }

      if (end == index) {
        throw ArgumentError.value(maxChunkBytes, 'maxChunkBytes',
            'too small to hold the next character of the payload');
      }
    }

    chunks.add(utf8.decode(payload.sublist(index, end)));
    index = end;
  }

  return chunks;
}