mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 14:52:17 +00:00
SaveTo & Loading
This commit is contained in:
parent
268eaa79f0
commit
d9230f635f
10
merkle/db.go
10
merkle/db.go
@ -22,13 +22,13 @@ func NewLDBDatabase(name string) (*LDBDatabase, error) {
|
|||||||
|
|
||||||
func (db *LDBDatabase) Put(key []byte, value []byte) {
|
func (db *LDBDatabase) Put(key []byte, value []byte) {
|
||||||
err := db.db.Put(key, value, nil)
|
err := db.db.Put(key, value, nil)
|
||||||
if err != nil {
|
if err != nil { panic(err) }
|
||||||
fmt.Println("Error put", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *LDBDatabase) Get(key []byte) ([]byte, error) {
|
func (db *LDBDatabase) Get(key []byte) ([]byte) {
|
||||||
return db.db.Get(key, nil)
|
res, err := db.db.Get(key, nil)
|
||||||
|
if err != nil { panic(err) }
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *LDBDatabase) Delete(key []byte) error {
|
func (db *LDBDatabase) Delete(key []byte) error {
|
||||||
|
299
merkle/iavl.go
299
merkle/iavl.go
@ -1,12 +1,11 @@
|
|||||||
package merkle
|
package merkle
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"math"
|
|
||||||
"io"
|
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const HASH_BYTE_SIZE int = 4+32
|
||||||
|
|
||||||
// Immutable AVL Tree (wraps the Node root)
|
// Immutable AVL Tree (wraps the Node root)
|
||||||
|
|
||||||
type IAVLTree struct {
|
type IAVLTree struct {
|
||||||
@ -33,16 +32,15 @@ func (self *IAVLTree) Has(key Key) bool {
|
|||||||
return self.root.Has(nil, key)
|
return self.root.Has(nil, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLTree) Put(key Key, value Value) (err error) {
|
func (self *IAVLTree) Put(key Key, value Value) {
|
||||||
self.root, _ = self.root.Put(nil, key, value)
|
self.root, _ = self.root.Put(nil, key, value)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLTree) Hash() ([]byte, uint64) {
|
func (self *IAVLTree) Hash() (ByteSlice, uint64) {
|
||||||
return self.root.Hash()
|
return self.root.Hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLTree) Get(key Key) (value Value, err error) {
|
func (self *IAVLTree) Get(key Key) (value Value) {
|
||||||
return self.root.Get(nil, key)
|
return self.root.Get(nil, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,27 +102,18 @@ func (self *IAVLNode) Right(db Db) Node {
|
|||||||
return self.right_filled(db)
|
return self.right_filled(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) left_filled(db Db) *IAVLNode {
|
|
||||||
// XXX
|
|
||||||
return self.left
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *IAVLNode) right_filled(db Db) *IAVLNode {
|
|
||||||
// XXX
|
|
||||||
return self.right
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *IAVLNode) Size() uint64 {
|
func (self *IAVLNode) Size() uint64 {
|
||||||
if self == nil {
|
if self == nil { return 0 }
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return self.size
|
return self.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *IAVLNode) Height() uint8 {
|
||||||
|
if self == nil { return 0 }
|
||||||
|
return self.height
|
||||||
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) Has(db Db, key Key) (has bool) {
|
func (self *IAVLNode) Has(db Db, key Key) (has bool) {
|
||||||
if self == nil {
|
if self == nil { return false }
|
||||||
return false
|
|
||||||
}
|
|
||||||
if self.key.Equals(key) {
|
if self.key.Equals(key) {
|
||||||
return true
|
return true
|
||||||
} else if key.Less(self.key) {
|
} else if key.Less(self.key) {
|
||||||
@ -134,12 +123,10 @@ func (self *IAVLNode) Has(db Db, key Key) (has bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) Get(db Db, key Key) (value Value, err error) {
|
func (self *IAVLNode) Get(db Db, key Key) (value Value) {
|
||||||
if self == nil {
|
if self == nil { return nil }
|
||||||
return nil, NotFound(key)
|
|
||||||
}
|
|
||||||
if self.key.Equals(key) {
|
if self.key.Equals(key) {
|
||||||
return self.value, nil
|
return self.value
|
||||||
} else if key.Less(self.key) {
|
} else if key.Less(self.key) {
|
||||||
return self.left_filled(db).Get(db, key)
|
return self.left_filled(db).Get(db, key)
|
||||||
} else {
|
} else {
|
||||||
@ -147,78 +134,177 @@ func (self *IAVLNode) Get(db Db, key Key) (value Value, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) Bytes() []byte {
|
func (self *IAVLNode) Hash() (ByteSlice, uint64) {
|
||||||
b := new(bytes.Buffer)
|
if self == nil { return nil, 0 }
|
||||||
self.WriteTo(b)
|
|
||||||
return b.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *IAVLNode) Hash() ([]byte, uint64) {
|
|
||||||
if self == nil {
|
|
||||||
return nil, 0
|
|
||||||
}
|
|
||||||
if self.hash != nil {
|
if self.hash != nil {
|
||||||
return self.hash, 0
|
return self.hash, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size := self.ByteSize()
|
||||||
|
buf := make([]byte, size, size)
|
||||||
hasher := sha256.New()
|
hasher := sha256.New()
|
||||||
_, hashCount, err := self.WriteTo(hasher)
|
_, hashCount := self.saveToCountHashes(buf)
|
||||||
if err != nil { panic(err) }
|
hasher.Write(buf)
|
||||||
self.hash = hasher.Sum(nil)
|
self.hash = hasher.Sum(nil)
|
||||||
|
|
||||||
return self.hash, hashCount
|
return self.hash, hashCount+1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) WriteTo(writer io.Writer) (written int64, hashCount uint64, err error) {
|
// TODO: don't clear the hash if the value hasn't changed.
|
||||||
|
func (self *IAVLNode) Put(db Db, key Key, value Value) (_ *IAVLNode, updated bool) {
|
||||||
|
if self == nil {
|
||||||
|
return &IAVLNode{key: key, value: value, height: 1, size: 1, hash: nil}, false
|
||||||
|
}
|
||||||
|
|
||||||
write := func(bytes []byte) {
|
self = self.Copy()
|
||||||
if err == nil {
|
|
||||||
var n int
|
if self.key.Equals(key) {
|
||||||
n, err = writer.Write(bytes)
|
self.value = value
|
||||||
written += int64(n)
|
return self, true
|
||||||
|
}
|
||||||
|
|
||||||
|
if key.Less(self.key) {
|
||||||
|
self.left, updated = self.left_filled(db).Put(db, key, value)
|
||||||
|
} else {
|
||||||
|
self.right, updated = self.right_filled(db).Put(db, key, value)
|
||||||
|
}
|
||||||
|
if updated {
|
||||||
|
return self, updated
|
||||||
|
} else {
|
||||||
|
self.calc_height_and_size(db)
|
||||||
|
return self.balance(db), updated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *IAVLNode) Remove(db Db, key Key) (new_self *IAVLNode, value Value, err error) {
|
||||||
|
if self == nil { return nil, nil, NotFound(key) }
|
||||||
|
|
||||||
|
if self.key.Equals(key) {
|
||||||
|
if self.left != nil && self.right != nil {
|
||||||
|
if self.left_filled(db).Size() < self.right_filled(db).Size() {
|
||||||
|
self, new_self = self.pop_node(db, self.right_filled(db).lmd(db))
|
||||||
|
} else {
|
||||||
|
self, new_self = self.pop_node(db, self.left_filled(db).rmd(db))
|
||||||
|
}
|
||||||
|
new_self.left = self.left
|
||||||
|
new_self.right = self.right
|
||||||
|
new_self.calc_height_and_size(db)
|
||||||
|
return new_self, self.value, nil
|
||||||
|
} else if self.left == nil {
|
||||||
|
return self.right_filled(db), self.value, nil
|
||||||
|
} else if self.right == nil {
|
||||||
|
return self.left_filled(db), self.value, nil
|
||||||
|
} else {
|
||||||
|
return nil, self.value, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if key.Less(self.key) {
|
||||||
|
if self.left == nil {
|
||||||
|
return self, nil, NotFound(key)
|
||||||
|
}
|
||||||
|
var new_left *IAVLNode
|
||||||
|
new_left, value, err = self.left_filled(db).Remove(db, key)
|
||||||
|
if new_left == self.left_filled(db) { // not found
|
||||||
|
return self, nil, err
|
||||||
|
} else if err != nil { // some other error
|
||||||
|
return self, value, err
|
||||||
|
}
|
||||||
|
self = self.Copy()
|
||||||
|
self.left = new_left
|
||||||
|
} else {
|
||||||
|
if self.right == nil {
|
||||||
|
return self, nil, NotFound(key)
|
||||||
|
}
|
||||||
|
var new_right *IAVLNode
|
||||||
|
new_right, value, err = self.right_filled(db).Remove(db, key)
|
||||||
|
if new_right == self.right_filled(db) { // not found
|
||||||
|
return self, nil, err
|
||||||
|
} else if err != nil { // some other error
|
||||||
|
return self, value, err
|
||||||
|
}
|
||||||
|
self = self.Copy()
|
||||||
|
self.right = new_right
|
||||||
|
}
|
||||||
|
self.calc_height_and_size(db)
|
||||||
|
return self.balance(db), value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *IAVLNode) ByteSize() int {
|
||||||
|
// 1 byte node descriptor
|
||||||
|
// 1 byte node neight
|
||||||
|
// 8 bytes node size
|
||||||
|
size := 10
|
||||||
|
size += self.key.ByteSize()
|
||||||
|
if self.value != nil {
|
||||||
|
size += self.value.ByteSize()
|
||||||
|
} else {
|
||||||
|
size += 1
|
||||||
|
}
|
||||||
|
if self.left != nil {
|
||||||
|
size += HASH_BYTE_SIZE
|
||||||
|
}
|
||||||
|
if self.right != nil {
|
||||||
|
size += HASH_BYTE_SIZE
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *IAVLNode) SaveTo(buf []byte) int {
|
||||||
|
written, _ := self.saveToCountHashes(buf)
|
||||||
|
return written
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *IAVLNode) saveToCountHashes(buf []byte) (int, uint64) {
|
||||||
|
cur := 0
|
||||||
|
hashCount := uint64(0)
|
||||||
|
|
||||||
// node descriptor
|
// node descriptor
|
||||||
nodeDesc := byte(0)
|
nodeDesc := byte(0)
|
||||||
if self.value != nil { nodeDesc |= 0x01 }
|
if self.value != nil { nodeDesc |= 0x01 }
|
||||||
if self.left != nil { nodeDesc |= 0x02 }
|
if self.left != nil { nodeDesc |= 0x02 }
|
||||||
if self.right != nil { nodeDesc |= 0x04 }
|
if self.right != nil { nodeDesc |= 0x04 }
|
||||||
write([]byte{nodeDesc})
|
cur += UInt8(nodeDesc).SaveTo(buf[cur:])
|
||||||
|
|
||||||
// node height & size
|
// node height & size
|
||||||
write(UInt8(self.height).Bytes())
|
cur += UInt8(self.height).SaveTo(buf[cur:])
|
||||||
write(UInt64(self.size).Bytes())
|
cur += UInt64(self.size).SaveTo(buf[cur:])
|
||||||
|
|
||||||
// node key
|
// node key
|
||||||
keyBytes := self.key.Bytes()
|
cur += self.key.SaveTo(buf[cur:])
|
||||||
if len(keyBytes) > 255 { panic("key is too long") }
|
|
||||||
write([]byte{byte(len(keyBytes))})
|
|
||||||
write(keyBytes)
|
|
||||||
|
|
||||||
// node value
|
// node value
|
||||||
if self.value != nil {
|
if self.value != nil {
|
||||||
valueBytes := self.value.Bytes()
|
cur += self.value.SaveTo(buf[cur:])
|
||||||
if len(valueBytes) > math.MaxUint32 { panic("value is too long") }
|
} else {
|
||||||
write([]byte{byte(len(valueBytes))})
|
cur += UInt8(0).SaveTo(buf[cur:])
|
||||||
write(valueBytes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// left child
|
// left child
|
||||||
if self.left != nil {
|
if self.left != nil {
|
||||||
leftHash, leftCount := self.left.Hash()
|
leftHash, leftCount := self.left.Hash()
|
||||||
hashCount += leftCount
|
hashCount += leftCount
|
||||||
write(leftHash)
|
cur += leftHash.SaveTo(buf[cur:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// right child
|
// right child
|
||||||
if self.right != nil {
|
if self.right != nil {
|
||||||
rightHash, rightCount := self.right.Hash()
|
rightHash, rightCount := self.right.Hash()
|
||||||
hashCount += rightCount
|
hashCount += rightCount
|
||||||
write(rightHash)
|
cur += rightHash.SaveTo(buf[cur:])
|
||||||
}
|
}
|
||||||
|
|
||||||
return written, hashCount+1, err
|
return cur, hashCount
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *IAVLNode) left_filled(db Db) *IAVLNode {
|
||||||
|
// XXX
|
||||||
|
return self.left
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *IAVLNode) right_filled(db Db) *IAVLNode {
|
||||||
|
// XXX
|
||||||
|
return self.right
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a new tree (unless node is the root) & a copy of the popped node.
|
// Returns a new tree (unless node is the root) & a copy of the popped node.
|
||||||
@ -332,97 +418,6 @@ func (self *IAVLNode) balance(db Db) (new_self *IAVLNode) {
|
|||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: don't clear the hash if the value hasn't changed.
|
|
||||||
func (self *IAVLNode) Put(db Db, key Key, value Value) (_ *IAVLNode, updated bool) {
|
|
||||||
if self == nil {
|
|
||||||
return &IAVLNode{key: key, value: value, height: 1, size: 1, hash: nil}, false
|
|
||||||
}
|
|
||||||
|
|
||||||
self = self.Copy()
|
|
||||||
|
|
||||||
if self.key.Equals(key) {
|
|
||||||
self.value = value
|
|
||||||
return self, true
|
|
||||||
}
|
|
||||||
|
|
||||||
if key.Less(self.key) {
|
|
||||||
self.left, updated = self.left_filled(db).Put(db, key, value)
|
|
||||||
} else {
|
|
||||||
self.right, updated = self.right_filled(db).Put(db, key, value)
|
|
||||||
}
|
|
||||||
if updated {
|
|
||||||
return self, updated
|
|
||||||
} else {
|
|
||||||
self.calc_height_and_size(db)
|
|
||||||
return self.balance(db), updated
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *IAVLNode) Remove(db Db, key Key) (new_self *IAVLNode, value Value, err error) {
|
|
||||||
if self == nil {
|
|
||||||
return nil, nil, NotFound(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.key.Equals(key) {
|
|
||||||
if self.left != nil && self.right != nil {
|
|
||||||
if self.left_filled(db).Size() < self.right_filled(db).Size() {
|
|
||||||
self, new_self = self.pop_node(db, self.right_filled(db).lmd(db))
|
|
||||||
} else {
|
|
||||||
self, new_self = self.pop_node(db, self.left_filled(db).rmd(db))
|
|
||||||
}
|
|
||||||
new_self.left = self.left
|
|
||||||
new_self.right = self.right
|
|
||||||
new_self.calc_height_and_size(db)
|
|
||||||
return new_self, self.value, nil
|
|
||||||
} else if self.left == nil {
|
|
||||||
return self.right_filled(db), self.value, nil
|
|
||||||
} else if self.right == nil {
|
|
||||||
return self.left_filled(db), self.value, nil
|
|
||||||
} else {
|
|
||||||
return nil, self.value, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if key.Less(self.key) {
|
|
||||||
if self.left == nil {
|
|
||||||
return self, nil, NotFound(key)
|
|
||||||
}
|
|
||||||
var new_left *IAVLNode
|
|
||||||
new_left, value, err = self.left_filled(db).Remove(db, key)
|
|
||||||
if new_left == self.left_filled(db) { // not found
|
|
||||||
return self, nil, err
|
|
||||||
} else if err != nil { // some other error
|
|
||||||
return self, value, err
|
|
||||||
}
|
|
||||||
self = self.Copy()
|
|
||||||
self.left = new_left
|
|
||||||
} else {
|
|
||||||
if self.right == nil {
|
|
||||||
return self, nil, NotFound(key)
|
|
||||||
}
|
|
||||||
var new_right *IAVLNode
|
|
||||||
new_right, value, err = self.right_filled(db).Remove(db, key)
|
|
||||||
if new_right == self.right_filled(db) { // not found
|
|
||||||
return self, nil, err
|
|
||||||
} else if err != nil { // some other error
|
|
||||||
return self, value, err
|
|
||||||
}
|
|
||||||
self = self.Copy()
|
|
||||||
self.right = new_right
|
|
||||||
}
|
|
||||||
self.calc_height_and_size(db)
|
|
||||||
return self.balance(db), value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *IAVLNode) Height() uint8 {
|
|
||||||
if self == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return self.height
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
func (self *IAVLNode) _md(side func(*IAVLNode)*IAVLNode) (*IAVLNode) {
|
func (self *IAVLNode) _md(side func(*IAVLNode)*IAVLNode) (*IAVLNode) {
|
||||||
if self == nil {
|
if self == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -80,9 +80,7 @@ func TestImmutableAvlPutHasGetRemove(t *testing.T) {
|
|||||||
if has := tree.Has(nil, randstr(12)); has {
|
if has := tree.Has(nil, randstr(12)); has {
|
||||||
t.Error("Table has extra key")
|
t.Error("Table has extra key")
|
||||||
}
|
}
|
||||||
if val, err := tree.Get(nil, r.key); err != nil {
|
if val := tree.Get(nil, r.key); !(val.(String)).Equals(r.value) {
|
||||||
t.Error(err, val.(String), r.value)
|
|
||||||
} else if !(val.(String)).Equals(r.value) {
|
|
||||||
t.Error("wrong value")
|
t.Error("wrong value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,9 +98,7 @@ func TestImmutableAvlPutHasGetRemove(t *testing.T) {
|
|||||||
if has := tree.Has(nil, randstr(12)); has {
|
if has := tree.Has(nil, randstr(12)); has {
|
||||||
t.Error("Table has extra key")
|
t.Error("Table has extra key")
|
||||||
}
|
}
|
||||||
if val, err := tree.Get(nil, r.key); err != nil {
|
if val := tree.Get(nil, r.key); !(val.(String)).Equals(r.value) {
|
||||||
t.Error(err)
|
|
||||||
} else if !(val.(String)).Equals(r.value) {
|
|
||||||
t.Error("wrong value")
|
t.Error("wrong value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,9 +147,7 @@ func TestTraversals(t *testing.T) {
|
|||||||
test := func(T Tree) {
|
test := func(T Tree) {
|
||||||
t.Logf("%T", T)
|
t.Logf("%T", T)
|
||||||
for j := range order {
|
for j := range order {
|
||||||
if err := T.Put(Int(data[order[j]]), Int(order[j])); err != nil {
|
T.Put(Int(data[order[j]]), Int(order[j]))
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
j := 0
|
j := 0
|
||||||
|
175
merkle/int.go
175
merkle/int.go
@ -16,6 +16,8 @@ type Int int
|
|||||||
type UInt uint
|
type UInt uint
|
||||||
|
|
||||||
|
|
||||||
|
// Int8
|
||||||
|
|
||||||
func (self Int8) Equals(other Key) bool {
|
func (self Int8) Equals(other Key) bool {
|
||||||
if o, ok := other.(Int8); ok {
|
if o, ok := other.(Int8); ok {
|
||||||
return self == o
|
return self == o
|
||||||
@ -32,10 +34,22 @@ func (self Int8) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Int8) Bytes() []byte {
|
func (self Int8) ByteSize() int {
|
||||||
return []byte{byte(self)}
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self Int8) SaveTo(b []byte) int {
|
||||||
|
if cap(b) < 1 { panic("buf too small") }
|
||||||
|
b[0] = byte(self)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadInt8(bytes []byte) Int8 {
|
||||||
|
return Int8(bytes[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// UInt8
|
||||||
|
|
||||||
func (self UInt8) Equals(other Key) bool {
|
func (self UInt8) Equals(other Key) bool {
|
||||||
if o, ok := other.(UInt8); ok {
|
if o, ok := other.(UInt8); ok {
|
||||||
@ -53,10 +67,22 @@ func (self UInt8) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self UInt8) Bytes() []byte {
|
func (self UInt8) ByteSize() int {
|
||||||
return []byte{byte(self)}
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self UInt8) SaveTo(b []byte) int {
|
||||||
|
if cap(b) < 1 { panic("buf too small") }
|
||||||
|
b[0] = byte(self)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadUInt8(bytes []byte) UInt8 {
|
||||||
|
return UInt8(bytes[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Int16
|
||||||
|
|
||||||
func (self Int16) Equals(other Key) bool {
|
func (self Int16) Equals(other Key) bool {
|
||||||
if o, ok := other.(Int16); ok {
|
if o, ok := other.(Int16); ok {
|
||||||
@ -74,12 +100,22 @@ func (self Int16) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Int16) Bytes() []byte {
|
func (self Int16) ByteSize() int {
|
||||||
b := [2]byte{}
|
return 2
|
||||||
binary.LittleEndian.PutUint16(b[:], uint16(self))
|
|
||||||
return b[:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self Int16) SaveTo(b []byte) int {
|
||||||
|
if cap(b) < 2 { panic("buf too small") }
|
||||||
|
binary.LittleEndian.PutUint16(b, uint16(self))
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadInt16(bytes []byte) Int16 {
|
||||||
|
return Int16(binary.LittleEndian.Uint16(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// UInt16
|
||||||
|
|
||||||
func (self UInt16) Equals(other Key) bool {
|
func (self UInt16) Equals(other Key) bool {
|
||||||
if o, ok := other.(UInt16); ok {
|
if o, ok := other.(UInt16); ok {
|
||||||
@ -97,12 +133,22 @@ func (self UInt16) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self UInt16) Bytes() []byte {
|
func (self UInt16) ByteSize() int {
|
||||||
b := [2]byte{}
|
return 2
|
||||||
binary.LittleEndian.PutUint16(b[:], uint16(self))
|
|
||||||
return b[:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self UInt16) SaveTo(b []byte) int {
|
||||||
|
if cap(b) < 2 { panic("buf too small") }
|
||||||
|
binary.LittleEndian.PutUint16(b, uint16(self))
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadUInt16(bytes []byte) UInt16 {
|
||||||
|
return UInt16(binary.LittleEndian.Uint16(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Int32
|
||||||
|
|
||||||
func (self Int32) Equals(other Key) bool {
|
func (self Int32) Equals(other Key) bool {
|
||||||
if o, ok := other.(Int32); ok {
|
if o, ok := other.(Int32); ok {
|
||||||
@ -120,12 +166,22 @@ func (self Int32) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Int32) Bytes() []byte {
|
func (self Int32) ByteSize() int {
|
||||||
b := [4]byte{}
|
return 4
|
||||||
binary.LittleEndian.PutUint32(b[:], uint32(self))
|
|
||||||
return b[:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self Int32) SaveTo(b []byte) int {
|
||||||
|
if cap(b) < 4 { panic("buf too small") }
|
||||||
|
binary.LittleEndian.PutUint32(b, uint32(self))
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadInt32(bytes []byte) Int32 {
|
||||||
|
return Int32(binary.LittleEndian.Uint32(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// UInt32
|
||||||
|
|
||||||
func (self UInt32) Equals(other Key) bool {
|
func (self UInt32) Equals(other Key) bool {
|
||||||
if o, ok := other.(UInt32); ok {
|
if o, ok := other.(UInt32); ok {
|
||||||
@ -143,12 +199,22 @@ func (self UInt32) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self UInt32) Bytes() []byte {
|
func (self UInt32) ByteSize() int {
|
||||||
b := [4]byte{}
|
return 4
|
||||||
binary.LittleEndian.PutUint32(b[:], uint32(self))
|
|
||||||
return b[:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self UInt32) SaveTo(b []byte) int {
|
||||||
|
if cap(b) < 4 { panic("buf too small") }
|
||||||
|
binary.LittleEndian.PutUint32(b, uint32(self))
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadUInt32(bytes []byte) UInt32 {
|
||||||
|
return UInt32(binary.LittleEndian.Uint32(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Int64
|
||||||
|
|
||||||
func (self Int64) Equals(other Key) bool {
|
func (self Int64) Equals(other Key) bool {
|
||||||
if o, ok := other.(Int64); ok {
|
if o, ok := other.(Int64); ok {
|
||||||
@ -166,12 +232,22 @@ func (self Int64) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Int64) Bytes() []byte {
|
func (self Int64) ByteSize() int {
|
||||||
b := [8]byte{}
|
return 8
|
||||||
binary.LittleEndian.PutUint64(b[:], uint64(self))
|
|
||||||
return b[:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self Int64) SaveTo(b []byte) int {
|
||||||
|
if cap(b) < 8 { panic("buf too small") }
|
||||||
|
binary.LittleEndian.PutUint64(b, uint64(self))
|
||||||
|
return 8
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadInt64(bytes []byte) Int64 {
|
||||||
|
return Int64(binary.LittleEndian.Uint64(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// UInt64
|
||||||
|
|
||||||
func (self UInt64) Equals(other Key) bool {
|
func (self UInt64) Equals(other Key) bool {
|
||||||
if o, ok := other.(UInt64); ok {
|
if o, ok := other.(UInt64); ok {
|
||||||
@ -189,12 +265,22 @@ func (self UInt64) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self UInt64) Bytes() []byte {
|
func (self UInt64) ByteSize() int {
|
||||||
b := [8]byte{}
|
return 8
|
||||||
binary.LittleEndian.PutUint64(b[:], uint64(self))
|
|
||||||
return b[:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self UInt64) SaveTo(b []byte) int {
|
||||||
|
if cap(b) < 8 { panic("buf too small") }
|
||||||
|
binary.LittleEndian.PutUint64(b, uint64(self))
|
||||||
|
return 8
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadUInt64(bytes []byte) UInt64 {
|
||||||
|
return UInt64(binary.LittleEndian.Uint64(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Int
|
||||||
|
|
||||||
func (self Int) Equals(other Key) bool {
|
func (self Int) Equals(other Key) bool {
|
||||||
if o, ok := other.(Int); ok {
|
if o, ok := other.(Int); ok {
|
||||||
@ -212,12 +298,21 @@ func (self Int) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Int) Bytes() []byte {
|
func (self Int) ByteSize() int {
|
||||||
b := [8]byte{}
|
return 8
|
||||||
binary.LittleEndian.PutUint64(b[:], uint64(self))
|
|
||||||
return b[:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self Int) SaveTo(b []byte) int {
|
||||||
|
if cap(b) < 8 { panic("buf too small") }
|
||||||
|
binary.LittleEndian.PutUint64(b, uint64(self))
|
||||||
|
return 8
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadInt(bytes []byte) Int {
|
||||||
|
return Int(binary.LittleEndian.Uint64(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UInt
|
||||||
|
|
||||||
func (self UInt) Equals(other Key) bool {
|
func (self UInt) Equals(other Key) bool {
|
||||||
if o, ok := other.(UInt); ok {
|
if o, ok := other.(UInt); ok {
|
||||||
@ -235,8 +330,16 @@ func (self UInt) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self UInt) Bytes() []byte {
|
func (self UInt) ByteSize() int {
|
||||||
b := [8]byte{}
|
return 8
|
||||||
binary.LittleEndian.PutUint64(b[:], uint64(self))
|
}
|
||||||
return b[:]
|
|
||||||
|
func (self UInt) SaveTo(b []byte) int {
|
||||||
|
if cap(b) < 8 { panic("buf too small") }
|
||||||
|
binary.LittleEndian.PutUint64(b, uint64(self))
|
||||||
|
return 8
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadUInt(bytes []byte) UInt {
|
||||||
|
return UInt(binary.LittleEndian.Uint64(bytes))
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import "bytes"
|
|||||||
type String string
|
type String string
|
||||||
type ByteSlice []byte
|
type ByteSlice []byte
|
||||||
|
|
||||||
|
// String
|
||||||
|
|
||||||
func (self String) Equals(other Key) bool {
|
func (self String) Equals(other Key) bool {
|
||||||
if o, ok := other.(String); ok {
|
if o, ok := other.(String); ok {
|
||||||
return self == o
|
return self == o
|
||||||
@ -21,10 +23,25 @@ func (self String) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self String) Bytes() []byte {
|
func (self String) ByteSize() int {
|
||||||
return []byte(self)
|
return len(self)+4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self String) SaveTo(buf []byte) int {
|
||||||
|
if len(buf) < self.ByteSize() { panic("buf too small") }
|
||||||
|
UInt32(len(self)).SaveTo(buf)
|
||||||
|
copy(buf[4:], []byte(self))
|
||||||
|
return len(self)+4
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadString(bytes []byte) String {
|
||||||
|
length := LoadUInt32(bytes)
|
||||||
|
return String(bytes[4:4+length])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ByteSlice
|
||||||
|
|
||||||
func (self ByteSlice) Equals(other Key) bool {
|
func (self ByteSlice) Equals(other Key) bool {
|
||||||
if o, ok := other.(ByteSlice); ok {
|
if o, ok := other.(ByteSlice); ok {
|
||||||
return bytes.Equal(self, o)
|
return bytes.Equal(self, o)
|
||||||
@ -41,6 +58,18 @@ func (self ByteSlice) Less(other Key) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self ByteSlice) Bytes() []byte {
|
func (self ByteSlice) ByteSize() int {
|
||||||
return []byte(self)
|
return len(self)+4
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self ByteSlice) SaveTo(buf []byte) int {
|
||||||
|
if len(buf) < self.ByteSize() { panic("buf too small") }
|
||||||
|
UInt32(len(self)).SaveTo(buf)
|
||||||
|
copy(buf[4:], self)
|
||||||
|
return len(self)+4
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadByteSlice(bytes []byte) ByteSlice {
|
||||||
|
length := LoadUInt32(bytes)
|
||||||
|
return ByteSlice(bytes[4:4+length])
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,20 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Binary interface {
|
||||||
|
ByteSize() int
|
||||||
|
SaveTo([]byte) int
|
||||||
|
}
|
||||||
|
|
||||||
type Value interface {
|
type Value interface {
|
||||||
Bytes() []byte
|
Binary
|
||||||
}
|
}
|
||||||
|
|
||||||
type Key interface {
|
type Key interface {
|
||||||
|
Binary
|
||||||
|
|
||||||
Equals(b Key) bool
|
Equals(b Key) bool
|
||||||
Less(b Key) bool
|
Less(b Key) bool
|
||||||
Bytes() []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tree interface {
|
type Tree interface {
|
||||||
@ -20,19 +26,21 @@ type Tree interface {
|
|||||||
Size() uint64
|
Size() uint64
|
||||||
Height() uint8
|
Height() uint8
|
||||||
Has(key Key) bool
|
Has(key Key) bool
|
||||||
Get(key Key) (Value, error)
|
Get(key Key) Value
|
||||||
Hash() ([]byte, uint64)
|
Hash() (ByteSlice, uint64)
|
||||||
|
|
||||||
Put(Key, Value) (err error)
|
Put(Key, Value)
|
||||||
Remove(Key) (Value, error)
|
Remove(Key) (Value, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Db interface {
|
type Db interface {
|
||||||
Get([]byte) ([]byte, error)
|
Get([]byte) []byte
|
||||||
Put([]byte, []byte) error
|
Put([]byte, []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Node interface {
|
type Node interface {
|
||||||
|
Binary
|
||||||
|
|
||||||
Key() Key
|
Key() Key
|
||||||
Value() Value
|
Value() Value
|
||||||
Left(Db) Node
|
Left(Db) Node
|
||||||
@ -41,9 +49,8 @@ type Node interface {
|
|||||||
Size() uint64
|
Size() uint64
|
||||||
Height() uint8
|
Height() uint8
|
||||||
Has(Db, Key) bool
|
Has(Db, Key) bool
|
||||||
Get(Db, Key) (Value, error)
|
Get(Db, Key) Value
|
||||||
Hash() ([]byte, uint64)
|
Hash() (ByteSlice, uint64)
|
||||||
Bytes() []byte
|
|
||||||
|
|
||||||
Put(Db, Key, Value) (*IAVLNode, bool)
|
Put(Db, Key, Value) (*IAVLNode, bool)
|
||||||
Remove(Db, Key) (*IAVLNode, Value, error)
|
Remove(Db, Key) (*IAVLNode, Value, error)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user