+// place returns the position of the node (l, i) if it is built.
+func (t *Tree) place(level, index int) (position, bool, error) {
+ if level < 0 || level >= bits.UintSize-2 || index < 0 {
+ return position{}, false, nil
+ }
+
+ records, err := t.level(level)
+ if err != nil {
+ return position{}, false, err
+ }
+
+ record, found, err := records.Read(index)
+ if err != nil || !found {
+ return position{}, false, err
+ }
+
+ place := decodePosition(record)
+
+ return place, place.length > 0, nil
+}
+
+// Node reads the node (l, i) if it is built.
+func (t *Tree) Node(level, index int) (Node, bool, error) {
+ place, built, err := t.place(level, index)
+ if err != nil || !built {
+ return Node{}, false, err
+ }
+
+ line, err := t.journal.Read(place)
+ if err != nil {
+ return Node{}, false, fmt.Errorf("read node (%d, %d): %w", level, index, err)
+ }
+
+ var node Node
+ err = json.Unmarshal(line, &node)
+ if err != nil {
+ return Node{}, false, fmt.Errorf("decode node (%d, %d): %w", level, index, err)
+ }
+
+ if node.Level != level || node.Index != index {
+ return Node{}, false, fmt.Errorf("index of node (%d, %d) points to node (%d, %d)", level, index, node.Level, node.Index)
+ }
+
+ return node, true, nil
+}
+
+// Count returns the number of built nodes.
+func (t *Tree) Count() int {
+ return t.order.count
+}
+
+// Keys returns the keys of the built nodes, ordered by level and then by index.
+func (t *Tree) Keys() ([]nodeKey, error) {
+ keys := make([]nodeKey, 0, t.order.count)
+ for n := range t.order.count {
+ record, _, err := t.order.Read(n)
+ if err != nil {
+ return nil, err
+ }
+
+ key, _ := decodeTreeRecord(record)
+ keys = append(keys, key)
+ }
+
+ slices.SortFunc(keys, func(a, b nodeKey) int {
+ return cmp.Or(cmp.Compare(a.level, b.level), cmp.Compare(a.index, b.index))
+ })
+
+ return keys, nil