-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
transcoding.go
122 lines (103 loc) · 3.24 KB
/
transcoding.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package sessions
import (
"bytes"
"encoding/gob"
"encoding/json"
"reflect"
"time"
)
func init() {
gob.Register(time.Time{})
}
type (
// Marshaler is the common marshaler interface, used by transcoder.
Marshaler interface {
Marshal(interface{}) ([]byte, error)
}
// Unmarshaler is the common unmarshaler interface, used by transcoder.
Unmarshaler interface {
Unmarshal([]byte, interface{}) error
}
// Transcoder is the interface that transcoders should implement, it includes just the `Marshaler` and the `Unmarshaler`.
Transcoder interface {
Marshaler
Unmarshaler
}
)
type (
defaultTranscoder struct{}
// GobTranscoder can be set to `DefaultTranscoder` to modify the database(s) transcoder.
GobTranscoder struct{}
)
var (
_ Transcoder = (*defaultTranscoder)(nil)
_ Transcoder = (*GobTranscoder)(nil)
// DefaultTranscoder is the default transcoder across databases (when `UseDatabase` is used).
//
// The default database's values encoder and decoder
// calls the value's `Marshal/Unmarshal` methods (if any)
// otherwise JSON is selected,
// the JSON format can be stored to any database and
// it supports both builtin language types(e.g. string, int) and custom struct values.
// Also, and the most important, the values can be
// retrieved/logged/monitored by a third-party program
// written in any other language as well.
//
// You can change this behavior by registering a custom `Transcoder`.
// Iris provides a `GobTranscoder` which is mostly suitable
// if your session values are going to be custom Go structs.
// Select this if you always retrieving values through Go.
// Don't forget to initialize a call of gob.Register when necessary.
// Read https://golang.org/pkg/encoding/gob/ for more.
//
// You can also implement your own `sessions.Transcoder` and use it,
// i.e: a transcoder which will allow(on Marshal: return its byte representation and nil error)
// or dissalow(on Marshal: return non nil error) certain types.
//
// sessions.DefaultTranscoder = sessions.GobTranscoder{}
DefaultTranscoder Transcoder = defaultTranscoder{}
)
func (defaultTranscoder) Marshal(value interface{}) ([]byte, error) {
if tr, ok := value.(Marshaler); ok {
return tr.Marshal(value)
}
if jsonM, ok := value.(json.Marshaler); ok {
return jsonM.MarshalJSON()
}
return json.Marshal(value)
}
func (defaultTranscoder) Unmarshal(b []byte, outPtr interface{}) error {
if tr, ok := outPtr.(Unmarshaler); ok {
return tr.Unmarshal(b, outPtr)
}
if jsonUM, ok := outPtr.(json.Unmarshaler); ok {
return jsonUM.UnmarshalJSON(b)
}
return json.Unmarshal(b, outPtr)
}
// Marshal returns the gob encoding of "value".
func (GobTranscoder) Marshal(value interface{}) ([]byte, error) {
var (
w = new(bytes.Buffer)
enc = gob.NewEncoder(w)
err error
)
if v, ok := value.(reflect.Value); ok {
err = enc.EncodeValue(v)
} else {
err = enc.Encode(&value)
}
if err != nil {
return nil, err
}
return w.Bytes(), nil
}
// Unmarshal parses the gob-encoded data "b" and stores the result
// in the value pointed to by "outPtr".
func (GobTranscoder) Unmarshal(b []byte, outPtr interface{}) error {
dec := gob.NewDecoder(bytes.NewBuffer(b))
if v, ok := outPtr.(reflect.Value); ok {
return dec.DecodeValue(v)
}
return dec.Decode(outPtr)
}