Iterate loops are syntactic sugar for partitioning a variable-sized input slice into fixed-sized chunk slices (with possible smaller-sized remainders). Individual chunks' fixed sizes are typically easier for bounds-checking.
For example, with primarily 8 length chunks, a 26 length input can be processed in five chunks (of length 8, 8, 8, 1 and 1). Accessing chunk[7]
is trivially in-bounds if chunk.length()
is exactly 8.
var chunk : slice base.u8 var input : slice base.u8 etc iterate (chunk = input)(length: 8, unroll: 2) { // Within this block, chunk.length() is always 8. For a 26 length input, // this block will run three times: // - with "chunk = input[0 .. 8]", // - with "chunk = input[8 .. 16]", // - with "chunk = input[16 .. 24]". etc } else (length: 1, unroll: 1) { // Each block of the iterate loop only runs after all previous blocks (in // this case the only previous block) are exhausted: the remaining input is // shorter than each of their given lengths. // // Within this block, chunk.length() is always 1. Continuing the previous // example, this block will run two times: // - with "chunk = input[24 .. 25]", // - with "chunk = input[25 .. 26]". etc }
Chunk processing (i.e. loop bodies) can also be unrolled, which affects performance but not semantics.