Goal
Implement a UTF-8 encoder and decoder from RFC 3629 without leaning on the language's built-in codec, then build a small text-processing CLI on top of it. Doing the bit-shifting yourself makes the three-layer tower — bytes, code points, grapheme clusters — permanent, and cures mojibake, broken emoji slicing, and "length lies" for good.
Subject: full brief & instructions
Practices
- Unicode & text encoding — the three layers, UTF-8's self-synchronizing design, normalization, and the "length" traps this drills.
- AppSec fundamentals — validate after normalizing; homoglyph and invisible-character handling are input-trust rules applied to text.
Milestones
- Encoder. Map a code point to 1–4 bytes per RFC 3629: compute the length from the code-point range, lay out the leading-byte and continuation-byte bit patterns. Reject surrogates (U+D800–DFFF) and out-of-range values.
- Decoder. Read a byte stream back to code points; reject overlong encodings, stray continuation bytes, and truncated sequences — the invalid inputs are the whole point. Verify against your language's codec on a fixtures file.
- Self-synchronization demo. From a random byte offset, find the next character boundary using only the high bits — proving why UTF-8 recovers where UTF-16 can't.
- Text CLI, layer-aware. Build a small
wc-like tool that reports counts three ways — bytes, code points, and grapheme clusters — on the same input; make the numbers differ on an emoji ZWJ sequence and a combining-accenté. - Normalization pass. Add an option to NFC-normalize input and show that two visually identical strings compare equal only after normalization.
Stretch goals
- Detect and flag bidi-control / zero-width characters (the "Trojan Source" trick).
- Add a UTF-16 (surrogate-pair) codec and cross-convert.
Related
- UTF-8 codec + text CLI — subject — the full work statement, byte-pattern rules, and acceptance checks for this exercise.
- Unicode & text encoding — cites this
exercise in its
# Practicesection. - Time, timezones & datetime — the sibling fundamental everyone gets wrong.