Skip to content

Commit

Permalink
Use sort.Interface.Len for more convient ring creation
Browse files Browse the repository at this point in the history
If a slice type implements a Len() method, we can use this to create a
ring with the right parameters for it. Since sort.Interface already
exists and sometimes gets implemented, this might make it much more
convenient to create rings.
  • Loading branch information
antifuchs committed Mar 16, 2019
1 parent f1151a5 commit 3affad0
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 4 deletions.
22 changes: 22 additions & 0 deletions new_ring_for_slice_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package o_test

import (
"fmt"
"sort"

"github.com/antifuchs/o"
)

func ExampleNewRingForSlice() {
// create some backing store:
store := make([]int, 90)

// put a ring on it:
ring := o.NewRingForSlice(sort.IntSlice(store))

// it is empty:
fmt.Println(ring.Empty())

// Output:
// true
}
25 changes: 21 additions & 4 deletions ring.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,30 @@ func ForcePush(r Ring) uint {
return i
}

// Returns a new Ring data structure. If cap is a power of 2, returns
// a data structure that is optimized for modulo-2
// accesses. Otherwise, the returned data structure uses general
// modulo division for its integer math.
// Returns a new Ring data structure with the given capacity. If cap
// is a power of 2, returns a data structure that is optimized for
// modulo-2 accesses. Otherwise, the returned data structure uses
// general modulo division for its integer math.
func NewRing(cap uint) Ring {
if bits.OnesCount(cap) == 1 {
return &maskRing{cap: cap}
}
return &basicRing{cap: cap}
}

// A type, usually a collection, that has length. This is inspired by
// (but kept intentionally smaller than) sort.Interface.
type Slice interface {
// Len returns the length of a slice.
Len() int
}

// NewRingForSlice creates a Ring that fits a slice. The slice's type
// must implement o.Slice (which is satisfied if the type implements
// sort.Interface, also).
//
// It is not advisable to resize the slice after creating a ring for
// it.
func NewRingForSlice(i Slice) Ring {
return NewRing(uint(i.Len()))
}
21 changes: 21 additions & 0 deletions ring_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package o

import (
"sort"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -39,3 +40,23 @@ func TestPushAndShift(t *testing.T) {
})
}
}

func TestSlices(t *testing.T) {
tests := []struct {
name string
slice Slice
len uint
}{
{"[]int", sort.IntSlice([]int{1, 2, 3, 4}), 4},
{"[]float64", sort.Float64Slice([]float64{1.0, 2.0, 3.0}), 3},
{"[]string", sort.StringSlice([]string{"hi", "there", "farts", "yup", "strings"}), 5},
}
for _, elt := range tests {
test := elt
t.Run(test.name, func(t *testing.T) {
t.Parallel()
ring := NewRingForSlice(test.slice)
assert.Equal(t, ring.capacity(), test.len)
})
}
}

0 comments on commit 3affad0

Please sign in to comment.