aboutsummaryrefslogtreecommitdiffstats
path: root/codec/msg_codec.go
diff options
context:
space:
mode:
Diffstat (limited to 'codec/msg_codec.go')
-rw-r--r--codec/msg_codec.go113
1 files changed, 40 insertions, 73 deletions
diff --git a/codec/msg_codec.go b/codec/msg_codec.go
index 3f60cae..920366e 100644
--- a/codec/msg_codec.go
+++ b/codec/msg_codec.go
@@ -15,19 +15,13 @@
package codec
import (
- "bytes"
"errors"
"fmt"
- "reflect"
-
- "github.com/lunixbochs/struc"
"git.fd.io/govpp.git/api"
)
-// MsgCodec provides encoding and decoding functionality of `api.Message` structs into/from
-// binary format as accepted by VPP.
-type MsgCodec struct{}
+var DefaultCodec = new(MsgCodec)
// VppRequestHeader struct contains header fields implemented by all VPP requests.
type VppRequestHeader struct {
@@ -53,13 +47,16 @@ type VppOtherHeader struct {
VlMsgID uint16
}
-// EncodeMsg encodes provided `Message` structure into its binary-encoded data representation.
+// MsgCodec provides encoding and decoding functionality of `api.Message` structs into/from
+// binary format as accepted by VPP.
+type MsgCodec struct{}
+
func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) (data []byte, err error) {
if msg == nil {
return nil, errors.New("nil message passed in")
}
- // try to recover panic which might possibly occur in struc.Pack call
+ // try to recover panic which might possibly occur
defer func() {
if r := recover(); r != nil {
var ok bool
@@ -70,38 +67,27 @@ func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) (data []byte, err erro
}
}()
- var header interface{}
-
- // encode message header
- switch msg.GetMessageType() {
- case api.RequestMessage:
- header = &VppRequestHeader{VlMsgID: msgID}
- case api.ReplyMessage:
- header = &VppReplyHeader{VlMsgID: msgID}
- case api.EventMessage:
- header = &VppEventHeader{VlMsgID: msgID}
- default:
- header = &VppOtherHeader{VlMsgID: msgID}
+ marshaller, ok := msg.(Marshaler)
+ if !ok {
+ marshaller = Wrapper{msg}
}
- buf := new(bytes.Buffer)
+ size := marshaller.Size()
+ offset := getOffset(msg)
- // encode message header
- if err := struc.Pack(buf, header); err != nil {
- return nil, fmt.Errorf("failed to encode message header: %+v, error: %v", header, err)
- }
+ // encode msg ID
+ b := make([]byte, size+offset)
+ b[0] = byte(msgID >> 8)
+ b[1] = byte(msgID)
- // encode message content
- if reflect.TypeOf(msg).Elem().NumField() > 0 {
- if err := struc.Pack(buf, msg); err != nil {
- return nil, fmt.Errorf("failed to encode message data: %+v, error: %v", data, err)
- }
+ data, err = marshaller.Marshal(b[offset:])
+ if err != nil {
+ return nil, err
}
- return buf.Bytes(), nil
+ return b[0:len(b):len(b)], nil
}
-// DecodeMsg decodes binary-encoded data of a message into provided `Message` structure.
func (*MsgCodec) DecodeMsg(data []byte, msg api.Message) (err error) {
if msg == nil {
return errors.New("nil message passed in")
@@ -118,63 +104,44 @@ func (*MsgCodec) DecodeMsg(data []byte, msg api.Message) (err error) {
}
}()
- var header interface{}
-
- // check which header is expected
- switch msg.GetMessageType() {
- case api.RequestMessage:
- header = new(VppRequestHeader)
- case api.ReplyMessage:
- header = new(VppReplyHeader)
- case api.EventMessage:
- header = new(VppEventHeader)
- default:
- header = new(VppOtherHeader)
+ marshaller, ok := msg.(Unmarshaler)
+ if !ok {
+ marshaller = Wrapper{msg}
}
- buf := bytes.NewReader(data)
-
- // decode message header
- if err = struc.Unpack(buf, header); err != nil {
- return fmt.Errorf("failed to decode message header: %+v, error: %v", header, err)
- }
+ offset := getOffset(msg)
- // decode message content
- if err := struc.Unpack(buf, msg); err != nil {
- return fmt.Errorf("failed to decode message data: %+v, error: %v", data, err)
+ err = marshaller.Unmarshal(data[offset:len(data)])
+ if err != nil {
+ return err
}
return nil
}
-func (*MsgCodec) DecodeMsgContext(data []byte, msg api.Message) (uint32, error) {
+func (*MsgCodec) DecodeMsgContext(data []byte, msg api.Message) (context uint32, err error) {
if msg == nil {
return 0, errors.New("nil message passed in")
}
- var header interface{}
- var getContext func() uint32
-
- // check which header is expected
switch msg.GetMessageType() {
case api.RequestMessage:
- header = new(VppRequestHeader)
- getContext = func() uint32 { return header.(*VppRequestHeader).Context }
-
+ return order.Uint32(data[6:10]), nil
case api.ReplyMessage:
- header = new(VppReplyHeader)
- getContext = func() uint32 { return header.(*VppReplyHeader).Context }
-
- default:
- return 0, nil
+ return order.Uint32(data[2:6]), nil
}
- buf := bytes.NewReader(data)
+ return 0, nil
+}
- // decode message header
- if err := struc.Unpack(buf, header); err != nil {
- return 0, fmt.Errorf("decoding message header failed: %v", err)
+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 getContext(), nil
+ return 2
}