tree.gno
2.98 Kb ยท 124 lines
1package staker
2
3import (
4 "strconv"
5 "strings"
6
7 "gno.land/p/nt/avl"
8 "gno.land/p/nt/ufmt"
9)
10
11// UintTree is a wrapper around an AVL tree for storing block timestamps as strings.
12// Since block timestamps are defined as int64, we take int64 and convert it to uint64 for the tree.
13//
14// Methods:
15// - Get: Retrieves a value associated with a uint64 key.
16// - set: Stores a value with a uint64 key.
17// - Has: Checks if a uint64 key exists in the tree.
18// - remove: Removes a uint64 key and its associated value.
19// - Iterate: Iterates over keys and values in a range.
20// - ReverseIterate: Iterates in reverse order over keys and values in a range.
21type UintTree struct {
22 tree *avl.Tree // blockTimestamp -> any
23}
24
25// NewUintTree creates a new UintTree instance.
26func NewUintTree() *UintTree {
27 return &UintTree{
28 tree: avl.NewTree(),
29 }
30}
31
32func (self *UintTree) Get(key int64) (any, bool) {
33 v, ok := self.tree.Get(EncodeInt64(key))
34 if !ok {
35 return nil, false
36 }
37 return v, true
38}
39
40func (self *UintTree) Set(key int64, value any) {
41 self.tree.Set(EncodeInt64(key), value)
42}
43
44func (self *UintTree) Has(key int64) bool {
45 return self.tree.Has(EncodeInt64(key))
46}
47
48func (self *UintTree) Remove(key int64) {
49 self.tree.Remove(EncodeInt64(key))
50}
51
52func (self *UintTree) Iterate(start, end int64, fn func(key int64, value any) bool) {
53 self.tree.Iterate(EncodeInt64(start), EncodeInt64(end), func(key string, value any) bool {
54 return fn(DecodeInt64(key), value)
55 })
56}
57
58func (self *UintTree) ReverseIterate(start, end int64, fn func(key int64, value any) bool) {
59 self.tree.ReverseIterate(EncodeInt64(start), EncodeInt64(end), func(key string, value any) bool {
60 return fn(DecodeInt64(key), value)
61 })
62}
63
64// Size returns the number of entries in the tree.
65func (self *UintTree) Size() int {
66 return self.tree.Size()
67}
68
69// EncodeUint converts a uint64 number into a zero-padded 20-character string.
70//
71// Parameters:
72// - num (uint64): The number to encode.
73//
74// Returns:
75// - string: A zero-padded string representation of the number.
76//
77// Example:
78// Input: 12345
79// Output: "00000000000000012345"
80func EncodeUint(num uint64) string {
81 // Convert the value to a decimal string.
82 s := strconv.FormatUint(num, 10)
83
84 // Zero-pad to a total length of 20 characters.
85 zerosNeeded := 20 - len(s)
86 return strings.Repeat("0", zerosNeeded) + s
87}
88
89func EncodeInt64(num int64) string {
90 if num < 0 {
91 panic(ufmt.Sprintf("negative value not supported: %d", num))
92 }
93 return EncodeUint(uint64(num))
94}
95
96// DecodeUint converts a zero-padded string back into a uint64 number.
97//
98// Parameters:
99// - s (string): The zero-padded string.
100//
101// Returns:
102// - uint64: The decoded number.
103//
104// Panics:
105// - If the string cannot be parsed into a uint64.
106//
107// Example:
108// Input: "00000000000000012345"
109// Output: 12345
110func DecodeUint(s string) uint64 {
111 num, err := strconv.ParseUint(s, 10, 64)
112 if err != nil {
113 panic(err)
114 }
115 return num
116}
117
118func DecodeInt64(s string) int64 {
119 num, err := strconv.ParseInt(s, 10, 64)
120 if err != nil {
121 panic(err)
122 }
123 return num
124}