diff --git a/trie/internal/vlc/buffer.go b/trie/internal/vlc/buffer.go new file mode 100644 index 000000000..3ca1a67a2 --- /dev/null +++ b/trie/internal/vlc/buffer.go @@ -0,0 +1,59 @@ +// Copyright (c) 2023 The VeChainThor developers + +// Distributed under the GNU Lesser General Public License v3.0 software license, see the accompanying +// file LICENSE or + +// Package vlc implements variable length coding. +// +// It's much simpler and a bit faster than RLP. +// Trie nodes stored in database are encoded using VLC. +package vlc + +import "encoding/binary" + +// Buffer is essentially a byte slice. It holds encoded elements. +type Buffer []byte + +// Truncate truncates the buffer to size. +func (b *Buffer) Truncate(size int) { + *b = (*b)[:size] +} + +// PutUint puts the uint value. +func (b *Buffer) PutUint(i uint64) { + *b = binary.AppendUvarint(*b, i) +} + +// PutString puts the string value. +func (b *Buffer) PutString(str []byte) { + *b = binary.AppendUvarint(*b, uint64(len(str))) + *b = append(*b, str...) +} + +// PutFunc puts the string value returned by func build. +// The build func should not modify existing content of buf, +// and should follow the behavior like append. +func (b *Buffer) PutFunc(build func(buf []byte) []byte) { + offset := len(*b) + *b = append(*b, make([]byte, binary.MaxVarintLen64)...) + *b = build(*b) + + str := (*b)[offset+binary.MaxVarintLen64:] + b.Truncate(offset) + b.PutString(str) +} + +// SplitString extracts a string and returns rest bytes. +// It'll panic if errored. +func SplitString(buf []byte) (str []byte, rest []byte) { + size, n := binary.Uvarint(buf) + buf = buf[n:] + return buf[:size], buf[size:] +} + +// SplitUint extracts uint64 and returns rest bytes. +// It'll panic if errored. +func SplitUint(buf []byte) (uint64, []byte) { + v, n := binary.Uvarint(buf) + return v, buf[n:] +}