Hello
I'm trying to write this data structure: Ctrie - Wikipedia. However, I'm having some problems with part of the data structure.
It is built of nodes of several kinds:
- Leaf node, containing a key-value pair.
- Inner node that contains a bitmap field and then an array of as many atomic pointers as there are ones in the bit field (the bit field doesn't change during the lifetime of the node, so the node doesn't have to shrink or grow).
- Some other service node types that are not interesting right now.
A natural representation would be something like this:
enum Node<K, V> {
Leaf(K, V),
Inner(u32, [AtomicPtr<Node<K, V>>]),
}
Now, there are some problems with this representation:
- I already know the size of the array, so I don't need to waste another machine word to store it once more.
- Enums don't like to be DSTs/unsized, only structs, so this can't be used like this.
- Pointers to DSTs are fat, therefore they can't be used as atomic pointers.
So I'm looking for something that is more like C-style DST. In C I can create a struct that has variable „tail“ and give it enough room by asking malloc to give me more memory. Is there a sane way to do something like this in Rust?
What I've come up with so far is this beast:
enum Tag {
Leaf,
Inner,
}
struct Leaf<K, V>(K, V);
#[repr(C)]
struct Inner<K, V> {
bits: u32,
ptrs: [AtomicPtr<Node<K, V>>; 0],
}
#[repr(C)]
union Tail<K, V> {
leaf: Leaf<K, V>,
inner: Inner<K, V>,
}
#[repr(C)]
struct Node<K, V> {
tag: Tag,
tail: Tail<K, V>,
}
And somehow put this structure together by… um… transmuting things around and moving bytes. And then, when dropping, having to somehow manually transmute it back and stuff so the alocator is told the proper size to free. But that feels very non-Rusty, error prone and tedious.
Is there a better way I'm not seeing (for either creating such structure or solving the problem in some completely different way)? I'm fine with unsafe
for this (I expect it'll be needed when doing such crazy things).