Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add minimal port of Slime API #27215

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions client/go/internal/slime/array_traverser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
// Author: arnej

package slime

type ArrayTraverser interface {
Entry(idx int, value Inspector)
}
96 changes: 96 additions & 0 deletions client/go/internal/slime/array_value.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
// Author: arnej

package slime

type ArrayValue struct {
valueBase
v []Cursor
}

func newArrayValue() *ArrayValue {
return &ArrayValue{
v: make([]Cursor, 0, 10),
}
}

func (a *ArrayValue) addElement(elem Cursor) Cursor {
a.v = append(a.v, elem)
return elem
}

func (a *ArrayValue) Valid() bool {
return true
}

func (a *ArrayValue) Type() Type {
return ARRAY
}

func (a *ArrayValue) Entries() int {
return len(a.v)
}

func (a *ArrayValue) TraverseArray(traverser ArrayTraverser) {
for idx, value := range a.v {
traverser.Entry(idx, value)
}
}

func (a *ArrayValue) Entry(idx int) Inspector {
if idx < len(a.v) {
return a.v[idx]
}
return InvalidNix
}

func (a *ArrayValue) MutableEntry(idx int) Cursor {
if idx < len(a.v) {
return a.v[idx]
}
return InvalidNix
}

func (a *ArrayValue) AddNix() Inspector {
return a.addElement(ValidNix)
}

func (a *ArrayValue) AddBool(value bool) Inspector {
return a.addElement(newBoolValue(value))
}

func (a *ArrayValue) AddLong(value int64) Inspector {
n := newLongValue(value)
a.v = append(a.v, n)
return n
}

func (a *ArrayValue) AddDouble(value float64) Inspector {
n := newDoubleValue(value)
a.v = append(a.v, n)
return n
}

func (a *ArrayValue) AddString(value string) Inspector {
n := newStringValue(value)
a.v = append(a.v, n)
return n
}

func (a *ArrayValue) AddData(value []byte) Inspector {
n := newDataValue(value)
a.v = append(a.v, n)
return n
}

func (a *ArrayValue) AddArray() Cursor {
n := newArrayValue()
a.v = append(a.v, n)
return n
}

func (a *ArrayValue) AddObject() Cursor {
n := newObjectValue()
a.v = append(a.v, n)
return n
}
188 changes: 188 additions & 0 deletions client/go/internal/slime/binary_decoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
// Author: arnej

package slime

type binaryDecoder struct {
buf []byte
pos int
symbols []string
failed bool
failure string
}

var emptyByteSlice = make([]byte, 0)

func newBinaryDecoder(input []byte) binaryDecoder {
return binaryDecoder{
buf: input,
pos: 0,
failed: false,
}
}

func (in *binaryDecoder) fail(reason string) {
in.failed = true
in.failure = reason
}

func (in *binaryDecoder) getByte() byte {
var b byte = 0
if !in.failed {
if in.pos < len(in.buf) {
b = in.buf[in.pos]
in.pos++
} else {
in.fail("buffer underflow")
}
}
return b
}

func (in *binaryDecoder) getBytes(sz int) []byte {
if !in.failed {
if in.pos+sz <= len(in.buf) {
start := in.pos
endp := start + sz
in.pos = endp
return in.buf[start:endp]
}
in.fail("buffer underflow")
}
return emptyByteSlice
}

func (in *binaryDecoder) read_bytes_le(sz uint32) uint64 {
var value uint64 = 0
shift := 0
for i := uint32(0); i < sz; i++ {
b := uint64(in.getByte())
value = value | (b << shift)
shift = shift + 8
}
return value
}

func (in *binaryDecoder) read_bytes_be(sz uint32) uint64 {
var value uint64 = 0
shift := 56
for i := uint32(0); i < sz; i++ {
b := uint64(in.getByte())
value = value | (b << shift)
shift = shift - 8
}
return value
}

func (in *binaryDecoder) read_cmpr_int() int {
next := in.getByte()
var value int64 = int64(next & 0x7f)
shift := 0
for (next & 0x80) != 0 {
shift += 7
next = in.getByte()
value = value | ((int64(next) & 0x7f) << shift)
if shift > 32 || value > 0x7fff_ffff {
in.fail("compressed int overflow")
value = 0
next = 0
}
}
return int(value)
}

func (in *binaryDecoder) read_size(meta uint32) int {
if meta != 0 {
return int(meta - 1)
}
return in.read_cmpr_int()
}

func (in *binaryDecoder) decodeSymbolTable() {
numSymbols := in.read_cmpr_int()
in.symbols = make([]string, numSymbols)
for i := 0; i < numSymbols; i++ {
sz := in.read_cmpr_int()
buf := in.getBytes(sz)
in.symbols[i] = string(buf)
}
}

func (in *binaryDecoder) decodeValue() Cursor {
b := in.getByte()
ty := decode_type(b)
meta := decode_meta(b)
switch ty {
case NIX:
return ValidNix
case BOOL:
return in.decodeBOOL(meta)
case LONG:
return in.decodeLONG(meta)
case DOUBLE:
return in.decodeDOUBLE(meta)
case STRING:
return in.decodeSTRING(meta)
case DATA:
return in.decodeDATA(meta)
case ARRAY:
return in.decodeARRAY(meta)
case OBJECT:
return in.decodeOBJECT(meta)
}
panic("bad type")
// return InvalidNix
}

func (in *binaryDecoder) decodeBOOL(meta uint32) Cursor {
return newBoolValue(meta != 0)
}

func (in *binaryDecoder) decodeLONG(meta uint32) Cursor {
var encoded uint64 = in.read_bytes_le(meta)
return newLongValue(decode_zigzag(encoded))
}

func (in *binaryDecoder) decodeDOUBLE(meta uint32) Cursor {
var encoded uint64 = in.read_bytes_be(meta)
return newDoubleValue(decode_double(encoded))
}

func (in *binaryDecoder) decodeSTRING(meta uint32) Cursor {
sz := in.read_size(meta)
image := in.getBytes(sz)
return newStringValue(string(image))
}

func (in *binaryDecoder) decodeDATA(meta uint32) Cursor {
sz := in.read_size(meta)
image := in.getBytes(sz)
return newDataValue(image)
}

func (in *binaryDecoder) decodeARRAY(meta uint32) Cursor {
res := newArrayValue()
sz := in.read_size(meta)
for i := 0; i < sz; i++ {
elem := in.decodeValue()
res.addElement(elem)
}
return res
}

func (in *binaryDecoder) decodeOBJECT(meta uint32) Cursor {
res := newObjectValue()
sz := in.read_size(meta)
for i := 0; i < sz; i++ {
symbol := in.read_cmpr_int()
if symbol < len(in.symbols) {
name := in.symbols[symbol]
elem := in.decodeValue()
res.addElement(name, elem)
} else {
in.fail("symbol id out of range decoding object")
return res
}
}
return res
}
Loading