numassigner: SectorNumReserveCount
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
package strle
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-bitfield"
|
||||
rlepluslazy "github.com/filecoin-project/go-bitfield/rle"
|
||||
)
|
||||
|
||||
func HumanRangesToBitField(h string) (bitfield.BitField, error) {
|
||||
var runs []rlepluslazy.Run
|
||||
var last uint64
|
||||
|
||||
strRanges := strings.Split(h, ",")
|
||||
for i, strRange := range strRanges {
|
||||
lr := strings.Split(strRange, "-")
|
||||
|
||||
var start, end uint64
|
||||
var err error
|
||||
|
||||
switch len(lr) {
|
||||
case 1: // one number
|
||||
start, err = strconv.ParseUint(lr[0], 10, 64)
|
||||
if err != nil {
|
||||
return bitfield.BitField{}, xerrors.Errorf("parsing left side of run %d: %w", i, err)
|
||||
}
|
||||
|
||||
end = start
|
||||
case 2: // x-y
|
||||
start, err = strconv.ParseUint(lr[0], 10, 64)
|
||||
if err != nil {
|
||||
return bitfield.BitField{}, xerrors.Errorf("parsing left side of run %d: %w", i, err)
|
||||
}
|
||||
end, err = strconv.ParseUint(lr[1], 10, 64)
|
||||
if err != nil {
|
||||
return bitfield.BitField{}, xerrors.Errorf("parsing right side of run %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
if start < last {
|
||||
return bitfield.BitField{}, xerrors.Errorf("run %d start(%d) was less than last run end(%d)", i, start, last)
|
||||
}
|
||||
|
||||
if start == last && last > 0 {
|
||||
return bitfield.BitField{}, xerrors.Errorf("run %d start(%d) was equal to last run end(%d)", i, start, last)
|
||||
}
|
||||
|
||||
if start > end {
|
||||
return bitfield.BitField{}, xerrors.Errorf("run start(%d) can't be greater than run end(%d) (run %d)", start, end, i)
|
||||
}
|
||||
|
||||
if start > last {
|
||||
runs = append(runs, rlepluslazy.Run{Val: false, Len: start - last})
|
||||
}
|
||||
|
||||
runs = append(runs, rlepluslazy.Run{Val: true, Len: end - start + 1})
|
||||
last = end + 1
|
||||
}
|
||||
|
||||
return bitfield.NewFromIter(&rlepluslazy.RunSliceIterator{Runs: runs})
|
||||
}
|
||||
|
||||
func BitfieldToHumanRanges(bf bitfield.BitField) (string, error) {
|
||||
bj, err := bf.MarshalJSON()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var bints []int64
|
||||
if err := json.Unmarshal(bj, &bints); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var at int64
|
||||
var out string
|
||||
|
||||
for i, bi := range bints {
|
||||
at += bi
|
||||
|
||||
if i%2 == 0 {
|
||||
if i > 0 {
|
||||
out += ","
|
||||
}
|
||||
out += fmt.Sprint(at)
|
||||
continue
|
||||
}
|
||||
|
||||
if bi > 1 {
|
||||
out += "-"
|
||||
out += fmt.Sprint(at - 1)
|
||||
}
|
||||
}
|
||||
|
||||
return out, err
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package strle
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-bitfield"
|
||||
)
|
||||
|
||||
func TestHumanBitfield(t *testing.T) {
|
||||
check := func(ints []uint64, out string) {
|
||||
bf := bitfield.NewFromSet(ints)
|
||||
h, err := BitfieldToHumanRanges(bf)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, out, h)
|
||||
}
|
||||
|
||||
check([]uint64{2, 3, 4}, "2-4")
|
||||
check([]uint64{2, 3, 4, 8, 9, 10, 11}, "2-4,8-11")
|
||||
check([]uint64{2}, "2")
|
||||
check([]uint64{0}, "0")
|
||||
check([]uint64{0, 1, 2}, "0-2")
|
||||
check([]uint64{0, 1, 5, 9, 11, 13, 14, 19}, "0-1,5,9,11,13-14,19")
|
||||
}
|
||||
|
||||
func TestHumanBitfieldRoundtrip(t *testing.T) {
|
||||
check := func(ints []uint64, out string) {
|
||||
parsed, err := HumanRangesToBitField(out)
|
||||
require.NoError(t, err)
|
||||
|
||||
h, err := BitfieldToHumanRanges(parsed)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, out, h)
|
||||
|
||||
bf := bitfield.NewFromSet(ints)
|
||||
ins, err := bitfield.IntersectBitField(bf, parsed)
|
||||
require.NoError(t, err)
|
||||
|
||||
// if intersected bitfield has the same length as both bitfields they are the same
|
||||
ic, err := ins.Count()
|
||||
require.NoError(t, err)
|
||||
|
||||
pc, err := parsed.Count()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, uint64(len(ints)), ic)
|
||||
require.Equal(t, ic, pc)
|
||||
}
|
||||
|
||||
check([]uint64{2, 3, 4}, "2-4")
|
||||
check([]uint64{2, 3, 4, 8, 9, 10, 11}, "2-4,8-11")
|
||||
check([]uint64{2}, "2")
|
||||
check([]uint64{0}, "0")
|
||||
check([]uint64{0, 1, 2}, "0-2")
|
||||
check([]uint64{0, 1, 5, 9, 11, 13, 14, 19}, "0-1,5,9,11,13-14,19")
|
||||
}
|
||||
Reference in New Issue
Block a user