///|
/// Rejects a capacity the caller cannot mean: zero or less for a container that
/// allocates on demand, or a ceiling below the data already stored.
fn require_capacity(capacity : Int32) -> Unit raise @spec.Refused {
  if capacity <= 0 {
    raise @spec.Refused::Capacity(got=capacity)
  }
}

///|
/// Rounds `value` up to the next multiple of 64, saturating rather than
/// overflowing, so a huge bit capacity is refused later instead of wrapping.
fn words_for(bits : Int32) -> Int32 {
  if bits <= 0 {
    0
  } else if bits > 0x7FFFFFF - 64 {
    0x7FFFFFFF
  } else {
    (bits + 63) / 64
  }
}

///|
/// The smallest storage size that can hold `needed` elements while doubling,
/// clamped to a ceiling. Used by every container that grows on demand.
fn grown_size(current : Int32, needed : Int32, ceiling : Int32) -> Int32 {
  let doubled = if current > ceiling / 2 { ceiling } else { current * 2 }
  let target = if doubled < needed { needed } else { doubled }
  if target > ceiling {
    ceiling
  } else {
    target
  }
}

///|
fn[T : Debug] debug_items(items : Array[T]) -> Array[Repr] {
  let out : Array[Repr] = []
  for value in items {
    out.push(Debug::to_repr(value))
  }
  out
}

///|
fn[T : Show] show_items(items : Array[T], logger : &Logger) -> Unit {
  for i, value in items {
    if i > 0 {
      logger.write_string(", ")
    }
    Show::output(value, logger)
  }
}