diff --git a/part/node.go b/part/node.go index b2f2fa3..8490f39 100644 --- a/part/node.go +++ b/part/node.go @@ -25,7 +25,6 @@ const ( type header[T any] struct { flags uint16 // kind(4b) | unused(3b) | size(9b) prefix []byte // the compressed prefix, [0] is the key - leaf *leaf[T] // non-nil if this node contains a value watch chan struct{} // watch channel that is closed when this node mutates } @@ -63,10 +62,37 @@ func (n *header[T]) isLeaf() bool { } func (n *header[T]) getLeaf() *leaf[T] { - if n.isLeaf() { + switch n.kind() { + case nodeKindLeaf: return (*leaf[T])(unsafe.Pointer(n)) + case nodeKind4: + return n.node4().leaf + case nodeKind16: + return n.node16().leaf + case nodeKind48: + return n.node48().leaf + case nodeKind256: + return n.node256().leaf + default: + panic("unknown node kind") + } +} + +func (n *header[T]) setLeaf(l *leaf[T]) { + switch n.kind() { + case nodeKindLeaf: + panic("cannot setLeaf on a leaf[T]") + case nodeKind4: + n.node4().leaf = l + case nodeKind16: + n.node16().leaf = l + case nodeKind48: + n.node48().leaf = l + case nodeKind256: + n.node256().leaf = l + default: + panic("unknown node kind") } - return n.leaf } func (n *header[T]) size() int { @@ -296,21 +322,25 @@ func newLeaf[T any](o *options, prefix, key []byte, value T) *leaf[T] { type node4[T any] struct { header[T] + leaf *leaf[T] // non-nil if this node contains a value children [4]*header[T] } type node16[T any] struct { header[T] + leaf *leaf[T] // non-nil if this node contains a value children [16]*header[T] } type node48[T any] struct { header[T] + leaf *leaf[T] // non-nil if this node contains a value children [48]*header[T] } type node256[T any] struct { header[T] + leaf *leaf[T] // non-nil if this node contains a value children [256]*header[T] } diff --git a/part/txn.go b/part/txn.go index 6e9dddc..606d6c5 100644 --- a/part/txn.go +++ b/part/txn.go @@ -153,7 +153,7 @@ func (txn *Txn[T]) insert(root *header[T], key []byte, value T) (oldValue T, had hadOld = true } else { // This is a non-leaf node, create/replace the existing leaf. - this.leaf = newLeaf(txn.opts, key, fullKey, value) + this.setLeaf(newLeaf(txn.opts, key, fullKey, value)) } return } @@ -267,7 +267,7 @@ func (txn *Txn[T]) delete(root *header[T], key []byte) (oldValue T, hadOld bool, newRoot = newNode4[T]() } else { newRoot = txn.cloneNode(root) - newRoot.leaf = nil + newRoot.setLeaf(nil) } return } @@ -293,11 +293,11 @@ func (txn *Txn[T]) delete(root *header[T], key []byte) (oldValue T, hadOld bool, // This is the node that we want to delete, but it has // children. Clone and clear the leaf. target.node = txn.cloneNode(target.node) - target.node.leaf = nil + target.node.setLeaf(nil) children[target.index] = target.node } - if target.node.size() == 0 && (target.node == this || target.node.leaf == nil) { + if target.node.size() == 0 && (target.node == this || target.node.getLeaf() == nil) { // The node is empty, remove it from the parent. parent.node.remove(target.index) } else {