diff --git a/new_ring_for_slice_example_test.go b/new_ring_for_slice_example_test.go new file mode 100644 index 0000000..c82778e --- /dev/null +++ b/new_ring_for_slice_example_test.go @@ -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 +} diff --git a/ring.go b/ring.go index 5ff20ef..509e8c1 100644 --- a/ring.go +++ b/ring.go @@ -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())) +} diff --git a/ring_test.go b/ring_test.go index fc90a74..87b18f3 100644 --- a/ring_test.go +++ b/ring_test.go @@ -1,6 +1,7 @@ package o import ( + "sort" "testing" "github.com/stretchr/testify/assert" @@ -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) + }) + } +}