/
opts.go
105 lines (82 loc) · 3.02 KB
/
opts.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package jdb
import (
"compress/gzip"
"encoding/json"
"io"
)
type Opts struct {
Backend func() Backend
CopyOnSet bool
}
type flusher interface {
Flush() error
}
// Backend defines a jdb transaction backend
// the backend may optionally implement the io.Closer interface
type Backend interface {
Init(w io.Writer, r io.Reader) error // initalizes the backend with a reader/writer, usually just an *os.File
Flush() error // this is called after every transaction
Encode(v interface{}) error // encodes a Tx
Decode(v interface{}) error // decodes a Tx
Marshal(in interface{}) ([]byte, error) // used by SetObject
Unmarshal(in []byte, out interface{}) error // used by GetObject
}
// JSONBackend returns a json backend.
func JSONBackend() Backend { return &jsonBackend{} }
type jsonBackend struct {
enc *json.Encoder
dec *json.Decoder
}
func (j *jsonBackend) Init(w io.Writer, r io.Reader) error {
j.enc, j.dec = json.NewEncoder(w), json.NewDecoder(r)
return nil
}
func (j *jsonBackend) Flush() error { return nil }
func (j *jsonBackend) Encode(v interface{}) error { return j.enc.Encode(v) }
func (j *jsonBackend) Decode(v interface{}) error { return j.dec.Decode(v) }
func (j *jsonBackend) Marshal(in interface{}) ([]byte, error) { return json.Marshal(in) }
func (j *jsonBackend) Unmarshal(in []byte, out interface{}) error { return json.Unmarshal(in, out) }
// GZipBackend is an alias for GZipLevelBackend(be, gzip.DefaultCompression)
func GZipBackend(be Backend) Backend { return GZipLevelBackend(be, gzip.DefaultCompression) }
// GZipLevelBackend returns a wrapper backend where all the data is gzip'ed.
func GZipLevelBackend(be Backend, level int) Backend { return &gzipBackend{level: level, be: be} }
type gzipBackend struct {
level int
be Backend
gzw *gzip.Writer
}
func (g *gzipBackend) Init(w io.Writer, r io.Reader) (err error) {
if g.gzw, err = gzip.NewWriterLevel(w, g.level); err != nil {
return err
}
gzr := &gzip.Reader{}
if err = gzr.Reset(r); err != nil && err != io.EOF {
return err
}
return g.be.Init(g.gzw, gzr)
}
func (g *gzipBackend) Flush() error {
if err := g.be.Flush(); err != nil {
return err
}
return g.gzw.Flush()
}
func (g *gzipBackend) Encode(v interface{}) error { return g.be.Encode(v) }
func (g *gzipBackend) Decode(v interface{}) error {
err := g.be.Decode(v)
if err == io.ErrUnexpectedEOF { // because gzip likes to fuck with it....
err = io.EOF
}
return err
}
func (g *gzipBackend) Marshal(in interface{}) ([]byte, error) { return g.be.Marshal(in) }
func (g *gzipBackend) Unmarshal(in []byte, out interface{}) error { return g.be.Unmarshal(in, out) }
func (j *gzipBackend) Close() error {
return j.gzw.Close()
}
// GZipJSONBackend is a shorthand for GZipBackend(JSONBackend())
func GZipJSONBackend() Backend { return GZipBackend(JSONBackend()) }
// GZipLevelJSONBackend is a shorthand for GZipLevelBackend(JSONBackend(), level)
func GZipLevelJSONBackend(level int) func() Backend {
return func() Backend { return GZipLevelBackend(JSONBackend(), level) }
}