Consistent Overhead Byte Stuffing (COBS) is a clever way to prepare data for transmission so that a specific byte (usually 0x00) never appears in the message body, allowing it to be used reliably as a "end of packet" marker. Unlike traditional "escape-character" stuffing, which can double the size of your data in the worst case, COBS has a guaranteed maximum overhead of only 1 byte for every 254 bytes of data.
COBS breaks your data into "code blocks." Each block starts with a code byte that tells the receiver how many bytes to skip to reach the next code byte.
- Append a "Phantom" Zero: Conceptually, treat the end of your data as if there is a zero byte there.
- Scan for Zeroes: Look at the first 254 bytes of your data.
- If you find a zero: The code byte is the distance (index) to that zero. For example, if the first byte is 0x00, the code byte is 1.
- If you don't find a zero: The code byte is 0xFF (255), indicating that the next 254 bytes are all non-zero data.
- Replace and Repeat: The found zero is removed from the data stream. The code byte is placed at the start of the block, and the process repeats from the byte immediately after the zero you just removed.
- Add Final Frame Marker: Once finished, you add a 0x00 at the very end to mark the boundary for the receiver.
Input: 11 22 00 33
- Block 1: First zero is at index 3. Code byte = 03. Data = 11 22.
- Block 2: Remaining data is 33. We hit the "phantom" zero 2 bytes away. Code byte = 02. Data = 33.
- Result: 03 11 22 02 33 (Final packet followed by 00 delimiter).
Input: 11 22 33 44
- Block 1: No zeroes found before the end. The "phantom" zero is 5 bytes away. Code byte = 05. Data = 11 22 33 44.
- Result: 05 11 22 33 44.
Input: 00 00 00
- Block 1: Zero at index 1. Code = 01.
- Block 2: Next zero at index 1. Code = 01.
- Block 3: Next zero at index 1. Code = 01.
- Block 4: "Phantom" zero at index 1. Code = 01.
- Result: 01 01 01 01.
| Unencoded Data | Encoded COBS | Explanation |
|---|---|---|
| 00 | 01 01 | First 01 points to the 00 (replaced); second 01 is the final pointer. |
| 11 22 00 33 | 03 11 22 02 33 | 03 says "the zero was at position 3". |
| 11 00 00 00 | 02 11 01 01 01 | Each 01 replaces a 00 in the original data. |