intarray
Memory-efficient packed integer array for Rust. Stores integers of 1–64 bits each, tightly packed into Vec<u64> with no per-element overhead.
When to use
- Fixed-width small integers (e.g. 4-bit counters, 10-bit indices, 20-bit values)
- Memory is the bottleneck and values fit in fewer than 64 bits
- You know the maximum value at construction time
Installation
[]
= "0.2"
Quick start
use ;
// 7-bit unsigned integers, 1000 elements (pre-allocated)
let mut v = new;
v.set.unwrap; // v[0] = 100
v.set.unwrap; // v[1] = 127 (max for 7 bits)
assert_eq!;
// Out-of-range value returns Err, never panics
assert_eq!;
// Append elements
v.push.unwrap;
Construction
// Pre-allocated, zero-filled
let v = new; // 4-bit, 100 elements
// From a Vec
let v = new_with_vec;
// From an iterator
let v = new_with_iter;
// Infer bit width from data (same as shape_auto)
let v = new_with_vec;
let compact = v.shape_auto; // bits = 2 (max value = 3, needs 2 bits)
Element access
All access methods return Result<_, IntArrayError>:
| Error | When |
|---|---|
OutOfBounds |
index ≥ length |
TooLarge |
value exceeds 2^bits − 1 |
TooSmall |
sub/decr would go below 0 |
Empty |
pop() on empty array |
let mut v = new; // max value = 15
v.get.unwrap; // → 0
v.set.unwrap; // ok
v.set.unwrap_err; // TooLarge
v.get.unwrap_err; // OutOfBounds
v.push.unwrap; // append, returns new index
v.pop.unwrap; // remove last, returns value
v.incr.unwrap; // v[5] += 1
v.decr.unwrap; // v[5] -= 1
v.add.unwrap; // v[5] += 3
v.sub.unwrap; // v[5] -= 3
incr_limit / decr_limit clamp at the boundary and return None instead of overflowing:
v.incr_limit; // → Some(old_value) if v[5] < max, None if already at max
v.decr_limit; // → Some(old_value) if v[5] > 0, None if already at 0
Bulk operations
push, extend, and extend_array are all atomic: on error, the array is left unchanged.
let mut v = new;
// Extend from an iterator of u64
v.extend.unwrap;
// Extend from another IntArray (fast path when bits and alignment match)
let other = new_with_vec;
v.extend_array.unwrap;
Arithmetic operators
Element-wise arithmetic via +=, -=, *=. Works on both a scalar u64 and another IntArray:
let mut a = new_with_vec;
a += 5u64; // [15, 25, 35]
let b = new_with_vec;
a += &b; // [16, 27, 38] (&b なので b は消費されない)
Iteration and statistics
let v = new_with_vec;
for x in v.iter
v.sum.unwrap; // → 23u128
v.min.unwrap; // → 1
v.max.unwrap; // → 9
v.average.unwrap; // → 3.8333...
Shape / reshape
let v = new_with_vec;
// Reshape to a different bit width (copies all elements)
let v8 = v.shape;
// Infer minimum bit width from max value
let compact = v.shape_auto; // bits = 10 (needs 10 bits for 1000)
// Subarray (slice without copying when aligned)
let sub = v.subarray; // elements [1..3)
Serialization (serde)
IntArray implements Serialize and Deserialize as a flat sequence of u64.
use serde_json;
let v = new_with_vec;
let json = to_string.unwrap; // "[1,2,3]"
let v2: IntArray = from_str.unwrap;
// Note: bit width is re-inferred from the max value (bits = 2 for max=3).
// All-zeros arrays always deserialize with bits = 1.
Memory layout
let v = new;
v.len; // 100 — number of elements
v.capacity; // 112 — allocated capacity in elements (rounded to word boundary)
v.datasize; // size in bytes (consumes v)
Each u64 word holds 64 / bits elements. For example, 4-bit integers pack 16 per word; a 100-element array uses 7 words (56 bytes of data).
Error type
IntArrayError implements std::error::Error and Display.
MSRV
Rust 1.87 (uses usize::is_multiple_of, stabilized in 1.87).