aboutsummaryrefslogtreecommitdiffstats
path: root/codec/marshaler.go
diff options
context:
space:
mode:
Diffstat (limited to 'codec/marshaler.go')
-rw-r--r--codec/marshaler.go229
1 files changed, 229 insertions, 0 deletions
diff --git a/codec/marshaler.go b/codec/marshaler.go
new file mode 100644
index 0000000..c6d33a3
--- /dev/null
+++ b/codec/marshaler.go
@@ -0,0 +1,229 @@
+// Copyright (c) 2020 Cisco and/or its affiliates.
+//
+// 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 codec
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "math"
+ "reflect"
+ "unsafe"
+
+ "github.com/lunixbochs/struc"
+
+ "git.fd.io/govpp.git/api"
+)
+
+var DefaultCodec = &NewCodec{} // &MsgCodec{}
+
+// Marshaler is the interface implemented by the binary API messages that can
+// marshal itself into binary form for the wire.
+type Marshaler interface {
+ Size() int
+ Marshal([]byte) ([]byte, error)
+}
+
+// Unmarshaler is the interface implemented by the binary API messages that can
+// unmarshal a binary representation of itself from the wire.
+type Unmarshaler interface {
+ Unmarshal([]byte) error
+}
+
+type NewCodec struct{}
+
+func (*NewCodec) EncodeMsg(msg api.Message, msgID uint16) (data []byte, err error) {
+ if msg == nil {
+ return nil, errors.New("nil message passed in")
+ }
+ marshaller, ok := msg.(Marshaler)
+ if !ok {
+ return nil, fmt.Errorf("message %s does not implement marshaller", msg.GetMessageName())
+ }
+
+ size := marshaller.Size()
+ offset := getOffset(msg)
+ //fmt.Printf("size=%d offset=%d\n", size, offset)
+
+ b := make([]byte, size+offset)
+ b[0] = byte(msgID >> 8)
+ b[1] = byte(msgID)
+
+ //fmt.Printf("len(b)=%d cap(b)=%d\n", len(b), cap(b))
+ //b = append(b, byte(msgID>>8), byte(msgID))
+
+ //buf := new(bytes.Buffer)
+ //buf.Grow(size)
+
+ // encode msg ID
+ //buf.WriteByte(byte(msgID >> 8))
+ //buf.WriteByte(byte(msgID))
+
+ data, err = marshaller.Marshal(b[offset:])
+ if err != nil {
+ return nil, err
+ }
+ //buf.Write(b)
+
+ return b[0:len(b):len(b)], nil
+}
+
+func getOffset(msg api.Message) (offset int) {
+ switch msg.GetMessageType() {
+ case api.RequestMessage:
+ return 10
+ case api.ReplyMessage:
+ return 6
+ case api.EventMessage:
+ return 6
+ }
+ return 2
+}
+
+func (*NewCodec) DecodeMsg(data []byte, msg api.Message) (err error) {
+ if msg == nil {
+ return errors.New("nil message passed in")
+ }
+ marshaller, ok := msg.(Unmarshaler)
+ if !ok {
+ return fmt.Errorf("message %s does not implement marshaller", msg.GetMessageName())
+ }
+
+ offset := getOffset(msg)
+
+ err = marshaller.Unmarshal(data[offset:len(data)])
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (*NewCodec) DecodeMsgContext(data []byte, msg api.Message) (context uint32, err error) {
+ if msg == nil {
+ return 0, errors.New("nil message passed in")
+ }
+
+ switch msg.GetMessageType() {
+ case api.RequestMessage:
+ return order.Uint32(data[6:10]), nil
+ case api.ReplyMessage:
+ return order.Uint32(data[2:6]), nil
+ }
+
+ return 0, nil
+}
+
+type OldCodec struct{}
+
+func (c *OldCodec) Marshal(v interface{}) (b []byte, err error) {
+ buf := new(bytes.Buffer)
+ if err := struc.Pack(buf, v); err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+func (c *OldCodec) Unmarshal(data []byte, v interface{}) error {
+ buf := bytes.NewReader(data)
+ if err := struc.Unpack(buf, v); err != nil {
+ return err
+ }
+ return nil
+}
+
+/*type CodecNew struct{}
+
+func (c *CodecNew) Marshal(v interface{}) (b []byte, err error) {
+ buf := new(bytes.Buffer)
+ if err := binary.Write(buf, binary.BigEndian, v); err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}*/
+
+func EncodeBool(b bool) byte {
+ if b {
+ return 1
+ }
+ return 0
+}
+
+func MarshalValue(value interface{}) []byte {
+ switch value.(type) {
+ case int8:
+ return []byte{byte(value.(int8))}
+ case uint8:
+ return []byte{byte(value.(uint8))}
+ }
+ return nil
+}
+
+var order = binary.BigEndian
+
+type Buffer struct {
+ pos int
+ buf []byte
+}
+
+func (b *Buffer) Bytes() []byte {
+ return b.buf[:b.pos]
+}
+
+func (b *Buffer) EncodeUint8(v uint8) {
+ b.buf[b.pos] = v
+ b.pos += 1
+}
+
+func (b *Buffer) EncodeUint16(v uint16) {
+ order.PutUint16(b.buf[b.pos:b.pos+2], v)
+ b.pos += 2
+}
+
+func (b *Buffer) EncodeUint32(v uint32) {
+ order.PutUint32(b.buf[b.pos:b.pos+4], v)
+ b.pos += 4
+}
+
+func (b *Buffer) EncodeUint64(v uint64) {
+ order.PutUint64(b.buf[b.pos:b.pos+8], v)
+ b.pos += 8
+}
+
+func (b *Buffer) EncodeFloat64(v float64) {
+ order.PutUint64(b.buf[b.pos:b.pos+8], math.Float64bits(v))
+ b.pos += 8
+}
+
+func (b *Buffer) EncodeBool(v bool) {
+ if v {
+ b.buf[b.pos] = 1
+ } else {
+ b.buf[b.pos] = 0
+ }
+ b.pos += 1
+}
+
+func (b *Buffer) EncodeString(v string) {
+
+ b.pos += 1
+}
+
+func DecodeString(b []byte) string {
+ sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+ stringHeader := reflect.StringHeader{Data: sliceHeader.Data, Len: sliceHeader.Len}
+ return *(*string)(unsafe.Pointer(&stringHeader))
+}