decodeCOBS function

DecodeResult decodeCOBS(
  1. ByteData decoded,
  2. ByteData source
)

Decode source to decoded using COBS and return DecodeResult status.

The DecodeResult instance returned will include the actual length of the decoded byte array in outLen and the status of the decoding attempt in status.

Implementation

DecodeResult decodeCOBS(ByteData decoded, ByteData source) {
  int sourceCounter = 0;
  int sourceEndCounter = source.lengthInBytes;
  int decodedEndCounter = decoded.lengthInBytes;
  int decodedWriteCounter = 0;
  int remainingBytes;
  int sourceByte;
  int i;
  int lengthCode;

  var decodeStatus = DecodeStatus.OK;

  if (source.lengthInBytes != 0) {
    while (true) {
      lengthCode = source.getUint8(sourceCounter++);
      if (lengthCode == 0) {
        return DecodeResult(status: DecodeStatus.ZERO_BYTE_IN_INPUT);
      }
      lengthCode--;

      /* Check length code against remaining input bytes */
      remainingBytes = sourceEndCounter - sourceCounter;
      if (lengthCode > remainingBytes) {
        decodeStatus = DecodeStatus.INPUT_TOO_SHORT;
        lengthCode = remainingBytes;
      }

      /* Check length code against remaining output buffer space */
      remainingBytes = decodedEndCounter - decodedWriteCounter;
      if (lengthCode > remainingBytes) {
        decodeStatus = DecodeStatus.OUT_BUFFER_OVERFLOW;
        lengthCode = remainingBytes;
      }

      for (i = lengthCode; i != 0; i--) {
        sourceByte = source.getUint8(sourceCounter++);
        if (sourceByte == 0) {
          decodeStatus = DecodeStatus.ZERO_BYTE_IN_INPUT;
        }
        decoded.setUint8(decodedWriteCounter++, sourceByte);
      }

      if (sourceCounter >= sourceEndCounter) {
        break;
      }

      /* Add a zero to the end */
      if (lengthCode != 0xFE) {
        if (decodedWriteCounter >= decodedEndCounter) {
          decodeStatus = DecodeStatus.OUT_BUFFER_OVERFLOW;
          break;
        }
        decoded.setUint8(decodedWriteCounter++, 0);
      }
    }
  }

  return DecodeResult(outLen: decodedWriteCounter, status: decodeStatus);
}