pub const fn build_table<const N: usize>(params: Params<'_>) -> [usize; N]Expand description
Build the size-class table at compile time: a geometric progression merged
with params.extras in sorted order, returned as [usize; N] where N
must equal params.geo_count + params.extras.len().
Spacing: start at min_block, then each next class is
round_up(ceil(prev * num / den), min_block), with a minimum step of
min_block. The extras are merged in sorted order (a plain sorted-merge —
const fn cannot call slice::sort), keeping the combined table strictly
increasing and every entry a multiple of min_block.
growth = (num, den) with num <= den (including (0, den)) is a
deliberately valid scheme, not a contract violation: a ratio <= 1 makes
the geometric term always <= prev, so every class falls back to the
min_block-step minimum, degrading the whole run to a flat min_block,
2 * min_block, 3 * min_block, … sequence.
§Panics
Panics – identically in const evaluation and at runtime, since this is
a pub const fn callable either way – if any of:
N != geo_count + extras.len();min_blockis not a power of two;geo_count == 0;params.growth.1(the growth denominator) is0;- any
extrasentry is not a multiple ofmin_block; - any
extrasentry is less thanmin_block(the scheme’s minimum block size); extrasis not strictly increasing;- the geometric progression’s advance step overflows
usize(see the worked example below); - the merged table (geometric run +
extras) is not itself strictly increasing – the per-entryextraschecks above catch misshapenextras, but not anextrasentry that DUPLICATES a value the geometric run also produces, which only the merged table reveals. Anextrasentry landing strictly BETWEEN two geometric values is fine, and is one of the main reasonsextrasexists.
The advance-step overflow is reachable not just with an extreme
min_block/growth combination but with a large enough geo_count
alone: with min_block = 16, growth = (5, 4) (this crate’s own tests’
example scheme; the crate itself has no defaults), geo_count = 183
already overflows on a 64-bit usize (84 on a 32-bit one – the
boundary scales with usize::BITS). At the top of that range (roughly
the last half-dozen steps – the intermediate cur * num product first
exceeds usize only once cur > usize::MAX / num) is exactly the
widened-arithmetic case: the next class fits even though the
intermediate cur * num product does not fit usize.