Fix codec fallback and generate type imports
[govpp.git] / codec / msg_codec.go
1 // Copyright (c) 2017 Cisco and/or its affiliates.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package codec
16
17 import (
18         "errors"
19         "fmt"
20
21         "git.fd.io/govpp.git/api"
22 )
23
24 var DefaultCodec = new(MsgCodec)
25
26 // VppRequestHeader struct contains header fields implemented by all VPP requests.
27 type VppRequestHeader struct {
28         VlMsgID     uint16
29         ClientIndex uint32
30         Context     uint32
31 }
32
33 // VppReplyHeader struct contains header fields implemented by all VPP replies.
34 type VppReplyHeader struct {
35         VlMsgID uint16
36         Context uint32
37 }
38
39 // VppEventHeader struct contains header fields implemented by all VPP events.
40 type VppEventHeader struct {
41         VlMsgID     uint16
42         ClientIndex uint32
43 }
44
45 // VppOtherHeader struct contains header fields implemented by other VPP messages (not requests nor replies).
46 type VppOtherHeader struct {
47         VlMsgID uint16
48 }
49
50 // MsgCodec provides encoding and decoding functionality of `api.Message` structs into/from
51 // binary format as accepted by VPP.
52 type MsgCodec struct{}
53
54 func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) (data []byte, err error) {
55         if msg == nil {
56                 return nil, errors.New("nil message passed in")
57         }
58
59         // try to recover panic which might possibly occur
60         defer func() {
61                 if r := recover(); r != nil {
62                         var ok bool
63                         if err, ok = r.(error); !ok {
64                                 err = fmt.Errorf("%v", r)
65                         }
66                         err = fmt.Errorf("panic occurred during encoding message %s: %v", msg.GetMessageName(), err)
67                 }
68         }()
69
70         marshaller, ok := msg.(Marshaler)
71         if !ok {
72                 marshaller = Wrapper{msg}
73         }
74
75         size := marshaller.Size()
76         offset := getOffset(msg)
77
78         // encode msg ID
79         b := make([]byte, size+offset)
80         b[0] = byte(msgID >> 8)
81         b[1] = byte(msgID)
82
83         data, err = marshaller.Marshal(b[offset:])
84         if err != nil {
85                 return nil, err
86         }
87
88         return b[0:len(b):len(b)], nil
89 }
90
91 func (*MsgCodec) DecodeMsg(data []byte, msg api.Message) (err error) {
92         if msg == nil {
93                 return errors.New("nil message passed in")
94         }
95
96         // try to recover panic which might possibly occur
97         defer func() {
98                 if r := recover(); r != nil {
99                         var ok bool
100                         if err, ok = r.(error); !ok {
101                                 err = fmt.Errorf("%v", r)
102                         }
103                         err = fmt.Errorf("panic occurred during decoding message %s: %v", msg.GetMessageName(), err)
104                 }
105         }()
106
107         marshaller, ok := msg.(Unmarshaler)
108         if !ok {
109                 marshaller = Wrapper{msg}
110         }
111
112         offset := getOffset(msg)
113
114         err = marshaller.Unmarshal(data[offset:len(data)])
115         if err != nil {
116                 return err
117         }
118
119         return nil
120 }
121
122 func (*MsgCodec) DecodeMsgContext(data []byte, msg api.Message) (context uint32, err error) {
123         if msg == nil {
124                 return 0, errors.New("nil message passed in")
125         }
126
127         switch msg.GetMessageType() {
128         case api.RequestMessage:
129                 return order.Uint32(data[6:10]), nil
130         case api.ReplyMessage:
131                 return order.Uint32(data[2:6]), nil
132         }
133
134         return 0, nil
135 }
136
137 func getOffset(msg api.Message) (offset int) {
138         switch msg.GetMessageType() {
139         case api.RequestMessage:
140                 return 10
141         case api.ReplyMessage:
142                 return 6
143         case api.EventMessage:
144                 return 6
145         }
146         return 2
147 }