-
Notifications
You must be signed in to change notification settings - Fork 609
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #32301 from vespa-engine/havardpe/slime-in-go
slime in go
- Loading branch information
Showing
8 changed files
with
321 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. | ||
|
||
package slime | ||
|
||
type arrayValue struct { | ||
emptyValue | ||
value []Value | ||
} | ||
|
||
func Array() *arrayValue { return &arrayValue{} } | ||
func (*arrayValue) Type() Type { return ARRAY } | ||
|
||
func (arr *arrayValue) NumEntries() int { return len(arr.value) } | ||
func (arr *arrayValue) Entry(index int) Value { | ||
if index < len(arr.value) { | ||
return arr.value[index] | ||
} | ||
return Invalid | ||
} | ||
func (arr *arrayValue) EachEntry(f func(index int, value Value)) { | ||
for i, x := range arr.value { | ||
f(i, x) | ||
} | ||
} | ||
|
||
func (arr *arrayValue) Add(value Value) Value { | ||
arr.value = append(arr.value, value) | ||
return value | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. | ||
|
||
package slime | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func TestArray(t *testing.T) { | ||
arr := Array() | ||
actual := []Value{ | ||
arr.Add(Empty), | ||
arr.Add(Bool(true)), | ||
arr.Add(Long(5)), | ||
arr.Add(Double(5.5)), | ||
arr.Add(String("foo")), | ||
arr.Add(Data([]byte{1, 2, 3}))} | ||
|
||
expect := []expectLeaf{ | ||
expectLeaf{mytype: EMPTY}, | ||
expectLeaf{mytype: BOOL, boolVal: true}, | ||
expectLeaf{mytype: LONG, longVal: 5, doubleVal: 5}, | ||
expectLeaf{mytype: DOUBLE, longVal: 5, doubleVal: 5.5}, | ||
expectLeaf{mytype: STRING, stringVal: "foo"}, | ||
expectLeaf{mytype: DATA, dataVal: []byte{1, 2, 3}}} | ||
|
||
var expectIndex int | ||
var collect []Value | ||
arr.EachEntry(func(idx int, val Value) { | ||
assert.Equal(t, idx, expectIndex) | ||
collect = append(collect, val) | ||
expectIndex++ | ||
}) | ||
|
||
assert.Equal(t, arr.NumEntries(), len(expect)) | ||
for i, e := range expect { | ||
checkLeaf(t, actual[i], e) | ||
checkLeaf(t, collect[i], e) | ||
checkLeaf(t, arr.Entry(i), e) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. | ||
|
||
package slime | ||
|
||
type boolValue struct { | ||
emptyValue | ||
value bool | ||
} | ||
|
||
func Bool(v bool) Value { return &boolValue{value: v} } | ||
func (*boolValue) Type() Type { return BOOL } | ||
func (v *boolValue) AsBool() bool { return v.value } | ||
|
||
type longValue struct { | ||
emptyValue | ||
value int64 | ||
} | ||
|
||
func Long(v int64) Value { return &longValue{value: v} } | ||
func (*longValue) Type() Type { return LONG } | ||
func (v *longValue) AsLong() int64 { return v.value } | ||
func (v *longValue) AsDouble() float64 { return float64(v.value) } | ||
|
||
type doubleValue struct { | ||
emptyValue | ||
value float64 | ||
} | ||
|
||
func Double(v float64) Value { return &doubleValue{value: v} } | ||
func (*doubleValue) Type() Type { return DOUBLE } | ||
func (v *doubleValue) AsLong() int64 { return int64(v.value) } | ||
func (v *doubleValue) AsDouble() float64 { return v.value } | ||
|
||
type stringValue struct { | ||
emptyValue | ||
value string | ||
} | ||
|
||
func String(v string) Value { return &stringValue{value: v} } | ||
func (*stringValue) Type() Type { return STRING } | ||
func (v *stringValue) AsString() string { return v.value } | ||
|
||
type dataValue struct { | ||
emptyValue | ||
value []byte | ||
} | ||
|
||
func Data(v []byte) Value { return &dataValue{value: v} } | ||
func (*dataValue) Type() Type { return DATA } | ||
func (v *dataValue) AsData() []byte { return v.value } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. | ||
|
||
package slime | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
type expectLeaf struct { | ||
invalid bool | ||
mytype Type | ||
boolVal bool | ||
longVal int64 | ||
doubleVal float64 | ||
stringVal string | ||
dataVal []byte | ||
} | ||
|
||
func checkLeaf(t *testing.T, value Value, expect expectLeaf) { | ||
if expect.dataVal == nil { | ||
expect.dataVal = emptyBytes | ||
} | ||
assert.Equal(t, value.Valid(), !expect.invalid) | ||
assert.Equal(t, value.Type(), expect.mytype) | ||
assert.Equal(t, value.AsBool(), expect.boolVal) | ||
assert.Equal(t, value.AsLong(), expect.longVal) | ||
assert.Equal(t, value.AsDouble(), expect.doubleVal) | ||
assert.Equal(t, value.AsString(), expect.stringVal) | ||
assert.Equal(t, value.AsData(), expect.dataVal) | ||
} | ||
|
||
func TestEmpty(t *testing.T) { | ||
checkLeaf(t, Empty, expectLeaf{}) | ||
checkLeaf(t, Invalid, expectLeaf{invalid: true}) | ||
} | ||
|
||
func TestBool(t *testing.T) { | ||
checkLeaf(t, Bool(false), expectLeaf{mytype: BOOL}) | ||
checkLeaf(t, Bool(true), expectLeaf{mytype: BOOL, boolVal: true}) | ||
} | ||
|
||
func TestLong(t *testing.T) { | ||
checkLeaf(t, Long(0), expectLeaf{mytype: LONG}) | ||
checkLeaf(t, Long(5), expectLeaf{mytype: LONG, longVal: 5, doubleVal: 5}) | ||
checkLeaf(t, Long(7), expectLeaf{mytype: LONG, longVal: 7, doubleVal: 7}) | ||
} | ||
|
||
func TestDouble(t *testing.T) { | ||
checkLeaf(t, Double(0.0), expectLeaf{mytype: DOUBLE}) | ||
checkLeaf(t, Double(5.0), expectLeaf{mytype: DOUBLE, longVal: 5, doubleVal: 5.0}) | ||
checkLeaf(t, Double(7.5), expectLeaf{mytype: DOUBLE, longVal: 7, doubleVal: 7.5}) | ||
} | ||
|
||
func TestString(t *testing.T) { | ||
checkLeaf(t, String(""), expectLeaf{mytype: STRING}) | ||
checkLeaf(t, String("foo"), expectLeaf{mytype: STRING, stringVal: "foo"}) | ||
checkLeaf(t, String("bar"), expectLeaf{mytype: STRING, stringVal: "bar"}) | ||
} | ||
|
||
func TestData(t *testing.T) { | ||
checkLeaf(t, Data(emptyBytes), expectLeaf{mytype: DATA}) | ||
checkLeaf(t, Data([]byte{1, 2, 3}), expectLeaf{mytype: DATA, dataVal: []byte{1, 2, 3}}) | ||
checkLeaf(t, Data([]byte{5, 6}), expectLeaf{mytype: DATA, dataVal: []byte{5, 6}}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. | ||
|
||
package slime | ||
|
||
type objectValue struct { | ||
emptyValue | ||
value map[string]Value | ||
} | ||
|
||
func Object() Value { return &objectValue{value: make(map[string]Value)} } | ||
func (*objectValue) Type() Type { return OBJECT } | ||
|
||
func (obj *objectValue) NumFields() int { return len(obj.value) } | ||
func (obj *objectValue) Field(name string) Value { | ||
value, found := obj.value[name] | ||
if found { | ||
return value | ||
} | ||
return Invalid | ||
} | ||
func (obj *objectValue) EachField(f func(name string, value Value)) { | ||
for n, x := range obj.value { | ||
f(n, x) | ||
} | ||
} | ||
|
||
func (obj *objectValue) Set(name string, value Value) Value { | ||
_, found := obj.value[name] | ||
if found { | ||
return Invalid | ||
} | ||
obj.value[name] = value | ||
return value | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. | ||
|
||
package slime | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func TestObject(t *testing.T) { | ||
obj := Object() | ||
actual := map[string]Value{ | ||
"a": obj.Set("a", Empty), | ||
"b": obj.Set("b", Bool(true)), | ||
"c": obj.Set("c", Long(5)), | ||
"d": obj.Set("d", Double(5.5)), | ||
"e": obj.Set("e", String("foo")), | ||
"f": obj.Set("f", Data([]byte{1, 2, 3}))} | ||
|
||
expect := map[string]expectLeaf{ | ||
"a": expectLeaf{mytype: EMPTY}, | ||
"b": expectLeaf{mytype: BOOL, boolVal: true}, | ||
"c": expectLeaf{mytype: LONG, longVal: 5, doubleVal: 5}, | ||
"d": expectLeaf{mytype: DOUBLE, longVal: 5, doubleVal: 5.5}, | ||
"e": expectLeaf{mytype: STRING, stringVal: "foo"}, | ||
"f": expectLeaf{mytype: DATA, dataVal: []byte{1, 2, 3}}} | ||
|
||
collect := make(map[string]Value) | ||
obj.EachField(func(name string, val Value) { | ||
collect[name] = val | ||
}) | ||
|
||
assert.Equal(t, obj.NumFields(), len(expect)) | ||
assert.Equal(t, len(collect), len(expect)) | ||
for n, e := range expect { | ||
checkLeaf(t, actual[n], e) | ||
checkLeaf(t, collect[n], e) | ||
checkLeaf(t, obj.Field(n), e) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. | ||
|
||
package slime | ||
|
||
type Type byte | ||
|
||
const ( | ||
EMPTY Type = iota | ||
BOOL | ||
LONG | ||
DOUBLE | ||
STRING | ||
DATA | ||
ARRAY | ||
OBJECT | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. | ||
|
||
package slime | ||
|
||
var ( | ||
emptyBytes []byte = make([]byte, 0) | ||
Empty Value = &emptyValue{} | ||
Invalid Value = (*emptyValue)(nil) | ||
) | ||
|
||
type Value interface { | ||
Valid() bool | ||
Type() Type | ||
AsBool() bool | ||
AsLong() int64 | ||
AsDouble() float64 | ||
AsString() string | ||
AsData() []byte | ||
NumEntries() int | ||
Entry(index int) Value | ||
EachEntry(func(index int, value Value)) | ||
NumFields() int | ||
Field(name string) Value | ||
EachField(func(name string, value Value)) | ||
Add(value Value) Value | ||
Set(name string, value Value) Value | ||
} | ||
|
||
type emptyValue struct{} | ||
|
||
func (v *emptyValue) Valid() bool { return (v != nil) } | ||
func (*emptyValue) Type() Type { return EMPTY } | ||
func (*emptyValue) AsBool() bool { return false } | ||
func (*emptyValue) AsLong() int64 { return 0 } | ||
func (*emptyValue) AsDouble() float64 { return 0 } | ||
func (*emptyValue) AsString() string { return "" } | ||
func (*emptyValue) AsData() []byte { return emptyBytes } | ||
func (*emptyValue) NumEntries() int { return 0 } | ||
func (*emptyValue) Entry(index int) Value { return Invalid } | ||
func (*emptyValue) EachEntry(func(index int, value Value)) {} | ||
func (*emptyValue) NumFields() int { return 0 } | ||
func (*emptyValue) Field(name string) Value { return Invalid } | ||
func (*emptyValue) EachField(func(name string, value Value)) {} | ||
func (*emptyValue) Add(value Value) Value { return Invalid } | ||
func (*emptyValue) Set(name string, value Value) Value { return Invalid } |