Renaming EncodeDecoder to MarshalUnmarshaler

This commit is contained in:
Asdine El Hrychy
2016-09-24 13:28:52 +02:00
parent 73768c4231
commit ba92ab1186
19 changed files with 58 additions and 61 deletions

View File

@@ -8,9 +8,6 @@ Storm is a simple and powerful ORM for [BoltDB](https://github.com/boltdb/bolt).
In addition to the examples below, see also the [examples in the GoDoc](https://godoc.org/github.com/asdine/storm#pkg-examples). In addition to the examples below, see also the [examples in the GoDoc](https://godoc.org/github.com/asdine/storm#pkg-examples).
**NEWS**
*Update: JSON is the new default codec and replaces Gob. To keep using gob use the [`storm.Codec` option](#provided-codecs) below*
## Getting Started ## Getting Started
```bash ```bash
@@ -279,9 +276,9 @@ You can change this behavior by using `BoltOptions`
db, err := storm.Open("my.db", storm.BoltOptions(0600, &bolt.Options{Timeout: 1 * time.Second})) db, err := storm.Open("my.db", storm.BoltOptions(0600, &bolt.Options{Timeout: 1 * time.Second}))
``` ```
#### EncodeDecoder #### MarshalUnmarshaler
To store the data in BoltDB, Storm encodes it in JSON by default. If you wish to change this behavior you can pass a codec that implements [`codec.EncodeDecoder`](https://godoc.org/github.com/asdine/storm/codec#EncodeDecoder) via the [`storm.Codec`](https://godoc.org/github.com/asdine/storm#Codec) option: To store the data in BoltDB, Storm marshals it in JSON by default. If you wish to change this behavior you can pass a codec that implements [`codec.MarshalUnmarshaler`](https://godoc.org/github.com/asdine/storm/codec#MarshalUnmarshaler) via the [`storm.Codec`](https://godoc.org/github.com/asdine/storm#Codec) option:
```go ```go
db := storm.Open("my.db", storm.Codec(myCodec)) db := storm.Open("my.db", storm.Codec(myCodec))
@@ -289,7 +286,7 @@ db := storm.Open("my.db", storm.Codec(myCodec))
##### Provided Codecs ##### Provided Codecs
You can easily implement your own `EncodeDecoder`, but Storm comes with built-in support for [JSON](https://godoc.org/github.com/asdine/storm/codec/json) (default), [GOB](https://godoc.org/github.com/asdine/storm/codec/gob), [Sereal](https://godoc.org/github.com/asdine/storm/codec/sereal) and [Protocol Buffers](https://godoc.org/github.com/asdine/storm/codec/protobuf) You can easily implement your own `MarshalUnmarshaler`, but Storm comes with built-in support for [JSON](https://godoc.org/github.com/asdine/storm/codec/json) (default), [GOB](https://godoc.org/github.com/asdine/storm/codec/gob), [Sereal](https://godoc.org/github.com/asdine/storm/codec/sereal) and [Protocol Buffers](https://godoc.org/github.com/asdine/storm/codec/protobuf)
These can be used by importing the relevant package and use that codec to configure Storm. The example below shows all three (without proper error handling): These can be used by importing the relevant package and use that codec to configure Storm. The example below shows all three (without proper error handling):

2
all.go
View File

@@ -79,7 +79,7 @@ func (n *node) allByIndex(tx *bolt.Tx, fieldName string, info *modelInfo, ref *r
return ErrNotFound return ErrNotFound
} }
err = n.s.codec.Decode(raw, results.Index(i).Addr().Interface()) err = n.s.codec.Unmarshal(raw, results.Index(i).Addr().Interface())
if err != nil { if err != nil {
return err return err
} }

View File

@@ -2,8 +2,8 @@
// to encode and decode entities in Storm. // to encode and decode entities in Storm.
package codec package codec
// EncodeDecoder represents a codec used to encode and decode entities. // MarshalUnmarshaler represents a codec used to marshal and unmarshal entities.
type EncodeDecoder interface { type MarshalUnmarshaler interface {
Encode(v interface{}) ([]byte, error) Marshal(v interface{}) ([]byte, error)
Decode(b []byte, v interface{}) error Unmarshal(b []byte, v interface{}) error
} }

View File

@@ -12,7 +12,7 @@ var Codec = new(gobCodec)
type gobCodec int type gobCodec int
func (c gobCodec) Encode(v interface{}) ([]byte, error) { func (c gobCodec) Marshal(v interface{}) ([]byte, error) {
var b bytes.Buffer var b bytes.Buffer
enc := gob.NewEncoder(&b) enc := gob.NewEncoder(&b)
err := enc.Encode(v) err := enc.Encode(v)
@@ -22,7 +22,7 @@ func (c gobCodec) Encode(v interface{}) ([]byte, error) {
return b.Bytes(), nil return b.Bytes(), nil
} }
func (c gobCodec) Decode(b []byte, v interface{}) error { func (c gobCodec) Unmarshal(b []byte, v interface{}) error {
r := bytes.NewReader(b) r := bytes.NewReader(b)
dec := gob.NewDecoder(r) dec := gob.NewDecoder(r)
return dec.Decode(v) return dec.Decode(v)

View File

@@ -12,8 +12,8 @@ type testStruct struct {
Name string Name string
} }
// RoundtripTester is a test helper to test a EncodeDecoder // RoundtripTester is a test helper to test a MarshalUnmarshaler
func RoundtripTester(t *testing.T, c codec.EncodeDecoder, vals ...interface{}) { func RoundtripTester(t *testing.T, c codec.MarshalUnmarshaler, vals ...interface{}) {
var val, to interface{} var val, to interface{}
if len(vals) > 0 { if len(vals) > 0 {
if len(vals) != 2 { if len(vals) != 2 {
@@ -26,11 +26,11 @@ func RoundtripTester(t *testing.T, c codec.EncodeDecoder, vals ...interface{}) {
to = &testStruct{} to = &testStruct{}
} }
encoded, err := c.Encode(val) encoded, err := c.Marshal(val)
if err != nil { if err != nil {
t.Fatal("Encode error:", err) t.Fatal("Encode error:", err)
} }
err = c.Decode(encoded, to) err = c.Unmarshal(encoded, to)
if err != nil { if err != nil {
t.Fatal("Decode error:", err) t.Fatal("Decode error:", err)
} }

View File

@@ -10,10 +10,10 @@ var Codec = new(jsonCodec)
type jsonCodec int type jsonCodec int
func (j jsonCodec) Encode(v interface{}) ([]byte, error) { func (j jsonCodec) Marshal(v interface{}) ([]byte, error) {
return json.Marshal(v) return json.Marshal(v)
} }
func (j jsonCodec) Decode(b []byte, v interface{}) error { func (j jsonCodec) Unmarshal(b []byte, v interface{}) error {
return json.Unmarshal(b, v) return json.Unmarshal(b, v)
} }

View File

@@ -18,20 +18,20 @@ type protobufCodec int
// Encode value with protocol buffer. // Encode value with protocol buffer.
// If type isn't a Protocol buffer Message, gob encoder will be used instead. // If type isn't a Protocol buffer Message, gob encoder will be used instead.
func (c protobufCodec) Encode(v interface{}) ([]byte, error) { func (c protobufCodec) Marshal(v interface{}) ([]byte, error) {
message, ok := v.(proto.Message) message, ok := v.(proto.Message)
if !ok { if !ok {
// toBytes() may need to encode non-protobuf type, if that occurs use json // toBytes() may need to encode non-protobuf type, if that occurs use json
return json.Codec.Encode(v) return json.Codec.Marshal(v)
} }
return proto.Marshal(message) return proto.Marshal(message)
} }
func (c protobufCodec) Decode(b []byte, v interface{}) error { func (c protobufCodec) Unmarshal(b []byte, v interface{}) error {
message, ok := v.(proto.Message) message, ok := v.(proto.Message)
if !ok { if !ok {
// toBytes() may have encoded non-protobuf type, if that occurs use json // toBytes() may have encoded non-protobuf type, if that occurs use json
return json.Codec.Decode(b, v) return json.Codec.Unmarshal(b, v)
} }
return proto.Unmarshal(b, message) return proto.Unmarshal(b, message)
} }

View File

@@ -12,10 +12,10 @@ var Codec = new(serealCodec)
type serealCodec int type serealCodec int
func (c serealCodec) Encode(v interface{}) ([]byte, error) { func (c serealCodec) Marshal(v interface{}) ([]byte, error) {
return sereal.Marshal(v) return sereal.Marshal(v)
} }
func (c serealCodec) Decode(b []byte, v interface{}) error { func (c serealCodec) Unmarshal(b []byte, v interface{}) error {
return sereal.Unmarshal(b, v) return sereal.Unmarshal(b, v)
} }

View File

@@ -132,38 +132,38 @@ func TestUniqueIndexRange(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
val, _ := gob.Codec.Encode(i) val, _ := gob.Codec.Marshal(i)
err = idx.Add(val, val) err = idx.Add(val, val)
assert.NoError(t, err) assert.NoError(t, err)
} }
min, _ := gob.Codec.Encode(3) min, _ := gob.Codec.Marshal(3)
max, _ := gob.Codec.Encode(5) max, _ := gob.Codec.Marshal(5)
list, err := idx.Range(min, max, nil) list, err := idx.Range(min, max, nil)
assert.Len(t, list, 3) assert.Len(t, list, 3)
assert.NoError(t, err) assert.NoError(t, err)
assertEncodedIntListEqual(t, []int{3, 4, 5}, list) assertEncodedIntListEqual(t, []int{3, 4, 5}, list)
min, _ = gob.Codec.Encode(11) min, _ = gob.Codec.Marshal(11)
max, _ = gob.Codec.Encode(20) max, _ = gob.Codec.Marshal(20)
list, err = idx.Range(min, max, nil) list, err = idx.Range(min, max, nil)
assert.Len(t, list, 0) assert.Len(t, list, 0)
assert.NoError(t, err) assert.NoError(t, err)
min, _ = gob.Codec.Encode(7) min, _ = gob.Codec.Marshal(7)
max, _ = gob.Codec.Encode(2) max, _ = gob.Codec.Marshal(2)
list, err = idx.Range(min, max, nil) list, err = idx.Range(min, max, nil)
assert.Len(t, list, 0) assert.Len(t, list, 0)
assert.NoError(t, err) assert.NoError(t, err)
min, _ = gob.Codec.Encode(-5) min, _ = gob.Codec.Marshal(-5)
max, _ = gob.Codec.Encode(2) max, _ = gob.Codec.Marshal(2)
list, err = idx.Range(min, max, nil) list, err = idx.Range(min, max, nil)
assert.Len(t, list, 0) assert.Len(t, list, 0)
assert.NoError(t, err) assert.NoError(t, err)
min, _ = gob.Codec.Encode(3) min, _ = gob.Codec.Marshal(3)
max, _ = gob.Codec.Encode(7) max, _ = gob.Codec.Marshal(7)
opts := index.NewOptions() opts := index.NewOptions()
opts.Skip = 2 opts.Skip = 2
list, err = idx.Range(min, max, opts) list, err = idx.Range(min, max, opts)
@@ -194,7 +194,7 @@ func assertEncodedIntListEqual(t *testing.T, expected []int, actual [][]byte) {
ints := make([]int, len(actual)) ints := make([]int, len(actual))
for i, e := range actual { for i, e := range actual {
err := gob.Codec.Decode(e, &ints[i]) err := gob.Codec.Unmarshal(e, &ints[i])
assert.NoError(t, err) assert.NoError(t, err)
} }

4
kv.go
View File

@@ -45,7 +45,7 @@ func (n *node) get(tx *bolt.Tx, bucketName string, id []byte, to interface{}) er
return ErrNotFound return ErrNotFound
} }
return n.s.codec.Decode(raw, to) return n.s.codec.Unmarshal(raw, to)
} }
// Set a key/value pair into a bucket // Set a key/value pair into a bucket
@@ -61,7 +61,7 @@ func (n *node) Set(bucketName string, key interface{}, value interface{}) error
var data []byte var data []byte
if value != nil { if value != nil {
data, err = n.s.codec.Encode(value) data, err = n.s.codec.Marshal(value)
if err != nil { if err != nil {
return err return err
} }

12
node.go
View File

@@ -32,11 +32,11 @@ type Node interface {
// Begin starts a new transaction. // Begin starts a new transaction.
Begin(writable bool) (Node, error) Begin(writable bool) (Node, error)
// Codec returns the EncodeDecoder used by this instance of Storm // Codec used by this instance of Storm
Codec() codec.EncodeDecoder Codec() codec.MarshalUnmarshaler
// WithCodec returns a New Storm Node that will use the given Codec. // WithCodec returns a New Storm Node that will use the given Codec.
WithCodec(codec codec.EncodeDecoder) Node WithCodec(codec codec.MarshalUnmarshaler) Node
// WithBatch returns a new Storm Node with the batch mode enabled. // WithBatch returns a new Storm Node with the batch mode enabled.
WithBatch(enabled bool) Node WithBatch(enabled bool) Node
@@ -53,7 +53,7 @@ type node struct {
tx *bolt.Tx tx *bolt.Tx
// Codec of this node // Codec of this node
codec codec.EncodeDecoder codec codec.MarshalUnmarshaler
// Enable batch mode for read-write transaction, instead of update mode // Enable batch mode for read-write transaction, instead of update mode
batchMode bool batchMode bool
@@ -73,7 +73,7 @@ func (n node) WithTransaction(tx *bolt.Tx) Node {
} }
// WithCodec returns a new Storm Node that will use the given Codec. // WithCodec returns a new Storm Node that will use the given Codec.
func (n node) WithCodec(codec codec.EncodeDecoder) Node { func (n node) WithCodec(codec codec.MarshalUnmarshaler) Node {
n.codec = codec n.codec = codec
return &n return &n
} }
@@ -91,7 +91,7 @@ func (n *node) Bucket() []string {
} }
// Codec returns the EncodeDecoder used by this instance of Storm // Codec returns the EncodeDecoder used by this instance of Storm
func (n *node) Codec() codec.EncodeDecoder { func (n *node) Codec() codec.MarshalUnmarshaler {
return n.codec return n.codec
} }

2
one.go
View File

@@ -91,7 +91,7 @@ func (n *node) one(tx *bolt.Tx, bucketName, fieldName, tag string, to interface{
return ErrNotFound return ErrNotFound
} }
return n.s.codec.Decode(raw, to) return n.s.codec.Unmarshal(raw, to)
} }
// One returns one record by the specified index // One returns one record by the specified index

View File

@@ -18,7 +18,7 @@ func BoltOptions(mode os.FileMode, options *bolt.Options) func(*DB) error {
} }
// Codec used to set a custom encoder and decoder. The default is JSON. // Codec used to set a custom encoder and decoder. The default is JSON.
func Codec(c codec.EncodeDecoder) func(*DB) error { func Codec(c codec.MarshalUnmarshaler) func(*DB) error {
return func(d *DB) error { return func(d *DB) error {
d.codec = c d.codec = c
return nil return nil

View File

@@ -37,7 +37,7 @@ func (n *node) Save(data interface{}) error {
var raw []byte var raw []byte
// postpone encoding if AutoIncrement mode if enabled // postpone encoding if AutoIncrement mode if enabled
if !n.s.autoIncrement { if !n.s.autoIncrement {
raw, err = n.s.codec.Encode(data) raw, err = n.s.codec.Marshal(data)
if err != nil { if err != nil {
return err return err
} }
@@ -68,7 +68,7 @@ func (n *node) save(tx *bolt.Tx, info *modelInfo, id []byte, raw []byte, data in
if data != nil { if data != nil {
if n.s.autoIncrement { if n.s.autoIncrement {
raw, err = n.s.codec.Encode(data) raw, err = n.s.codec.Marshal(data)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -59,7 +59,7 @@ func TestSave(t *testing.T) {
val := bucket.Get(i) val := bucket.Get(i)
assert.NotNil(t, val) assert.NotNil(t, val)
content, err := db.codec.Encode(&v) content, err := db.codec.Marshal(&v)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, content, val) assert.Equal(t, content, val)
return nil return nil

View File

@@ -21,7 +21,7 @@ type reflectSink interface {
func filter(s reflectSink, node Node, tree q.Matcher, bucket *bolt.Bucket, k, v []byte) (bool, error) { func filter(s reflectSink, node Node, tree q.Matcher, bucket *bolt.Bucket, k, v []byte) (bool, error) {
newElem := s.elem() newElem := s.elem()
err := node.Codec().Decode(v, newElem.Interface()) err := node.Codec().Unmarshal(v, newElem.Interface())
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@@ -64,7 +64,7 @@ type DB struct {
Path string Path string
// Handles encoding and decoding of objects // Handles encoding and decoding of objects
codec codec.EncodeDecoder codec codec.MarshalUnmarshaler
// Bolt is still easily accessible // Bolt is still easily accessible
Bolt *bolt.DB Bolt *bolt.DB
@@ -114,12 +114,12 @@ func (s *DB) Close() error {
} }
// Codec returns the EncodeDecoder used by this instance of Storm // Codec returns the EncodeDecoder used by this instance of Storm
func (s *DB) Codec() codec.EncodeDecoder { func (s *DB) Codec() codec.MarshalUnmarshaler {
return s.codec return s.codec
} }
// WithCodec returns a New Storm Node that will use the given Codec. // WithCodec returns a New Storm Node that will use the given Codec.
func (s *DB) WithCodec(codec codec.EncodeDecoder) Node { func (s *DB) WithCodec(codec codec.MarshalUnmarshaler) Node {
n := s.From().(*node) n := s.From().(*node)
n.codec = codec n.codec = codec
return n return n
@@ -148,7 +148,7 @@ func (s *DB) checkVersion() error {
} }
// toBytes turns an interface into a slice of bytes // toBytes turns an interface into a slice of bytes
func toBytes(key interface{}, encoder codec.EncodeDecoder) ([]byte, error) { func toBytes(key interface{}, codec codec.MarshalUnmarshaler) ([]byte, error) {
if key == nil { if key == nil {
return nil, nil return nil, nil
} }
@@ -159,5 +159,5 @@ func toBytes(key interface{}, encoder codec.EncodeDecoder) ([]byte, error) {
return []byte(k), nil return []byte(k), nil
} }
return encoder.Encode(key) return codec.Marshal(key)
} }

View File

@@ -96,20 +96,20 @@ func TestBoltDB(t *testing.T) {
type dummyCodec int type dummyCodec int
func (c dummyCodec) Encode(v interface{}) ([]byte, error) { func (c dummyCodec) Marshal(v interface{}) ([]byte, error) {
return []byte("dummy"), nil return []byte("dummy"), nil
} }
func (c dummyCodec) Decode(b []byte, v interface{}) error { func (c dummyCodec) Unmarshal(b []byte, v interface{}) error {
return nil return nil
} }
func TestCodec(t *testing.T) { func TestCodec(t *testing.T) {
u1 := &SimpleUser{Name: "John"} u1 := &SimpleUser{Name: "John"}
encoded, err := defaultCodec.Encode(u1) encoded, err := defaultCodec.Marshal(u1)
assert.Nil(t, err) assert.Nil(t, err)
u2 := &SimpleUser{} u2 := &SimpleUser{}
err = defaultCodec.Decode(encoded, u2) err = defaultCodec.Unmarshal(encoded, u2)
assert.Nil(t, err) assert.Nil(t, err)
if !reflect.DeepEqual(u1, u2) { if !reflect.DeepEqual(u1, u2) {
t.Fatal("Codec mismatch") t.Fatal("Codec mismatch")

View File

@@ -93,7 +93,7 @@ func (n *node) update(data interface{}, fn func(*reflect.Value, *reflect.Value,
return err return err
} }
raw, err := ntx.s.codec.Encode(current.Interface()) raw, err := ntx.s.codec.Marshal(current.Interface())
if err != nil { if err != nil {
return err return err
} }