The 63 AC coefficients are coded as run-length pairs - a count of leading zeros and a magnitude category. Today you expand one AC symbol into a placed coefficient.
Expand an AC Huffman symbol into a zero-run and a size, skip that many coefficients, then place the extended value.
The 63 AC coefficients of a block are mostly zero after the zig-zag reorder groups the high frequencies together, so JPEG codes them as run-length pairs. Each AC Huffman symbol is one byte splitting into two nibbles: the high nibble is a run of leading zero coefficients to skip, and the low nibble is the size (magnitude category) of the nonzero coefficient that follows. So 0x32 means “skip 3 zeros, then a size-2 value”: starting from index 1 you advance past indices 1, 2, 3, and place the extended value at index 4.
The value itself comes from the same receive-and-extend you built for DC - here 10 with size 2 extends to +2. This is the loop that fills a block: decode an AC symbol, jump the index forward by the run, place a coefficient, and repeat, walking from index 1 toward index 63. Two symbols get special treatment - the end-of-block and the full zero-run - and those are the next lesson; today you handle the ordinary run-then-value case that does the bulk of the work.
// AC symbol byte: (run << 4) | size// run = high nibble = number of zero coefficients to skip// size = low nibble = magnitude category of the next value// advance index by run, then place receiveExtend(size) at that index.func placeAC(block *[64]int, index *int, sym byte, r *BitReader) { }