Add flatList and some tests. Not everything tested yet.

This commit is contained in:
Aaron Boodman
2015-06-03 18:44:39 -07:00
parent addf1b34d8
commit 3a0dc592fc
3 changed files with 164 additions and 0 deletions

72
types/flat_list.go Normal file
View File

@@ -0,0 +1,72 @@
package types
// flatList is a quick 'n easy implementation of List.
// It should eventually be replaced by a chunking implementation.
type flatList struct {
list []Value
}
func (l flatList) Len() uint64 {
return uint64(len(l.list))
}
func (l flatList) Get(idx uint64) Value {
return l.list[idx]
}
func (l flatList) Slice(start uint64, end uint64) List {
return flatList{l.list[start:end]}
}
func (l flatList) Set(idx uint64, v Value) List {
b := make([]Value, len(l.list))
copy(b, l.list)
b[idx] = v
return flatList{b}
}
func (l flatList) Append(v ...Value) List {
return flatList{append(l.list, v...)}
}
func (l flatList) Insert(idx uint64, v ...Value) List {
b := make([]Value, len(l.list)+len(v))
copy(b, l.list[:idx])
copy(b[idx:], v)
copy(b[idx+uint64(len(v)):], l.list[idx:])
return flatList{b}
}
func (l flatList) Remove(start uint64, end uint64) List {
b := make([]Value, uint64(len(l.list))-(end-start))
copy(b, l.list[:start])
copy(b[start:], l.list[end:])
return flatList{b}
}
func (l flatList) RemoveAt(idx uint64) List {
return l.Remove(idx, idx+1)
}
func (l flatList) Equals(other Value) bool {
// TODO: Seems like this might be better to implement via content addressing.
//
// 1. Give List a Codec-like interface (not Codec itself because of circular deps)
// 2. Give List (or maybe all values?) a Ref() method
// 3. Ref works by using Codec to serialize the value, then caching the ref
// 4. Equals works by comparing the value of Ref()
//
// The Codec-alike interface in (1) doesn't have to be a general purpose cache, I don't think. The client of this type probably knows whether he's about to send stuff someplace else (in which case he doesn't need a cache because he can just send the chunks immediately, or at worse put them in a temp dir), or whether he's not going to send them anywhere (in which case he doesn't need a cache because he doesn't need the data permanently).
if other, ok := other.(List); ok {
if l.Len() != other.Len() {
return false
}
for i := uint64(0); i < l.Len(); i++ {
if !l.Get(i).Equals(other.Get(i)) {
return false
}
}
return true
}
return false
}

74
types/flat_list_test.go Normal file
View File

@@ -0,0 +1,74 @@
package types
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestFlatListLen(t *testing.T) {
assert := assert.New(t)
l := List(flatList{})
assert.Equal(uint64(0), l.Len())
l = l.Append(Bool(true))
assert.Equal(uint64(1), l.Len())
l = l.Append(Bool(false), Bool(false))
assert.Equal(uint64(3), l.Len())
}
func TestFlatListGet(t *testing.T) {
assert := assert.New(t)
l := List(flatList{})
l = l.Append(Int32(0), Int32(1), Int32(2))
assert.Equal(Int32(0), l.Get(0))
assert.Equal(Int32(1), l.Get(1))
assert.Equal(Int32(2), l.Get(2))
assert.Panics(func() {
l.Get(3)
})
}
func TestFlatListSlice(t *testing.T) {
assert := assert.New(t)
l1 := List(flatList{})
l1 = l1.Append(Int32(0), Int32(1), Int32(2), Int32(3))
l2 := l1.Slice(1, 3)
assert.Equal(uint64(4), l1.Len())
assert.Equal(uint64(2), l2.Len())
assert.Equal(Int32(1), l2.Get(0))
assert.Equal(Int32(2), l2.Get(1))
l3 := l1.Slice(0, 0)
assert.Equal(uint64(0), l3.Len())
l3 = l1.Slice(1, 1)
assert.Equal(uint64(0), l3.Len())
l3 = l1.Slice(1, 2)
assert.Equal(uint64(1), l3.Len())
assert.Equal(Int32(1), l3.Get(0))
l3 = l1.Slice(0, l1.Len())
assert.True(l1.Equals(l3))
assert.Panics(func() {
l3 = l1.Slice(0, l1.Len()+1)
})
}
func TestFlatListAppend(t *testing.T) {
assert := assert.New(t)
l0 := flatList{}
l1 := l0.Append(Bool(false))
assert.Equal(uint64(0), l0.Len())
assert.Equal(uint64(1), l1.Len())
assert.Equal(Bool(false), l1.Get(0))
// Append(v1, v2)
l2 := l1.Append(Bool(true), Bool(true))
assert.Equal(uint64(3), l2.Len())
assert.Equal(Bool(false), l2.Get(0))
assert.True(NewList(Bool(true), Bool(true)).Equals(l2.Slice(1, l2.Len())))
assert.Equal(uint64(1), l1.Len())
}

18
types/list.go Normal file
View File

@@ -0,0 +1,18 @@
package types
type List interface {
Value
Len() uint64
Get(idx uint64) Value
// TODO: iterator
Slice(idx uint64, end uint64) List
Set(idx uint64, v Value) List
Append(v ...Value) List
Insert(idx uint64, v ...Value) List
Remove(start uint64, end uint64) List
RemoveAt(idx uint64) List
}
func NewList(v ...Value) List {
return flatList{v}
}