Skip to content

Commit

Permalink
feat(draft-02): implement draft-02, resolve #60,#61,#62,#63
Browse files Browse the repository at this point in the history
  • Loading branch information
fanweixiao committed Feb 21, 2021
1 parent 4318488 commit 4d247aa
Show file tree
Hide file tree
Showing 15 changed files with 1,202 additions and 31 deletions.
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2019~2020 北京熹乐科技有限公司 CELLA
Copyright 2019~2020 CELLA, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -198,4 +198,4 @@
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.
limitations under the License.
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@ vet:
lint:
$(GOLINT) $(GOFILES)

test:
v1test:
$(GO) test -v ./...

cover:
$(GO) test -coverprofile=prof.out && $(GO) tool cover -html=prof.out && rm prof.out
$(GO) test github.com/yomorun/y3-codec-golang/pkg -coverprofile=prof.out && $(GO) tool cover -html=prof.out && rm prof.out

test:
$(GO) test -v api.go api_test.go stream_api.go stream_api_test.go

test-spec:
$(GO) test -v github.com/yomorun/y3-codec-golang/pkg/spec
65 changes: 43 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ See [YoMo Codec SPEC](https://github.com/yomorun/yomo-codec)

## Test

`go test ./...`
`make test`

## Use

Expand All @@ -27,6 +27,8 @@ See [YoMo Codec SPEC](https://github.com/yomorun/yomo-codec)

### Encode examples

Encode Key-Value type `{ID: 3}` to Y3:

```go
package main

Expand All @@ -36,34 +38,47 @@ import (
)

func main() {
// if we want to repesent `var obj = &foo{ID: -1, bar: &bar{Name: "C"}}`
// in YoMo-Codec:
// Key:ID = Tag:0x01
buffer, _ = y3.EncodeInt(0x01, 3)

// get whole buf
fmt.Printf("res=%#v", buffer) // res=[]byte{0x01, 0x01, 0x03}
}
```

// 0x81 -> node
var foo = y3.NewNodePacketEncoder(0x01)
if we want to repesent JSON `foo: {ID: -1, Name: "C"}` in Y3:

// 0x02 -> foo.ID=-11
var yp1 = y3.NewPrimitivePacketEncoder(0x02)
yp1.SetInt32Value(-1)
foo.AddPrimitivePacket(yp1)
```go
package main

// 0x83 -> &bar{}
var bar = y3.NewNodePacketEncoder(0x03)
import (
"fmt"
y3 "github.com/yomorun/y3-codec-golang"
)

// 0x04 -> bar.Name="C"
var yp2 = y3.NewPrimitivePacketEncoder(0x04)
yp2.SetStringValue("C")
bar.AddPrimitivePacket(yp2)
func main() {
// Key:ID 0x01 -> -1
var id, _ = y3.NewPacket(0x01)
id.SetInt32(-1)

// -> foo.bar=&bar
foo.AddNodePacket(bar)

fmt.Printf("res=%#v", foo.Encode()) // res=[]byte{0x81, 0x08, 0x02, 0x01, 0x7F, 0x83, 0x03, 0x04, 0x01, 0x43}
// Key:Name 0x02 -> "C"
var name, _ = y3.NewPacket(0x02)
name.SetString("C")

// parent node
var foo, _ = y3.NewPacket(0x10)
foo.AddNode(id)
foo.AddNode(name)

// get whole buf
fmt.Printf("res=%#v", foo.Encode()) // res=[]byte{0x10, 0x06, 0x01, 0x01, 0x7F, 0x02, 0x01, 0x43}
}
```

### Decode examples 1: decode a primitive packet

Decode `[0x0A, 0x01, 0x7F]` as Int type

```go
package main

Expand All @@ -75,13 +90,13 @@ import (
func main() {
fmt.Println(">> Parsing [0x0A, 0x01, 0x7F], which like Key-Value format = 0x0A: 127")
buf := []byte{0x0A, 0x01, 0x7F}
res, _, err := y3.DecodePrimitivePacket(buf)
v1, err := res.ToUInt32()
res, _, err := y3.DecodePacket(buf)
val, err := res.ToInt32()
if err != nil {
panic(err)
}

fmt.Printf("Tag Key=[%#X], Value=%v\n", res.SeqID(), v1)
fmt.Printf("Tag Key=[%#X], Value=%v\n", res.Tag, val)
}
```

Expand Down Expand Up @@ -130,3 +145,9 @@ More examples in `/examples/`

## License
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fyomorun%2Fy3-codec-golang.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fyomorun%2Fy3-codec-golang?ref=badge_large)

## CLA

[Sign CLA](https://cla-assistant.io/yomorun/y3-codec-golang)

[![CLA assistant](https://cla-assistant.io/readme/badge/yomorun/y3-codec-golang)](https://cla-assistant.io/yomorun/y3-codec-golang)
102 changes: 102 additions & 0 deletions api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package y3

import (
"errors"

"github.com/yomorun/y3-codec-golang/pkg/spec"
)

// EncodeBool encode bool type data
func EncodeBool(tag int, v bool) ([]byte, error) {
p, err := spec.NewPacket(uint64(tag))
if err != nil {
return nil, err
}
p.SetBool(v)
return p.Encode()
}

// EncodeUInt encode uint type data
func EncodeUInt(tag int, v uint) ([]byte, error) {
p, err := spec.NewPacket(uint64(tag))
if err != nil {
return nil, err
}
p.SetUInt32(uint32(v))
return p.Encode()
}

// EncodeInt encode int type data
func EncodeInt(tag int, v int) ([]byte, error) {
p, err := spec.NewPacket(uint64(tag))
if err != nil {
return nil, err
}
p.SetInt32(v)
return p.Encode()
}

// EncodeUInt64 encode uint64 type data
func EncodeUInt64(tag int, v uint64) ([]byte, error) {
p, err := spec.NewPacket(uint64(tag))
if err != nil {
return nil, err
}
p.SetUInt64(v)
return p.Encode()
}

// EncodeInt64 encode int type data
func EncodeInt64(tag int, v int64) ([]byte, error) {
p, err := spec.NewPacket(uint64(tag))
if err != nil {
return nil, err
}
p.SetInt64(v)
return p.Encode()
}

// EncodeFloat32 encode float32 type data
func EncodeFloat32(tag int, v float32) ([]byte, error) {
p, err := spec.NewPacket(uint64(tag))
if err != nil {
return nil, err
}
p.SetFloat32(v)
return p.Encode()
}

// EncodeFloat64 encode float64 type data
func EncodeFloat64(tag int, v float64) ([]byte, error) {
p, err := spec.NewPacket(uint64(tag))
if err != nil {
return nil, err
}
p.SetFloat64(v)
return p.Encode()
}

// EncodeString encode UTF-8 string data
func EncodeString(tag int, v string) ([]byte, error) {
p, err := spec.NewPacket(uint64(tag))
if err != nil {
return nil, err
}
p.SetUTF8String(v)
return p.Encode()
}

// EncodeBytes encode raw bytes
func EncodeBytes(tag int, v []byte) ([]byte, error) {
p, err := spec.NewPacket(uint64(tag))
if err != nil {
return nil, err
}
p.PutBytes(v)
return p.Encode()
}

// Marshal TODO wip
func Marshal(tag int, obj interface{}) ([]byte, error) {
panic(errors.New("NotImplementedError"))
}
102 changes: 102 additions & 0 deletions api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package y3

import (
"testing"
)

func TestD2EncodeUInt32(t *testing.T) {
testD2EncodeUInt32(t, 0x03, 6, []byte{0x03, 0x01, 0x06})
testD2EncodeUInt32(t, 0x06, 127, []byte{0x06, 0x02, 0x80, 0x7F})
}

func TestD2EncodeInt32(t *testing.T) {
testD2EncodeInt(t, 0x03, -1, []byte{0x03, 0x01, 0x7F})
testD2EncodeInt(t, 0x06, -65, []byte{0x06, 0x02, 0xFF, 0x3F})
testD2EncodeInt(t, 0x09, 255, []byte{0x09, 0x02, 0x81, 0x7F})
}

func TestD2EncodeUInt64(t *testing.T) {
testD2EncodeUInt64(t, 0x03, 0, []byte{0x03, 0x01, 0x00})
testD2EncodeUInt64(t, 0x06, 1, []byte{0x06, 0x01, 0x01})
testD2EncodeUInt64(t, 0x09, 18446744073709551615, []byte{0x09, 0x01, 0x7F})
}

func TestD2EncodeInt64(t *testing.T) {
testD2EncodeInt64(t, 0x03, 0, []byte{0x03, 0x01, 0x00})
testD2EncodeInt64(t, 0x06, 1, []byte{0x06, 0x01, 0x01})
testD2EncodeInt64(t, 0x09, -1, []byte{0x09, 0x01, 0x7F})
}

func TestD2EncodeFloat32(t *testing.T) {
testD2EncodeFloat32(t, 0x03, -2, []byte{0x03, 0x01, 0xC0})
testD2EncodeFloat32(t, 0x06, 0.25, []byte{0x06, 0x02, 0x3E, 0x80})
testD2EncodeFloat32(t, 0x09, 68.123, []byte{0x09, 0x04, 0x42, 0x88, 0x3E, 0xFA})
}

func TestD2EncodeFloat64(t *testing.T) {
testD2EncodeFloat64(t, 0x03, 23, []byte{0x03, 0x02, 0x40, 0x37})
testD2EncodeFloat64(t, 0x06, 2, []byte{0x06, 0x01, 0x40})
testD2EncodeFloat64(t, 0x09, 0.01171875, []byte{0x09, 0x02, 0x3F, 0x88})
}

func TestD2EncodeString(t *testing.T) {
p, _ := EncodeString(0x01, "C")
compareTwoBytes(t, p, []byte{0x01, 0x01, 0x43})
p, _ = EncodeString(0x01, "CC")
compareTwoBytes(t, p, []byte{0x01, 0x02, 0x43, 0x43})
p, _ = EncodeString(0x01, "Yona")
compareTwoBytes(t, p, []byte{0x01, 0x04, 0x59, 0x6F, 0x6E, 0x61})
p, _ = EncodeString(0x01, "https://yomo.run")
compareTwoBytes(t, p, []byte{0x01, 0x10, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x79, 0x6F, 0x6D, 0x6F, 0x2E, 0x72, 0x75, 0x6E})
}

func TestD2EncodeBytes(t *testing.T) {
p, _ := EncodeBytes(0x01, []byte{0x03, 0x06, 0x09, 0x0C, 0x0F})
compareTwoBytes(t, p, []byte{0x01, 0x05, 0x03, 0x06, 0x09, 0x0C, 0x0F})
}

func TestD2EncodeBool(t *testing.T) {
p, _ := EncodeBool(0x01, true)
compareTwoBytes(t, p, []byte{0x01, 0x01, 0x01})
p, _ = EncodeBool(0x01, false)
compareTwoBytes(t, p, []byte{0x01, 0x01, 0x00})
}

func testD2EncodeUInt32(t *testing.T, tag int, val uint, expected []byte) {
p, _ := EncodeUInt(tag, val)
compareTwoBytes(t, p, expected)
}

func testD2EncodeInt(t *testing.T, tag int, val int, expected []byte) {
p, _ := EncodeInt(tag, val)
compareTwoBytes(t, p, expected)
}

func testD2EncodeUInt64(t *testing.T, tag int, val uint64, expected []byte) {
p, _ := EncodeUInt64(tag, val)
compareTwoBytes(t, p, expected)
}

func testD2EncodeInt64(t *testing.T, tag int, val int64, expected []byte) {
p, _ := EncodeInt64(tag, val)
compareTwoBytes(t, p, expected)
}

func testD2EncodeFloat32(t *testing.T, tag int, val float32, expected []byte) {
p, _ := EncodeFloat32(tag, val)
compareTwoBytes(t, p, expected)
}

func testD2EncodeFloat64(t *testing.T, tag int, val float64, expected []byte) {
p, _ := EncodeFloat64(tag, val)
compareTwoBytes(t, p, expected)
}

func compareTwoBytes(t *testing.T, result []byte, expected []byte) {
for i, p := range result {
if p != expected[i] {
t.Errorf("\nexpected:[% X]\n actual:[% X]\n", expected, result)
break
}
}
}
2 changes: 1 addition & 1 deletion pkg/encoding/nvarint.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func sizeOfNVarInt(value int64, width int) int {
const unit = 8 // bit width of encoding unit

var lead = value >> (width - 1)
for size := width / unit - 1; size > 0; size-- {
for size := width/unit - 1; size > 0; size-- {
var lookAhead = value >> (size*unit - 1)
if lookAhead != lead {
return size + 1
Expand Down
4 changes: 2 additions & 2 deletions pkg/encoding/pvarint.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func (codec *VarCodec) decodePVarInt(buffer []byte, value *int64) error {
return ErrBufferInsufficient
}

const unit = 7 // bit width of encoding unit
const unit = 7 // bit width of encoding unit
if codec.Size == 0 { // initialize sign bit
const flag = 8 - unit // bit width for non-encoding bits
*value = int64(int8(buffer[codec.Ptr]) << flag >> unit)
Expand All @@ -135,7 +135,7 @@ func (codec *VarCodec) decodePVarInt(buffer []byte, value *int64) error {
codec.Ptr++

codec.Size++
*value = (*value << unit) | int64(mask & part)
*value = (*value << unit) | int64(mask&part)

if part >= 0 { // it's the last byte
return nil
Expand Down
4 changes: 2 additions & 2 deletions pkg/encoding/varfloat.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func sizeOfVarFloat(bits uint64, width int) int {
const mask = uint64(0xFF) // mask of encoding unit

for s := 0; width > 1; s += unit {
if bits & (mask << s) != 0 {
if bits&(mask<<s) != 0 {
return width
}
width--
Expand All @@ -68,7 +68,7 @@ func (codec *VarCodec) encodeVarFloat(buffer []byte, bits uint64, width int) err
return ErrBufferInsufficient
}
codec.Size--
buffer[codec.Ptr] = byte(bits >> ((codec.Size & mask + gap) * unit))
buffer[codec.Ptr] = byte(bits >> ((codec.Size&mask + gap) * unit))
codec.Ptr++
}

Expand Down
Loading

0 comments on commit 4d247aa

Please sign in to comment.