diff --git a/go/store/val/triple.go b/go/store/val/triple.go new file mode 100644 index 0000000000..d371f8fa4f --- /dev/null +++ b/go/store/val/triple.go @@ -0,0 +1,59 @@ +// Copyright 2022 Dolthub, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package val + +import "github.com/dolthub/dolt/go/store/pool" + +const ( + tripleOffSz = int(uint16Size + uint16Size) +) + +func NewTriple[V ~[]byte](pool pool.BuffPool, one, two, three V) (tri Triple[V]) { + o1 := len(one) + o2 := len(two) + o1 + end := len(three) + o2 + tri = pool.Get(uint64(end + tripleOffSz)) + + // populate fields + copy(tri, one) + copy(tri[o1:], two) + copy(tri[o2:], three) + + // populate offsets + writeUint16(tri[end:end+2], uint16(o1)) + writeUint16(tri[end+2:], uint16(o2)) + return +} + +type Triple[V ~[]byte] []byte + +func (t Triple[V]) First() V { + l := len(t) + o1 := readUint16(t[l-4 : l-2]) + return V(t[:o1]) +} + +func (t Triple[V]) Second() V { + l := len(t) + o1 := readUint16(t[l-4 : l-2]) + o2 := readUint16(t[l-2 : l]) + return V(t[o1:o2]) +} + +func (t Triple[V]) Third() V { + l := len(t) + o2 := readUint16(t[l-2 : l]) + return V(t[o2 : l-4]) +} diff --git a/go/store/val/triple_test.go b/go/store/val/triple_test.go new file mode 100644 index 0000000000..4c79894cbd --- /dev/null +++ b/go/store/val/triple_test.go @@ -0,0 +1,55 @@ +// Copyright 2021 Dolthub, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package val + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestNewTriple(t *testing.T) { + t.Run("test tuple round trip", func(t *testing.T) { + roundTripTripleFields(t) + }) +} + +func roundTripTripleFields(t *testing.T) { + for n := 0; n < 100; n++ { + f1 := randomByteFields(t) + f2 := randomByteFields(t) + f3 := randomByteFields(t) + + t1 := NewTuple(testPool, f1...) + t2 := NewTuple(testPool, f2...) + t3 := NewTuple(testPool, f3...) + + tri := NewTriple(testPool, t1, t2, t3) + + a, b, c := tri.First(), tri.Second(), tri.Third() + assert.Equal(t, t1, a) + assert.Equal(t, t2, b) + assert.Equal(t, t3, c) + + for i, field := range f1 { + assert.Equal(t, field, a.GetField(i)) + } + for i, field := range f2 { + assert.Equal(t, field, b.GetField(i)) + } + for i, field := range f3 { + assert.Equal(t, field, c.GetField(i)) + } + } +} diff --git a/go/store/val/tuple_test.go b/go/store/val/tuple_test.go index 25fd9c5762..6c44488dc5 100644 --- a/go/store/val/tuple_test.go +++ b/go/store/val/tuple_test.go @@ -31,14 +31,14 @@ var testRand = rand.New(rand.NewSource(1)) func TestNewTuple(t *testing.T) { t.Run("test tuple round trip", func(t *testing.T) { - roundTripBytes(t) + roundTripTupleFields(t) }) t.Run("test tuple get many", func(t *testing.T) { testTupleGetMany(t) }) } -func roundTripBytes(t *testing.T) { +func roundTripTupleFields(t *testing.T) { for n := 0; n < 100; n++ { fields := randomByteFields(t) tup := NewTuple(testPool, fields...)