X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=codec%2Fmsg_codec.go;fp=codec%2Fmsg_codec.go;h=920366e66721bd99c41e2f46a2e9d3b585f87a82;hb=ceed73403bdb61387d04be8b47183e9c4a970749;hp=3f60cae34173ffe1313913f2c0e51f0d99daff47;hpb=94620e85f0bdbb054af07ce3670fadc1f76cfdf0;p=govpp.git 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 }