# auto-concat-array
Concatenate fixed-size arrays on **stable Rust** with automatic array length inference and zero unused compile-time overhead.
## Motivation
In current stable Rust, concatenating two arrays `[T; N]` and `[T; M]` to return an array of size `[T; N + M]` is not directly possible because the `#![feature(generic_const_exprs)]` feature is heavily unstable.
While other crates solve this via process macros at the call site (which breaks natural type inference chaining) or complex `typenum` math, `auto-concat-array` takes a different approach: **Inversion of Control via Macros and Traits.**
It provides a `ConcatHelper` trait and an `impl_concat!` macro, allowing you to generate exactly the implementations you need for your own local marker types.
## Highlights
- **Seamless Type Inference**: Once wrapped in a generic function, you don't need to specify the output array's length. The compiler deduces `[T; N + M]` automatically. It feels exactly like native Rust.
- **Pay For What You Use**: Instead of pre-generating tens of thousands of combinations and severely bloating compilation times, *you* decide which length combinations matter to your project.
- **No Orphan Rule Conflicts**: By implementing the trait on your own custom marker struct, you avoid trait implementation collisions across the ecosystem.
- **Chainable**: Because it resolves at the type-system level rather than relying on AST-expanding macros at the call site, you can smoothly chain function calls (e.g., `concat(concat(a, b), c)`).
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
auto-concat-array = "0.1.0"
```
### Example
```rust
use auto_concat_array::{impl_concat, ConcatHelper};
// 1. Define your own local marker type
struct MyArrayTools;
// 2. Generate concatenations ONLY for what you need!
// You can generate specific large array combinations:
impl_concat!(MyArrayTools; (100, 200), (300, 100));
// Or generate a matrix of combinations using ranges (N in 0..16, M in 0..16):
impl_concat!(MyArrayTools; 0..16 ; 0..16);
// 3. Create a wrapper function for seamless type inference
fn array_concat<T, const N: usize, const M: usize>(
a: [T; N],
b: [T; M],
) -> <MyArrayTools as ConcatHelper<T, N, M>>::Output
where
T: Copy,
MyArrayTools: ConcatHelper<T, N, M>,
{
MyArrayTools::do_concat(a, b)
}
fn main() {
// Works perfectly with generated small array ranges
let str_a = ["Rust", "is"];
let str_b = ["Awesome", "!"];
// The compiler knows `str_c` is exactly `[&str; 4]`!
let str_c = array_concat(str_a, str_b);
assert_eq!(str_c, ["Rust", "is", "Awesome", "!"]);
// Works with your specifically hand-picked large combinations
let large_a = [0; 100];
let large_b = [1; 200];
let large_c = array_concat(large_a, large_b);
assert_eq!(large_c.len(), 300);
}
```
## Limitations
- **`T: Copy` Requirement**: Currently, the macro implementation uses array indexing and requires the elements to implement `Copy`.
- **Combinatorial Explosion Caution**: While `impl_concat!` accepts ranges like `0..256 ; 0..256`, doing so will generate `65,536` implementations for your struct. This *will* exponentially slow down the Rust compiler. Only generate the ranges you actively need (e.g., `0..16`, or `0..32`), and use specific tuples for larger buffers.
- **Not "Infinite"**: If you attempt to concatenate arrays whose lengths fall outside the bounds you generated with `impl_concat!`, you will receive a compile-time error: `trait bound not satisfied`.
## License
Dual-licensed under either of
* Apache License, Version 2.0
* MIT license
at your option.