generic-array

Generic array types for Rust, letting structs and traits be generic over array length via typenum-backed sizes.

Library
Cargo
v1.4.5
437stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
64/100Good
Development Activity60
Maintenance44
Community72
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture85
Code Quality82
Innovation68
Learning Curve70

generic-array solves a gap that predates and still partially outlives Rust’s const generics: making a struct or trait generic over an array’s length. It defines an ArrayLength trait implemented for the unsigned integer types from the typenum crate, and a GenericArray<T, N: ArrayLength> struct that behaves like [T; N] while N remains a type parameter usable in trait bounds and associated types.

The crate underpins the generic-array 0.14 ecosystem widely used by cryptography and hashing crates (block ciphers, hash functions) that need fixed-size buffers parameterized by a type. Version 1.x drops the old ArrayLength<T> shape in favor of a simpler ArrayLength, ships a compat-0_14 feature for bridging old and new versions, and adds interop with the hybrid-array crate for projects migrating toward native const generics.

Optional feature flags add serde, zeroize, bytemuck, rkyv, arbitrary, subtle, and bitvec integrations, plus an alloc feature for conversions to and from Vec<T>/Box<[T]>, so consumers pull in only the interop code they need in no_std contexts.

What You Get

  • GenericArray<T, N> — an array type generic over length via the ArrayLength trait, usable in generic struct fields and trait signatures
  • The arr! macro for literal array construction, e.g. arr![1, 2, 3], without spelling out the length type
  • Feature-gated interop with serde, zeroize, bytemuck, rkyv, arbitrary, subtle, and bitvec so downstream crates opt into only what they need
  • A compat-0_14 bridge and hybrid-array-0_4 interop for migrating code between generic-array major versions and toward native const generics
  • no_std support by default, with an alloc feature unlocking Vec<T>/Box<[T]> conversions for allocator-backed environments

Common Use Cases

  • Cryptography and hashing crates that need a fixed-size output buffer (e.g. a 32-byte digest) parameterized by a type rather than a hardcoded array length
  • Generic numeric or SIMD-adjacent code where buffer size must propagate through several layers of generic structs and trait implementations
  • Libraries maintaining no_std compatibility while still needing statically-sized, type-safe buffers
  • Crates that need serde/zeroize/bytemuck support for fixed-size buffers without hand-rolling those trait implementations for every possible array length

Under The Hood

Architecture generic-array’s core is the ArrayLength trait in internal.rs, implemented for every typenum unsigned integer via a blanket/macro-driven mechanism that maps a type-level number to a concrete backing array representation; GenericArray<T, N> in lib.rs wraps that representation and forwards Deref/DerefMut to a plain slice so it interoperates with existing slice-based APIs. sequence.rs and functional.rs layer map/zip/fold-style combinators on top using associated-type projections rather than runtime dispatch, iter.rs supplies owned and borrowed iterators, and compat/ isolates the version-bridging code (generic_array_0_14.rs, hybrid_array_0_4.rs) so migration support doesn’t leak into the core type. Optional third-party trait impls live entirely under ext_impls/, one file per integration, gated behind their own Cargo features — changing the core ArrayLength/GenericArray definitions would ripple through every one of these files plus every downstream crate that stores a GenericArray field.

Tech Stack The crate targets Rust edition 2021 with a minimum supported Rust version of 1.65, and has exactly two mandatory dependencies: typenum (for the type-level unsigned integers that back ArrayLength) and rustversion (for version-gated code paths across Rust releases). Everything else — serde_core, zeroize, faster-hex, subtle, arbitrary, bytemuck, as-slice, bitvec, rkyv/bytecheck, and the generic-array 0.14/hybrid-array 0.4 compatibility shims — is an optional dependency behind a matching feature flag, keeping the default build minimal and no_std-friendly. There is no build script; cargo and rustdoc (with docsrs cfg for feature-gated doc rendering) are the only tooling involved.

Code Quality The crate carries an extensive test suite split across tests/mod.rs, alloc.rs, iter.rs, hex.rs, arr.rs, generics.rs, and compatibility-specific files, run under both a normal cargo test and cargo miri test --all-features in CI to catch undefined behavior in the crate’s unsafe code, plus a coverage job that publishes a live badge. Given the crate’s job — projecting type-level lengths onto raw memory — it relies on a meaningful amount of unsafe code for transmutes and uninitialized-memory handling, which is exactly why the Miri pass under full feature flags is treated as a required CI gate rather than an afterthought. Naming and module layout are consistent (one file per external integration, one file per core concern), and the crate is entirely #![no_std] by default, which constrains error handling to Result/Option patterns rather than panics wherever avoidable.

API Design The public surface is deliberately small: GenericArray<T, N>, the ArrayLength trait, and the arr! macro cover the common case, with everything else opt-in through Cargo features. Migrating from the 0.14 line requires only dropping a now-removed type parameter from ArrayLength<T> bounds, and the crate documents this upgrade path directly in its top-level docs along with to_0_14/from_0_14/as_0_14/as_0_14_mut conversion methods, which is unusually thorough for a low-level utility crate. The tradeoff is that consumers still need to understand typenum’s type-level numerals (U5, U32, etc.) to use the crate productively, since that’s inherent to the const-generic gap it fills rather than something the API can fully hide.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search