mirror of
https://github.com/dolthub/dolt.git
synced 2026-01-30 10:45:18 -06:00
Add flatList and some tests. Not everything tested yet.
This commit is contained in:
72
types/flat_list.go
Normal file
72
types/flat_list.go
Normal 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
74
types/flat_list_test.go
Normal 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
18
types/list.go
Normal 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}
|
||||
}
|
||||
Reference in New Issue
Block a user