README.md
v0 - Unaudited This is an initial version of this package that has not yet been formally audited. A fully audited version will be published as a subsequent release. Use in production at your own risk.
bptree - Mutable B+ tree
A mutable, in-place B+ tree for storing key-value data in Gno realms. Exposes the same ITree interface as gno.land/p/nt/avl/v0 but uses a B+ tree internally — fewer pointer dereferences per operation and better cache locality, with a configurable fanout.
Usage
1package myrealm
2
3import "gno.land/p/nt/bptree/v0"
4
5// Zero value is usable (fanout 32). Persisted across transactions.
6var tree bptree.BPTree
7
8func Set(key string, value int) {
9 tree.Set(key, value)
10}
11
12func Get(key string) int {
13 raw := tree.Get(key)
14 if raw == nil {
15 panic("not found")
16 }
17 return raw.(int)
18}
19
20func RangeAsc(start, end string) {
21 tree.Iterate(start, end, func(key string, value any) bool {
22 // return true to stop early
23 return false
24 })
25}
For a different fanout, use a constructor:
1tree := bptree.NewBPTreeN(64) // fanout 64
API
1type BPTree struct{ /* unexported */ }
2
3func NewBPTree32() *BPTree // fanout 32
4func NewBPTreeN(fanout int) *BPTree // panics if fanout < 4
5
6// Read
7func (t *BPTree) Size() int
8func (t *BPTree) Has(key string) bool
9func (t *BPTree) Get(key string) (value any) // nil if the key is absent
10func (t *BPTree) GetByIndex(index int) (key string, value any)
11func (t *BPTree) Iterate(start, end string, cb IterCbFn) bool
12func (t *BPTree) ReverseIterate(start, end string, cb IterCbFn) bool
13func (t *BPTree) IterateByOffset(offset, count int, cb IterCbFn) bool
14func (t *BPTree) ReverseIterateByOffset(offset, count int, cb IterCbFn) bool
15
16// Write
17func (t *BPTree) Set(key string, value any) (updated bool)
18func (t *BPTree) Remove(key string) (value any, removed bool)
19
20type IterCbFn func(key string, value any) bool
21
22type ITree interface { /* same shape as BPTree's methods */ }
The zero value of BPTree is a usable empty tree (fanout 32). Iterate uses [start, end) (start inclusive, end exclusive); ReverseIterate uses [start, end] (both inclusive). Empty strings mean unbounded. Callbacks return true to stop early. GetByIndex panics on out-of-range indices.
The tree must not be modified during iteration (no Set or Remove from the callback).
Subpackages
gno.land/p/nt/bptree/v0/list- ordered list built on top ofBPTree.gno.land/p/nt/bptree/v0/pager- pagination helper for trees and lists.gno.land/p/nt/bptree/v0/rotree- read-only view of aBPTree.
Notes
- API and semantics match
gno.land/p/nt/avl/v0exactly —""is a valid key,Getreturnsnilfor a missing key (useHasto distinguish a storednil), andRemovereturns(nil, false). - Never return the live
*BPTreefrom a realm getter: a caller can then callSet/Removeon it under your realm's authority. Return values, copies, or a read-onlyrotreeview. - Sequential keys from
seqid(gno.land/p/nt/seqid/v0) pair well here: monotonic inserts hit the append-optimized split path. - Fanout must be
>= 4. Higher fanouts mean shallower trees and fewer object loads per lookup, at the cost of larger individual node objects. - Each node (leaf or inner) is persisted as a separate object, so reads only load the
O(log n)nodes on the search path — same storage-efficiency benefit asavl. - No sibling pointers or
first/lastshortcuts: iteration uses an ephemeral stack to keep every persisted node at ref-count 1 (avoids Gno's object-escape penalty).