package message import ( "encoding/binary" "errors" ) var _ Codec = (*NNetCodec)(nil) const ( msgRouteCompressMask = 0x01 // 0000 0001 last bit msgTypeMask = 0x07 // 0000 0111 1-3 bit (需要>>) msgRouteLengthMask = 0xFF // 1111 1111 last 8 bit msgHeadLength = 0x02 // 0000 0010 2 bit ) // Errors that could be occurred in message codec var ( ErrWrongMessageType = errors.New("wrong message type") ErrInvalidMessage = errors.New("invalid message") ErrRouteInfoNotFound = errors.New("route info not found in dictionary") ErrWrongMessage = errors.New("wrong message") ) var ( routes = make(map[string]uint16) // route map to code codes = make(map[uint16]string) // code map to route ) type NNetCodec struct{} func (n *NNetCodec) routable(t Type) bool { return t == Request || t == Notify || t == Push } func (n *NNetCodec) invalidType(t Type) bool { return t < Request || t > Push } func (n *NNetCodec) Encode(v interface{}) ([]byte, error) { m, ok := v.(*Message) if !ok { return nil, ErrWrongMessageType } if n.invalidType(m.Type) { return nil, ErrWrongMessageType } buf := make([]byte, 0) flag := byte(m.Type << 1) // 编译器提示,此处 byte 转换不能删 code, compressed := routes[m.Route] if compressed { flag |= msgRouteCompressMask } buf = append(buf, flag) if m.Type == Request || m.Type == Response { n := m.ID // variant length encode for { b := byte(n % 128) n >>= 7 if n != 0 { buf = append(buf, b+128) } else { buf = append(buf, b) break } } } if n.routable(m.Type) { if compressed { buf = append(buf, byte((code>>8)&0xFF)) buf = append(buf, byte(code&0xFF)) } else { buf = append(buf, byte(len(m.Route))) buf = append(buf, []byte(m.Route)...) } } buf = append(buf, m.Data...) return buf, nil } func (n *NNetCodec) Decode(data []byte) (interface{}, error) { if len(data) < msgHeadLength { return nil, ErrInvalidMessage } m := New() flag := data[0] offset := 1 m.Type = Type((flag >> 1) & msgTypeMask) // 编译器提示,此处Type转换不能删 if n.invalidType(m.Type) { return nil, ErrWrongMessageType } if m.Type == Request || m.Type == Response { id := uint64(0) // little end byte order // WARNING: must can be stored in 64 bits integer // variant length encode for i := offset; i < len(data); i++ { b := data[i] id += uint64(b&0x7F) << uint64(7*(i-offset)) if b < 128 { offset = i + 1 break } } m.ID = id } if offset >= len(data) { return nil, ErrWrongMessage } if n.routable(m.Type) { if flag&msgRouteCompressMask == 1 { m.compressed = true code := binary.BigEndian.Uint16(data[offset:(offset + 2)]) route, ok := codes[code] if !ok { return nil, ErrRouteInfoNotFound } m.Route = route offset += 2 } else { m.compressed = false rl := data[offset] offset++ if offset+int(rl) > len(data) { return nil, ErrWrongMessage } m.Route = string(data[offset:(offset + int(rl))]) offset += int(rl) } } if offset > len(data) { return nil, ErrWrongMessage } m.Data = data[offset:] return m, nil }