// encoding package netlib import ( "bytes" "encoding/binary" "fmt" "google.golang.org/protobuf/proto" ) const ( EncodingTypeNil = iota EncodingTypeGPB EncodingTypeBinary EncodingTypeGob EncodingTypeMax ) var ( encodingArray [EncodingTypeMax]EncDecoder typeTesters [EncodingTypeMax]TypeTester ) type EncDecoder interface { Unmarshal(buf []byte, pack interface{}) error Marshal(pack interface{}) ([]byte, error) } type UnparsePacketTypeErr struct { EncodeType int16 PacketId int16 Err error } type TypeTester func(pack interface{}) int func (this *UnparsePacketTypeErr) Error() string { return fmt.Sprintf("cannot parse proto type:%v packetid:%v err:%v", this.EncodeType, this.PacketId, this.Err) } func NewUnparsePacketTypeErr(et, packid int16, err error) *UnparsePacketTypeErr { return &UnparsePacketTypeErr{EncodeType: et, PacketId: packid, Err: err} } func UnmarshalPacket(data []byte) (int, interface{}, error) { var ph PacketHeader err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &ph) if err != nil { return int(ph.PacketId), nil, err } if ph.EncodeType >= EncodingTypeMax { return int(ph.PacketId), nil, NewUnparsePacketTypeErr(ph.EncodeType, ph.PacketId, fmt.Errorf("EncodeType:%d unregiste", ph.EncodeType)) } pck := CreatePacket(int(ph.PacketId)) if pck == nil { return int(ph.PacketId), nil, NewUnparsePacketTypeErr(ph.EncodeType, ph.PacketId, fmt.Errorf("packetId:%d unregiste", ph.PacketId)) } else { err = encodingArray[ph.EncodeType].Unmarshal(data[LenOfPacketHeader:], pck) return int(ph.PacketId), pck, err } return 0, nil, nil } func MarshalPacket(packetid int, pack interface{}) ([]byte, error) { et := typetest(pack) if et < EncodingTypeNil || et > EncodingTypeMax { return nil, fmt.Errorf("MarshalPacket unkown data type:%v", et) } if encodingArray[et] == nil { return nil, fmt.Errorf("MarshalPacket unkown data type:%v", et) } data, err := encodingArray[et].Marshal(pack) if err != nil { return nil, fmt.Errorf("%v %v", pack, err.Error()) } ph := PacketHeader{ EncodeType: int16(et), PacketId: int16(packetid), } w := bytes.NewBuffer(nil) binary.Write(w, binary.LittleEndian, &ph) binary.Write(w, binary.LittleEndian, data) return w.Bytes(), nil } func MarshalPacketNoPackId(pack interface{}) (data []byte, err error) { et := typetest(pack) if et < EncodingTypeNil || et > EncodingTypeMax { return nil, fmt.Errorf("MarshalPacket unkown data type:%v", et) } if encodingArray[et] == nil { return nil, fmt.Errorf("MarshalPacket unkown data type:%v", et) } data, err = encodingArray[et].Marshal(pack) if err != nil { return nil, fmt.Errorf("%v %v", pack, err.Error()) } ph := PacketHeader{ EncodeType: int16(et), PacketId: int16(0), } w := bytes.NewBuffer(nil) binary.Write(w, binary.LittleEndian, &ph) binary.Write(w, binary.LittleEndian, data) return w.Bytes(), nil } func UnmarshalPacketNoPackId(data []byte, pck interface{}) error { var ph PacketHeader err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &ph) if err != nil { return err } if ph.EncodeType >= EncodingTypeMax { return NewUnparsePacketTypeErr(ph.EncodeType, ph.PacketId, fmt.Errorf("EncodeType:%d unregiste", ph.EncodeType)) } err = encodingArray[ph.EncodeType].Unmarshal(data[LenOfPacketHeader:], pck) if err != nil { return NewUnparsePacketTypeErr(ph.EncodeType, ph.PacketId, err) } return err } func SkipHeaderGetRaw(data []byte) []byte { if len(data) < LenOfPacketHeader { return nil } return data[LenOfPacketHeader:] } func typetest(pack interface{}) int { switch pack.(type) { case proto.Message: return EncodingTypeGPB case []byte: return EncodingTypeBinary default: return EncodingTypeGob } return -1 } func RegisteEncoding(edtype int, ed EncDecoder, tt TypeTester) { if encodingArray[edtype] != nil { panic(fmt.Sprintf("repeated registe EncDecoder %d", edtype)) } encodingArray[edtype] = ed typeTesters[edtype] = tt }