Fixed size layout container from Vec<Enum<T>>

I'm working with a set of a few dozen enums that are all either 1, 4, or 8 values of T = f64 (maybe f32), and the single value variant is by far the most common. During setup I'll use an ordinary mutable Vec of enums to be able to add/remove/configure everything. Then, perhaps via an Into method, I'd like to create the immutable layout for use as a reference for parallel runtimes. Would something like that be possible based on the following?

pub struct DenseGroup<T: Sized, const N: usize, const S: usize> {
    storage: [MaybeUninit<u8>; S],
    pointers: [Option<NonNull<??>>; N],
    initialized: usize,
}

Basically I'd like bumpalo or arena-style allocation, but with a conceptually "fixed" memory layout that is effectively runtime assigned using compile-time-validated checks. I have zero desire to see this as an external crate, as I'm pretty sure it's a minefield of uninit, drop, and bounds concerns, plus many more I'm sure I haven't thought of. But, I think it could be very useful as an unsafe and internal only struct.

The other concern I have is: how to unify the pointers' type? I really just want a fixed block of memory containing a fixed amount of variously-sized objects that I can iterate, map, and reduce over. That leads me to think it will need to be dyn Trait, but then it's unsized... Is that the Achilles heel here? Or would it just require use of a custom Box? But aren't boxes just pointers?

Nevertheless, if that doesn't torpedo this, then the process to go from setup to run is just - count the number of items (N) and sum the size_of all items (S) to be able to initialize the container. Then immediately push (copy) all items, shadow itself into an immutable instance, and ... step 3 profit?

Sounds like sized_chunks - Rust

This is slightly similar to the stack_dst crate. I haven't really looked at its internals, but they might have some useful ideas:

Both very interesting and slightly different solutions than I'm picturing. Definitely some good stuff to dig through for ideas.

Unfortunately sized_chunks mentions this in its documentation on choosing between its types:

  • I only ever want to push to the back: you don't need this crate, try ArrayVec .

And stack_dst is founded on a default [usize; 9] for its array-backed storage, so no chance at memory footprint reduction (without further customization).

I'm surprised I hadn't seen these yet, just smallbox and ArrayVec/stackvec.

I think I'm just going to wade in and see where this takes me!

Bah, I'm starting to think this might be the simpler solution:

pub struct EnumVecCompactor<const N1: usize, const N2: usize, const N3: usize> {
    type1s: [VariantA; N1],
    type2s: [VariantB; N2],
    type3s: [VariantC; N3],
    // for as many variant types as needed
}

Except that I have further use for the original concept to hold instances of a single struct which has surprisingly different sizes for each of the various generics it can use. I guess I'll do both on my quest to learn Rust better by trying to take everything apart. Working specific cases first may help understand how to transition to being more generic anyway...