Add chunk implementation from old code base
This commit is contained in:
parent
a5a78c786a
commit
4f811a8ffe
|
@ -0,0 +1,66 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// chunk holds the offsets for a partial piece of data
|
||||||
|
type chunk struct {
|
||||||
|
Start int64 `json:"start"`
|
||||||
|
End int64 `json:"end"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the number of bytes between Start and End.
|
||||||
|
func (c chunk) Size() int64 {
|
||||||
|
return c.End - c.Start + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// chunkSet holds a set of chunks and helps with adding/merging new chunks into
|
||||||
|
// set set.
|
||||||
|
type chunkSet []chunk
|
||||||
|
|
||||||
|
// Add merges a newChunk into a chunkSet. This may lead to the chunk being
|
||||||
|
// combined with one or more adjecent chunks, possibly shrinking the chunkSet
|
||||||
|
// down to a single member.
|
||||||
|
func (c *chunkSet) Add(newChunk chunk) {
|
||||||
|
if newChunk.Size() <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
*c = append(*c, newChunk)
|
||||||
|
sort.Sort(c)
|
||||||
|
|
||||||
|
// merge chunks that can be combined
|
||||||
|
for i := 0; i < len(*c)-1; i++ {
|
||||||
|
current := (*c)[i]
|
||||||
|
next := (*c)[i+1]
|
||||||
|
|
||||||
|
if current.End+1 < next.Start {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
*c = append((*c)[0:i], (*c)[i+1:]...)
|
||||||
|
|
||||||
|
if current.End > next.End {
|
||||||
|
(*c)[i].End = current.End
|
||||||
|
}
|
||||||
|
|
||||||
|
if current.Start < next.Start {
|
||||||
|
(*c)[i].Start = current.Start
|
||||||
|
}
|
||||||
|
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c chunkSet) Len() int {
|
||||||
|
return len(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c chunkSet) Less(i, j int) bool {
|
||||||
|
return c[i].Start < c[j].Start
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c chunkSet) Swap(i, j int) {
|
||||||
|
c[i], c[j] = c[j], c[i]
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var chunkSet_AddTests = []struct {
|
||||||
|
Name string
|
||||||
|
Add []chunk
|
||||||
|
Expect []chunk
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "add one",
|
||||||
|
Add: []chunk{{Start: 1, End: 5}},
|
||||||
|
Expect: []chunk{{Start: 1, End: 5}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "add twice",
|
||||||
|
Add: []chunk{{Start: 1, End: 5}, {Start: 1, End: 5}},
|
||||||
|
Expect: []chunk{{Start: 1, End: 5}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "append",
|
||||||
|
Add: []chunk{{Start: 1, End: 5}, {Start: 7, End: 10}},
|
||||||
|
Expect: []chunk{{Start: 1, End: 5}, {Start: 7, End: 10}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "insert",
|
||||||
|
Add: []chunk{{Start: 0, End: 5}, {Start: 12, End: 15}, {Start: 7, End: 10}},
|
||||||
|
Expect: []chunk{{Start: 0, End: 5}, {Start: 7, End: 10}, {Start: 12, End: 15}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "prepend",
|
||||||
|
Add: []chunk{{Start: 5, End: 10}, {Start: 1, End: 3}},
|
||||||
|
Expect: []chunk{{Start: 1, End: 3}, {Start: 5, End: 10}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "grow start",
|
||||||
|
Add: []chunk{{Start: 1, End: 5}, {Start: 0, End: 5}},
|
||||||
|
Expect: []chunk{{Start: 0, End: 5}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "grow end",
|
||||||
|
Add: []chunk{{Start: 1, End: 5}, {Start: 1, End: 6}},
|
||||||
|
Expect: []chunk{{Start: 1, End: 6}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "grow end with multiple items",
|
||||||
|
Add: []chunk{{Start: 1, End: 5}, {Start: 7, End: 10}, {Start: 8, End: 15}},
|
||||||
|
Expect: []chunk{{Start: 1, End: 5}, {Start: 7, End: 15}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "grow exact end match",
|
||||||
|
Add: []chunk{{Start: 1, End: 5}, {Start: 6, End: 6}},
|
||||||
|
Expect: []chunk{{Start: 1, End: 6}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "sink",
|
||||||
|
Add: []chunk{{Start: 1, End: 5}, {Start: 2, End: 3}},
|
||||||
|
Expect: []chunk{{Start: 1, End: 5}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "swallow",
|
||||||
|
Add: []chunk{{Start: 1, End: 5}, {Start: 6, End: 10}, {Start: 0, End: 11}},
|
||||||
|
Expect: []chunk{{Start: 0, End: 11}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "ignore 0 byte chunks",
|
||||||
|
Add: []chunk{{Start: 0, End: -1}},
|
||||||
|
Expect: []chunk{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "ignore invalid chunks",
|
||||||
|
Add: []chunk{{Start: 0, End: -2}},
|
||||||
|
Expect: []chunk{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_chunkSet_Add(t *testing.T) {
|
||||||
|
for _, test := range chunkSet_AddTests {
|
||||||
|
var chunks chunkSet
|
||||||
|
for _, chunk := range test.Add {
|
||||||
|
chunks.Add(chunk)
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := fmt.Sprintf("%+v", test.Expect)
|
||||||
|
got := fmt.Sprintf("%+v", chunks)
|
||||||
|
|
||||||
|
if got != expected {
|
||||||
|
t.Errorf(
|
||||||
|
"Failed test '%s':\nexpected: %s\ngot: %s",
|
||||||
|
test.Name,
|
||||||
|
expected,
|
||||||
|
got,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue