mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-03 01:27:38 +00:00
87 lines
1.8 KiB
Go
87 lines
1.8 KiB
Go
package base_encoding
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
"io"
|
|
|
|
"github.com/klauspost/compress/zstd"
|
|
)
|
|
|
|
func WriteRabbits(in []uint64, w io.Writer) error {
|
|
// Retrieve compressor first
|
|
compressor := compressorPool.Get().(*zstd.Encoder)
|
|
defer compressorPool.Put(compressor)
|
|
compressor.Reset(w)
|
|
|
|
expectedNum := uint64(0)
|
|
count := 0
|
|
// write length
|
|
if err := binary.Write(compressor, binary.LittleEndian, uint64(len(in))); err != nil {
|
|
return err
|
|
}
|
|
for _, element := range in {
|
|
if expectedNum != element {
|
|
// [1,2,5,6]
|
|
// write contiguous sequence
|
|
if err := binary.Write(compressor, binary.LittleEndian, uint64(count)); err != nil {
|
|
return err
|
|
}
|
|
// write non-contiguous element
|
|
if err := binary.Write(compressor, binary.LittleEndian, element-expectedNum); err != nil {
|
|
return err
|
|
}
|
|
count = 0
|
|
}
|
|
count++
|
|
expectedNum = element + 1
|
|
|
|
}
|
|
// write last contiguous sequence
|
|
if err := binary.Write(compressor, binary.LittleEndian, uint64(count)); err != nil {
|
|
return err
|
|
}
|
|
return compressor.Close()
|
|
}
|
|
|
|
func ReadRabbits(out []uint64, r io.Reader) ([]uint64, error) {
|
|
// Retrieve compressor first
|
|
decompressor, err := zstd.NewReader(r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer decompressor.Close()
|
|
|
|
var length uint64
|
|
if err := binary.Read(decompressor, binary.LittleEndian, &length); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if cap(out) < int(length) {
|
|
out = make([]uint64, 0, length)
|
|
}
|
|
out = out[:0]
|
|
var count uint64
|
|
var current uint64
|
|
active := true
|
|
for err != io.EOF {
|
|
err = binary.Read(decompressor, binary.LittleEndian, &count)
|
|
if errors.Is(err, io.EOF) {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if active {
|
|
for i := current; i < current+count; i++ {
|
|
out = append(out, i)
|
|
}
|
|
current += count
|
|
} else {
|
|
current += count
|
|
}
|
|
active = !active
|
|
}
|
|
return out, nil
|
|
}
|