1package codec
2
3import (
4	"github.com/gogo/protobuf/proto"
5	"github.com/golang/snappy"
6)
7
8// Codec allows KV clients to serialise and deserialise values.
9type Codec interface {
10	Decode([]byte) (interface{}, error)
11	Encode(interface{}) ([]byte, error)
12
13	// CodecID is a short identifier to communicate what codec should be used to decode the value.
14	// Once in use, this should be stable to avoid confusing other clients.
15	CodecID() string
16}
17
18// Proto is a Codec for proto/snappy
19type Proto struct {
20	id      string
21	factory func() proto.Message
22}
23
24func NewProtoCodec(id string, factory func() proto.Message) Proto {
25	return Proto{id: id, factory: factory}
26}
27
28func (p Proto) CodecID() string {
29	return p.id
30}
31
32// Decode implements Codec
33func (p Proto) Decode(bytes []byte) (interface{}, error) {
34	out := p.factory()
35	bytes, err := snappy.Decode(nil, bytes)
36	if err != nil {
37		return nil, err
38	}
39	if err := proto.Unmarshal(bytes, out); err != nil {
40		return nil, err
41	}
42	return out, nil
43}
44
45// Encode implements Codec
46func (p Proto) Encode(msg interface{}) ([]byte, error) {
47	bytes, err := proto.Marshal(msg.(proto.Message))
48	if err != nil {
49		return nil, err
50	}
51	return snappy.Encode(nil, bytes), nil
52}
53
54// String is a code for strings.
55type String struct{}
56
57func (String) CodecID() string {
58	return "string"
59}
60
61// Decode implements Codec.
62func (String) Decode(bytes []byte) (interface{}, error) {
63	return string(bytes), nil
64}
65
66// Encode implements Codec.
67func (String) Encode(msg interface{}) ([]byte, error) {
68	return []byte(msg.(string)), nil
69}
70