mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-06 02:52:19 +00:00
32375df7af
* made changeSet an helper type * added comment * removed dbutils.Add * remove common.CopyBytes from walk * fixes
143 lines
3.5 KiB
Go
143 lines
3.5 KiB
Go
package ethdb
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
)
|
|
|
|
// Maximum length (in bytes of encoded timestamp)
|
|
const MaxTimestampLength = 8
|
|
|
|
func encodingLen8to7(b []byte) int { //nolint
|
|
return (len(b)*8 + 6) / 7
|
|
}
|
|
|
|
// Transforms b into encoding where only
|
|
// 7 bits of each byte are used to encode the bits of b
|
|
// The most significant bit is left empty, for other purposes
|
|
func encode8to7(b []byte) []byte {
|
|
// Calculate number of bytes in the output
|
|
inbytes := len(b)
|
|
outbytes := (inbytes*8 + 6) / 7
|
|
out := make([]byte, outbytes)
|
|
for i := 0; i < outbytes; i++ {
|
|
out[i] = 0x80
|
|
}
|
|
outidx := 0
|
|
for inidx := 0; inidx < inbytes; inidx++ {
|
|
bb := b[inidx]
|
|
switch inidx % 7 {
|
|
case 0:
|
|
out[outidx] |= bb >> 1
|
|
out[outidx+1] |= (bb & 0x1) << 6
|
|
case 1:
|
|
out[outidx+1] |= (bb >> 2) & 0x3f
|
|
out[outidx+2] |= (bb & 0x3) << 5
|
|
case 2:
|
|
out[outidx+2] |= (bb >> 3) & 0x1f
|
|
out[outidx+3] |= (bb & 0x7) << 4
|
|
case 3:
|
|
out[outidx+3] |= (bb >> 4) & 0xf
|
|
out[outidx+4] |= (bb & 0xf) << 3
|
|
case 4:
|
|
out[outidx+4] |= (bb >> 5) & 0x7
|
|
out[outidx+5] |= (bb & 0x1f) << 2
|
|
case 5:
|
|
out[outidx+5] |= (bb >> 6) & 0x3
|
|
out[outidx+6] |= (bb & 0x3f) << 1
|
|
case 6:
|
|
out[outidx+6] |= bb >> 7
|
|
out[outidx+7] |= bb & 0x7f
|
|
outidx += 8
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func decode7to8(b []byte) []byte {
|
|
inbytes := len(b)
|
|
outbytes := inbytes * 7 / 8
|
|
out := make([]byte, outbytes)
|
|
inidx := 0
|
|
for outidx := 0; outidx < outbytes; outidx++ {
|
|
switch outidx % 7 {
|
|
case 0:
|
|
out[outidx] = ((b[inidx] & 0x7f) << 1) | ((b[inidx+1] >> 6) & 0x1)
|
|
case 1:
|
|
out[outidx] = ((b[inidx+1] & 0x3f) << 2) | ((b[inidx+2] >> 5) & 0x3)
|
|
case 2:
|
|
out[outidx] = ((b[inidx+2] & 0x1f) << 3) | ((b[inidx+3] >> 4) & 0x7)
|
|
case 3:
|
|
out[outidx] = ((b[inidx+3] & 0xf) << 4) | ((b[inidx+4] >> 3) & 0xf)
|
|
case 4:
|
|
out[outidx] = ((b[inidx+4] & 0x7) << 5) | ((b[inidx+5] >> 2) & 0x1f)
|
|
case 5:
|
|
out[outidx] = ((b[inidx+5] & 0x3) << 6) | ((b[inidx+6] >> 1) & 0x3f)
|
|
case 6:
|
|
out[outidx] = ((b[inidx+6] & 0x1) << 7) | (b[inidx+7] & 0x7f)
|
|
inidx += 8
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// addToChangeSet is not part the ChangeSet API, and it is only used in the test settings.
|
|
// In the production settings, ChangeSets encodings are never modified.
|
|
// In production settings (mutation.PutS) we always first populate ChangeSet object,
|
|
// then encode it once, and then only work with the encoding
|
|
func addToChangeSet(b []byte, key []byte, value []byte) ([]byte, error) {
|
|
var m int
|
|
var n int
|
|
|
|
if len(b) == 0 {
|
|
m = len(key)
|
|
n = 0
|
|
} else {
|
|
n = int(binary.BigEndian.Uint32(b[0:4]))
|
|
m = int(binary.BigEndian.Uint32(b[4:8]))
|
|
if len(key) != m {
|
|
return nil, fmt.Errorf("wrong key size in ChangeSet: expected %d, actual %d", m, len(key))
|
|
}
|
|
}
|
|
pos := 4
|
|
var buffer bytes.Buffer
|
|
// Encode n
|
|
intArr := make([]byte, 4)
|
|
binary.BigEndian.PutUint32(intArr, uint32(n+1))
|
|
buffer.Write(intArr)
|
|
// KeySize should be the same
|
|
if n == 0 {
|
|
binary.BigEndian.PutUint32(intArr, uint32(len(key)))
|
|
buffer.Write(intArr)
|
|
} else {
|
|
buffer.Write(b[pos : pos+4])
|
|
}
|
|
|
|
pos += 4
|
|
// append key
|
|
if n == 0 {
|
|
buffer.Write(key)
|
|
pos += len(key)
|
|
} else {
|
|
buffer.Write(b[pos : pos+n*m])
|
|
buffer.Write(key)
|
|
pos += n * m
|
|
}
|
|
// Append Index
|
|
if n == 0 {
|
|
binary.BigEndian.PutUint32(intArr, uint32(len(value)))
|
|
buffer.Write(intArr)
|
|
} else {
|
|
buffer.Write(b[pos : pos+4*n])
|
|
pos += 4 * n
|
|
prev := int(binary.BigEndian.Uint32(b[pos-4 : pos]))
|
|
binary.BigEndian.PutUint32(intArr, uint32(prev+len(value)))
|
|
buffer.Write(intArr)
|
|
buffer.Write(b[pos:])
|
|
}
|
|
// Append Value
|
|
buffer.Write(value)
|
|
return buffer.Bytes(), nil
|
|
}
|