gecko/network/codec.go

73 lines
1.6 KiB
Go
Raw Normal View History

2020-03-10 12:20:34 -07:00
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
2020-05-17 20:47:43 -07:00
package network
2020-03-10 12:20:34 -07:00
import (
"errors"
2020-05-17 20:47:43 -07:00
"fmt"
2020-03-10 12:20:34 -07:00
"math"
"github.com/ava-labs/gecko/utils/wrappers"
)
var (
errBadLength = errors.New("stream has unexpected length")
errMissingField = errors.New("message missing field")
errBadOp = errors.New("input field has invalid operation")
)
// Codec defines the serialization and deserialization of network messages
type Codec struct{}
// Pack attempts to pack a map of fields into a message.
// The first byte of the message is the opcode of the message.
2020-05-25 13:02:03 -07:00
func (Codec) Pack(op Op, fields map[Field]interface{}) (Msg, error) {
2020-03-10 12:20:34 -07:00
message, ok := Messages[op]
if !ok {
return nil, errBadOp
}
p := wrappers.Packer{MaxSize: math.MaxInt32}
2020-05-25 13:02:03 -07:00
p.PackByte(byte(op))
2020-03-10 12:20:34 -07:00
for _, field := range message {
data, ok := fields[field]
if !ok {
return nil, errMissingField
}
field.Packer()(&p, data)
}
return &msg{
op: op,
fields: fields,
2020-05-17 20:47:43 -07:00
bytes: p.Bytes,
}, p.Err
2020-03-10 12:20:34 -07:00
}
2020-05-17 20:47:43 -07:00
// Parse attempts to convert bytes into a message.
// The first byte of the message is the opcode of the message.
2020-05-17 20:47:43 -07:00
func (Codec) Parse(b []byte) (Msg, error) {
p := wrappers.Packer{Bytes: b}
2020-05-25 13:02:03 -07:00
op := Op(p.UnpackByte())
2020-03-10 12:20:34 -07:00
message, ok := Messages[op]
if !ok {
return nil, errBadOp
}
fields := make(map[Field]interface{}, len(message))
for _, field := range message {
fields[field] = field.Unpacker()(&p)
}
2020-05-17 20:47:43 -07:00
if p.Offset != len(b) {
p.Add(fmt.Errorf("expected length %d got %d", len(b), p.Offset))
2020-03-10 12:20:34 -07:00
}
return &msg{
op: op,
fields: fields,
2020-05-17 20:47:43 -07:00
bytes: b,
2020-03-10 12:20:34 -07:00
}, p.Err
}