forked from niubaoshu/gotiny
-
Notifications
You must be signed in to change notification settings - Fork 3
/
encoder.go
137 lines (119 loc) · 3.52 KB
/
encoder.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package gotiny
import (
"reflect"
"unsafe"
)
type Encoder struct {
buf []byte // the destination array for encoding
off int // the current offset in buf
boolPos int // the next bool to be set in buf, i.e. buf[boolPos]
boolBit byte // the next bit to be set in buf[boolPos]
engines []encEng // a collection of encoders
length int // number of encoders
}
// Marshal marshal value
func Marshal(is ...any) []byte {
return NewEncoderWithPtr(is...).Encode(is...)
}
// MarshalEncrypt marshal and encrypt value
func MarshalEncrypt(aesConfig *aesConfigStruct, is ...any) []byte {
return NewEncoderWithPtr(is...).EncodeEncrypt(aesConfig, is...)
}
// MarshalCompress marshal and compress value
func MarshalCompress(is ...any) []byte {
return NewEncoderWithPtr(is...).EncodeCompress(is...)
}
// MarshalCompressEncrypt marshal and compress and encrypt value
func MarshalCompressEncrypt(aesConfig *aesConfigStruct, is ...any) []byte {
return NewEncoderWithPtr(is...).EncodeCompressEncrypt(aesConfig, is...)
}
// Create an encoder that points to the encoding of the given type.
func NewEncoderWithPtr(ps ...any) *Encoder {
l := len(ps)
engines := make([]encEng, l)
for i := 0; i < l; i++ {
rt := reflect.TypeOf(ps[i])
if rt.Kind() != reflect.Ptr {
panic("must a pointer type!")
}
engines[i] = getEncEngine(rt.Elem())
}
return &Encoder{
length: l,
engines: engines,
}
}
// Create an encoder of type Encoder.
func NewEncoder(is ...any) *Encoder {
l := len(is)
engines := make([]encEng, l)
for i := 0; i < l; i++ {
engines[i] = getEncEngine(reflect.TypeOf(is[i]))
}
return &Encoder{
length: l,
engines: engines,
}
}
func NewEncoderWithType(ts ...reflect.Type) *Encoder {
l := len(ts)
engines := make([]encEng, l)
for i := 0; i < l; i++ {
engines[i] = getEncEngine(ts[i])
}
return &Encoder{
length: l,
engines: engines,
}
}
// Encode encode value The input is a pointer to the value to be encoded.
func (e *Encoder) Encode(is ...any) []byte {
engines := e.engines
for i := 0; i < len(engines) && i < len(is); i++ {
engines[i](e, (*[2]unsafe.Pointer)(unsafe.Pointer(&is[i]))[1])
}
return e.reset()
}
// EncodeEncrypt encrypt and encode value The input is a pointer to the value to be encoded.
func (e *Encoder) EncodeEncrypt(aesConfig *aesConfigStruct, is ...any) []byte {
return aesConfig.Encrypt(e.Encode(is...))
}
// EncodeCompress compress and encode value The input is a pointer to the value to be encoded.
func (e *Encoder) EncodeCompress(is ...any) []byte {
b := Gzip.Getbuffer()
defer Gzip.Putbuffer(b)
Gziper(b, e.Encode(is...))
return b.Bytes()
}
// EncodeCompressEncrypt compress and ecrypt and encode value The input is a pointer to the value to be encoded.
func (e *Encoder) EncodeCompressEncrypt(aesConfig *aesConfigStruct, is ...any) []byte {
return aesConfig.Encrypt(e.EncodeCompress(is...))
}
// an unsafe.Pointer to the value to be encoded.
func (e *Encoder) EncodePtr(ps ...unsafe.Pointer) []byte {
engines := e.engines
for i := 0; i < len(engines) && i < len(ps); i++ {
engines[i](e, ps[i])
}
return e.reset()
}
// vs holds the value to be encoded.
func (e *Encoder) EncodeValue(vs ...reflect.Value) []byte {
engines := e.engines
for i := 0; i < len(engines) && i < len(vs); i++ {
engines[i](e, getUnsafePointer(&vs[i]))
}
return e.reset()
}
// The encoded data will be appended to buf.
func (e *Encoder) AppendTo(buf []byte) {
e.off = len(buf)
e.buf = buf
}
func (e *Encoder) reset() []byte {
buf := e.buf
e.buf = buf[:e.off]
e.boolBit = 0
e.boolPos = 0
return buf
}