1// @author Couchbase <info@couchbase.com>
2// @copyright 2014 Couchbase, Inc.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16package common
17
18import (
19	"reflect"
20)
21
22var gRegistry = NewPacketRegistry()
23
24/////////////////////////////////////////////////////////////////////////////
25// Type Declaration
26/////////////////////////////////////////////////////////////////////////////
27
28type Packet interface {
29	// Name of the message
30	Name() string
31
32	// Encode function shall marshal message to byte array.
33	Encode() (data []byte, err error)
34
35	// Decode function shall unmarshal byte array back to message.
36	Decode(data []byte) (err error)
37
38	GetVersion() uint32
39
40	// Debug Representation
41	String() string
42}
43
44type PacketRegistry struct {
45	mapping map[string]Packet
46}
47
48/////////////////////////////////////////////////////////////////////////////
49// Public Function
50/////////////////////////////////////////////////////////////////////////////
51
52func NewPacketRegistry() *PacketRegistry {
53	return &PacketRegistry{mapping: make(map[string]Packet)}
54}
55
56func RegisterPacketByName(name string, instance Packet) {
57	gRegistry.mapping[name] = instance
58}
59
60func CreatePacketByName(name string) (Packet, error) {
61	sample := gRegistry.mapping[name]
62	if sample == nil {
63		panic("Packet " + name + " is not registered with message factory.  Cannot create new packet.")
64	}
65
66	return reflect.New(FindPacketConcreteType(sample)).Interface().(Packet), nil
67}
68
69func FindPacketConcreteType(packet Packet) reflect.Type {
70	return reflect.ValueOf(packet).Elem().Type()
71}
72
73func IsValidType(name string) bool {
74
75	_, ok := gRegistry.mapping[name]
76	return ok
77}
78