mirror of https://github.com/gofiber/fiber.git
parent
861e5d21fb
commit
b1b490645e
4
go.sum
4
go.sum
|
@ -8,19 +8,15 @@ github.com/valyala/fasthttp v1.18.0 h1:IV0DdMlatq9QO1Cr6wGJPVW1sV1Q8HvZXAIcjoryl
|
|||
github.com/valyala/fasthttp v1.18.0/go.mod h1:jjraHZVbKOXftJfsOYoAjaeygpj5hr8ermTRJNroD7A=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0 h1:5kGOVHlq0euqwzgTC9Vu15p6fV1Wi0ArVi8da2urnVg=
|
||||
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201210223839-7e3030f88018 h1:XKi8B/gRBuTZN1vU9gFsLMm6zVz5FSCDzm8JYACnjy8=
|
||||
golang.org/x/sys v0.0.0-20201210223839-7e3030f88018/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 zheng-ji.info
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -1,205 +0,0 @@
|
|||
package gotiny
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type decEng func(*Decoder, unsafe.Pointer) // 解码器
|
||||
|
||||
var (
|
||||
rt2decEng = map[reflect.Type]decEng{
|
||||
reflect.TypeOf((*bool)(nil)).Elem(): decBool,
|
||||
reflect.TypeOf((*int)(nil)).Elem(): decInt,
|
||||
reflect.TypeOf((*int8)(nil)).Elem(): decInt8,
|
||||
reflect.TypeOf((*int16)(nil)).Elem(): decInt16,
|
||||
reflect.TypeOf((*int32)(nil)).Elem(): decInt32,
|
||||
reflect.TypeOf((*int64)(nil)).Elem(): decInt64,
|
||||
reflect.TypeOf((*uint)(nil)).Elem(): decUint,
|
||||
reflect.TypeOf((*uint8)(nil)).Elem(): decUint8,
|
||||
reflect.TypeOf((*uint16)(nil)).Elem(): decUint16,
|
||||
reflect.TypeOf((*uint32)(nil)).Elem(): decUint32,
|
||||
reflect.TypeOf((*uint64)(nil)).Elem(): decUint64,
|
||||
reflect.TypeOf((*uintptr)(nil)).Elem(): decUintptr,
|
||||
reflect.TypeOf((*unsafe.Pointer)(nil)).Elem(): decPointer,
|
||||
reflect.TypeOf((*float32)(nil)).Elem(): decFloat32,
|
||||
reflect.TypeOf((*float64)(nil)).Elem(): decFloat64,
|
||||
reflect.TypeOf((*complex64)(nil)).Elem(): decComplex64,
|
||||
reflect.TypeOf((*complex128)(nil)).Elem(): decComplex128,
|
||||
reflect.TypeOf((*[]byte)(nil)).Elem(): decBytes,
|
||||
reflect.TypeOf((*string)(nil)).Elem(): decString,
|
||||
reflect.TypeOf((*time.Time)(nil)).Elem(): decTime,
|
||||
reflect.TypeOf((*struct{})(nil)).Elem(): decIgnore,
|
||||
reflect.TypeOf(nil): decIgnore,
|
||||
}
|
||||
|
||||
baseDecEngines = []decEng{
|
||||
reflect.Invalid: decIgnore,
|
||||
reflect.Bool: decBool,
|
||||
reflect.Int: decInt,
|
||||
reflect.Int8: decInt8,
|
||||
reflect.Int16: decInt16,
|
||||
reflect.Int32: decInt32,
|
||||
reflect.Int64: decInt64,
|
||||
reflect.Uint: decUint,
|
||||
reflect.Uint8: decUint8,
|
||||
reflect.Uint16: decUint16,
|
||||
reflect.Uint32: decUint32,
|
||||
reflect.Uint64: decUint64,
|
||||
reflect.Uintptr: decUintptr,
|
||||
reflect.UnsafePointer: decPointer,
|
||||
reflect.Float32: decFloat32,
|
||||
reflect.Float64: decFloat64,
|
||||
reflect.Complex64: decComplex64,
|
||||
reflect.Complex128: decComplex128,
|
||||
reflect.String: decString,
|
||||
}
|
||||
decLock sync.RWMutex
|
||||
)
|
||||
|
||||
func getDecEngine(rt reflect.Type) decEng {
|
||||
decLock.RLock()
|
||||
engine := rt2decEng[rt]
|
||||
decLock.RUnlock()
|
||||
if engine != nil {
|
||||
return engine
|
||||
}
|
||||
decLock.Lock()
|
||||
buildDecEngine(rt, &engine)
|
||||
decLock.Unlock()
|
||||
return engine
|
||||
}
|
||||
|
||||
func buildDecEngine(rt reflect.Type, engPtr *decEng) {
|
||||
engine, has := rt2decEng[rt]
|
||||
if has {
|
||||
*engPtr = engine
|
||||
return
|
||||
}
|
||||
|
||||
if _, engine = implementOtherSerializer(rt); engine != nil {
|
||||
rt2decEng[rt] = engine
|
||||
*engPtr = engine
|
||||
return
|
||||
}
|
||||
|
||||
kind := rt.Kind()
|
||||
var eEng decEng
|
||||
switch kind {
|
||||
case reflect.Ptr:
|
||||
et := rt.Elem()
|
||||
defer buildDecEngine(et, &eEng)
|
||||
engine = func(d *Decoder, p unsafe.Pointer) {
|
||||
if d.decIsNotNil() {
|
||||
if isNil(p) {
|
||||
*(*unsafe.Pointer)(p) = unsafe.Pointer(reflect.New(et).Elem().UnsafeAddr())
|
||||
}
|
||||
eEng(d, *(*unsafe.Pointer)(p))
|
||||
} else if !isNil(p) {
|
||||
*(*unsafe.Pointer)(p) = nil
|
||||
}
|
||||
}
|
||||
case reflect.Array:
|
||||
l, et := rt.Len(), rt.Elem()
|
||||
size := et.Size()
|
||||
defer buildDecEngine(et, &eEng)
|
||||
engine = func(d *Decoder, p unsafe.Pointer) {
|
||||
for i := 0; i < l; i++ {
|
||||
eEng(d, unsafe.Pointer(uintptr(p)+uintptr(i)*size))
|
||||
}
|
||||
}
|
||||
case reflect.Slice:
|
||||
et := rt.Elem()
|
||||
size := et.Size()
|
||||
defer buildDecEngine(et, &eEng)
|
||||
engine = func(d *Decoder, p unsafe.Pointer) {
|
||||
header := (*reflect.SliceHeader)(p)
|
||||
if d.decIsNotNil() {
|
||||
l := d.decLength()
|
||||
if isNil(p) || header.Cap < l {
|
||||
*header = reflect.SliceHeader{Data: reflect.MakeSlice(rt, l, l).Pointer(), Len: l, Cap: l}
|
||||
} else {
|
||||
header.Len = l
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
eEng(d, unsafe.Pointer(header.Data+uintptr(i)*size))
|
||||
}
|
||||
} else if !isNil(p) {
|
||||
*header = reflect.SliceHeader{}
|
||||
}
|
||||
}
|
||||
case reflect.Map:
|
||||
kt, vt := rt.Key(), rt.Elem()
|
||||
skt, svt := reflect.SliceOf(kt), reflect.SliceOf(vt)
|
||||
var kEng, vEng decEng
|
||||
defer buildDecEngine(kt, &kEng)
|
||||
defer buildDecEngine(vt, &vEng)
|
||||
engine = func(d *Decoder, p unsafe.Pointer) {
|
||||
if d.decIsNotNil() {
|
||||
l := d.decLength()
|
||||
var v reflect.Value
|
||||
if isNil(p) {
|
||||
v = reflect.MakeMapWithSize(rt, l)
|
||||
*(*unsafe.Pointer)(p) = unsafe.Pointer(v.Pointer())
|
||||
} else {
|
||||
v = reflect.NewAt(rt, p).Elem()
|
||||
}
|
||||
keys, vals := reflect.MakeSlice(skt, l, l), reflect.MakeSlice(svt, l, l)
|
||||
for i := 0; i < l; i++ {
|
||||
key, val := keys.Index(i), vals.Index(i)
|
||||
kEng(d, unsafe.Pointer(key.UnsafeAddr()))
|
||||
vEng(d, unsafe.Pointer(val.UnsafeAddr()))
|
||||
v.SetMapIndex(key, val)
|
||||
}
|
||||
} else if !isNil(p) {
|
||||
*(*unsafe.Pointer)(p) = nil
|
||||
}
|
||||
}
|
||||
case reflect.Struct:
|
||||
fields, offs := getFieldType(rt, 0)
|
||||
nf := len(fields)
|
||||
fEngines := make([]decEng, nf)
|
||||
defer func() {
|
||||
for i := 0; i < nf; i++ {
|
||||
buildDecEngine(fields[i], &fEngines[i])
|
||||
}
|
||||
}()
|
||||
engine = func(d *Decoder, p unsafe.Pointer) {
|
||||
for i := 0; i < len(fEngines) && i < len(offs); i++ {
|
||||
fEngines[i](d, unsafe.Pointer(uintptr(p)+offs[i]))
|
||||
}
|
||||
}
|
||||
case reflect.Interface:
|
||||
engine = func(d *Decoder, p unsafe.Pointer) {
|
||||
if d.decIsNotNil() {
|
||||
name := ""
|
||||
decString(d, unsafe.Pointer(&name))
|
||||
et, has := name2type[name]
|
||||
if !has {
|
||||
//panic("unknown typ:" + name)
|
||||
fmt.Println("[session] Register this type first with the `RegisterType` method.")
|
||||
}
|
||||
v := reflect.NewAt(rt, p).Elem()
|
||||
var ev reflect.Value
|
||||
if v.IsNil() || v.Elem().Type() != et {
|
||||
ev = reflect.New(et).Elem()
|
||||
} else {
|
||||
ev = v.Elem()
|
||||
}
|
||||
getDecEngine(et)(d, getUnsafePointer(&ev))
|
||||
v.Set(ev)
|
||||
} else if !isNil(p) {
|
||||
*(*unsafe.Pointer)(p) = nil
|
||||
}
|
||||
}
|
||||
case reflect.Chan, reflect.Func:
|
||||
//panic("not support " + rt.String() + " type")
|
||||
default:
|
||||
engine = baseDecEngines[kind]
|
||||
}
|
||||
rt2decEng[rt] = engine
|
||||
*engPtr = engine
|
||||
}
|
|
@ -1,161 +0,0 @@
|
|||
package gotiny
|
||||
|
||||
import (
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (d *Decoder) decBool() (b bool) {
|
||||
if d.boolBit == 0 {
|
||||
d.boolBit = 1
|
||||
d.boolPos = d.buf[d.index]
|
||||
d.index++
|
||||
}
|
||||
b = d.boolPos&d.boolBit != 0
|
||||
d.boolBit <<= 1
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Decoder) decUint64() uint64 {
|
||||
buf, i := d.buf, d.index
|
||||
x := uint64(buf[i])
|
||||
if x < 0x80 {
|
||||
d.index++
|
||||
return x
|
||||
}
|
||||
x1 := buf[i+1]
|
||||
x += uint64(x1) << 7
|
||||
if x1 < 0x80 {
|
||||
d.index += 2
|
||||
return x - 1<<7
|
||||
}
|
||||
x2 := buf[i+2]
|
||||
x += uint64(x2) << 14
|
||||
if x2 < 0x80 {
|
||||
d.index += 3
|
||||
return x - (1<<7 + 1<<14)
|
||||
}
|
||||
x3 := buf[i+3]
|
||||
x += uint64(x3) << 21
|
||||
if x3 < 0x80 {
|
||||
d.index += 4
|
||||
return x - (1<<7 + 1<<14 + 1<<21)
|
||||
}
|
||||
x4 := buf[i+4]
|
||||
x += uint64(x4) << 28
|
||||
if x4 < 0x80 {
|
||||
d.index += 5
|
||||
return x - (1<<7 + 1<<14 + 1<<21 + 1<<28)
|
||||
}
|
||||
x5 := buf[i+5]
|
||||
x += uint64(x5) << 35
|
||||
if x5 < 0x80 {
|
||||
d.index += 6
|
||||
return x - (1<<7 + 1<<14 + 1<<21 + 1<<28 + 1<<35)
|
||||
}
|
||||
x6 := buf[i+6]
|
||||
x += uint64(x6) << 42
|
||||
if x6 < 0x80 {
|
||||
d.index += 7
|
||||
return x - (1<<7 + 1<<14 + 1<<21 + 1<<28 + 1<<35 + 1<<42)
|
||||
}
|
||||
x7 := buf[i+7]
|
||||
x += uint64(x7) << 49
|
||||
if x7 < 0x80 {
|
||||
d.index += 8
|
||||
return x - (1<<7 + 1<<14 + 1<<21 + 1<<28 + 1<<35 + 1<<42 + 1<<49)
|
||||
}
|
||||
d.index += 9
|
||||
return x + uint64(buf[i+8])<<56 - (1<<7 + 1<<14 + 1<<21 + 1<<28 + 1<<35 + 1<<42 + 1<<49 + 1<<56)
|
||||
}
|
||||
|
||||
func (d *Decoder) decUint16() uint16 {
|
||||
buf, i := d.buf, d.index
|
||||
x := uint16(buf[i])
|
||||
if x < 0x80 {
|
||||
d.index++
|
||||
return x
|
||||
}
|
||||
x1 := buf[i+1]
|
||||
x += uint16(x1) << 7
|
||||
if x1 < 0x80 {
|
||||
d.index += 2
|
||||
return x - 1<<7
|
||||
}
|
||||
d.index += 3
|
||||
return x + uint16(buf[i+2])<<14 - (1<<7 + 1<<14)
|
||||
}
|
||||
|
||||
func (d *Decoder) decUint32() uint32 {
|
||||
buf, i := d.buf, d.index
|
||||
x := uint32(buf[i])
|
||||
if x < 0x80 {
|
||||
d.index++
|
||||
return x
|
||||
}
|
||||
x1 := buf[i+1]
|
||||
x += uint32(x1) << 7
|
||||
if x1 < 0x80 {
|
||||
d.index += 2
|
||||
return x - 1<<7
|
||||
}
|
||||
x2 := buf[i+2]
|
||||
x += uint32(x2) << 14
|
||||
if x2 < 0x80 {
|
||||
d.index += 3
|
||||
return x - (1<<7 + 1<<14)
|
||||
}
|
||||
x3 := buf[i+3]
|
||||
x += uint32(x3) << 21
|
||||
if x3 < 0x80 {
|
||||
d.index += 4
|
||||
return x - (1<<7 + 1<<14 + 1<<21)
|
||||
}
|
||||
x4 := buf[i+4]
|
||||
x += uint32(x4) << 28
|
||||
d.index += 5
|
||||
return x - (1<<7 + 1<<14 + 1<<21 + 1<<28)
|
||||
}
|
||||
|
||||
func (d *Decoder) decLength() int { return int(d.decUint32()) }
|
||||
func (d *Decoder) decIsNotNil() bool { return d.decBool() }
|
||||
|
||||
func decIgnore(*Decoder, unsafe.Pointer) {}
|
||||
func decBool(d *Decoder, p unsafe.Pointer) { *(*bool)(p) = d.decBool() }
|
||||
func decInt(d *Decoder, p unsafe.Pointer) { *(*int)(p) = int(uint64ToInt64(d.decUint64())) }
|
||||
func decInt8(d *Decoder, p unsafe.Pointer) { *(*int8)(p) = int8(d.buf[d.index]); d.index++ }
|
||||
func decInt16(d *Decoder, p unsafe.Pointer) { *(*int16)(p) = uint16ToInt16(d.decUint16()) }
|
||||
func decInt32(d *Decoder, p unsafe.Pointer) { *(*int32)(p) = uint32ToInt32(d.decUint32()) }
|
||||
func decInt64(d *Decoder, p unsafe.Pointer) { *(*int64)(p) = uint64ToInt64(d.decUint64()) }
|
||||
func decUint(d *Decoder, p unsafe.Pointer) { *(*uint)(p) = uint(d.decUint64()) }
|
||||
func decUint8(d *Decoder, p unsafe.Pointer) { *(*uint8)(p) = d.buf[d.index]; d.index++ }
|
||||
func decUint16(d *Decoder, p unsafe.Pointer) { *(*uint16)(p) = d.decUint16() }
|
||||
func decUint32(d *Decoder, p unsafe.Pointer) { *(*uint32)(p) = d.decUint32() }
|
||||
func decUint64(d *Decoder, p unsafe.Pointer) { *(*uint64)(p) = d.decUint64() }
|
||||
func decUintptr(d *Decoder, p unsafe.Pointer) { *(*uintptr)(p) = uintptr(d.decUint64()) }
|
||||
func decPointer(d *Decoder, p unsafe.Pointer) { *(*uintptr)(p) = uintptr(d.decUint64()) }
|
||||
func decFloat32(d *Decoder, p unsafe.Pointer) { *(*float32)(p) = uint32ToFloat32(d.decUint32()) }
|
||||
func decFloat64(d *Decoder, p unsafe.Pointer) { *(*float64)(p) = uint64ToFloat64(d.decUint64()) }
|
||||
func decTime(d *Decoder, p unsafe.Pointer) { *(*time.Time)(p) = time.Unix(0, int64(d.decUint64())) }
|
||||
func decComplex64(d *Decoder, p unsafe.Pointer) { *(*uint64)(p) = d.decUint64() }
|
||||
func decComplex128(d *Decoder, p unsafe.Pointer) {
|
||||
*(*uint64)(p) = d.decUint64()
|
||||
*(*uint64)(unsafe.Pointer(uintptr(p) + ptr1Size)) = d.decUint64()
|
||||
}
|
||||
|
||||
func decString(d *Decoder, p unsafe.Pointer) {
|
||||
l, val := int(d.decUint32()), (*string)(p)
|
||||
*val = string(d.buf[d.index : d.index+l])
|
||||
d.index += l
|
||||
}
|
||||
|
||||
func decBytes(d *Decoder, p unsafe.Pointer) {
|
||||
bytes := (*[]byte)(p)
|
||||
if d.decIsNotNil() {
|
||||
l := int(d.decUint32())
|
||||
*bytes = d.buf[d.index : d.index+l]
|
||||
d.index += l
|
||||
} else if !isNil(p) {
|
||||
*bytes = nil
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
package gotiny
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type Decoder struct {
|
||||
buf []byte //buf
|
||||
index int //下一个要使用的字节在buf中的下标
|
||||
boolPos byte //下一次要读取的bool在buf中的下标,即buf[boolPos]
|
||||
boolBit byte //下一次要读取的bool的buf[boolPos]中的bit位
|
||||
|
||||
engines []decEng //解码器集合
|
||||
length int //解码器数量
|
||||
}
|
||||
|
||||
func Unmarshal(buf []byte, is ...interface{}) int {
|
||||
return NewDecoderWithPtr(is...).Decode(buf, is...)
|
||||
}
|
||||
|
||||
func NewDecoderWithPtr(is ...interface{}) *Decoder {
|
||||
l := len(is)
|
||||
engines := make([]decEng, l)
|
||||
for i := 0; i < l; i++ {
|
||||
rt := reflect.TypeOf(is[i])
|
||||
if rt.Kind() != reflect.Ptr {
|
||||
panic("must a pointer type!")
|
||||
}
|
||||
engines[i] = getDecEngine(rt.Elem())
|
||||
}
|
||||
return &Decoder{
|
||||
length: l,
|
||||
engines: engines,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDecoder(is ...interface{}) *Decoder {
|
||||
l := len(is)
|
||||
engines := make([]decEng, l)
|
||||
for i := 0; i < l; i++ {
|
||||
engines[i] = getDecEngine(reflect.TypeOf(is[i]))
|
||||
}
|
||||
return &Decoder{
|
||||
length: l,
|
||||
engines: engines,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDecoderWithType(ts ...reflect.Type) *Decoder {
|
||||
l := len(ts)
|
||||
des := make([]decEng, l)
|
||||
for i := 0; i < l; i++ {
|
||||
des[i] = getDecEngine(ts[i])
|
||||
}
|
||||
return &Decoder{
|
||||
length: l,
|
||||
engines: des,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Decoder) reset() int {
|
||||
index := d.index
|
||||
d.index = 0
|
||||
d.boolPos = 0
|
||||
d.boolBit = 0
|
||||
return index
|
||||
}
|
||||
|
||||
// is is pointer of variable
|
||||
func (d *Decoder) Decode(buf []byte, is ...interface{}) int {
|
||||
d.buf = buf
|
||||
engines := d.engines
|
||||
for i := 0; i < len(engines) && i < len(is); i++ {
|
||||
engines[i](d, (*[2]unsafe.Pointer)(unsafe.Pointer(&is[i]))[1])
|
||||
}
|
||||
return d.reset()
|
||||
}
|
||||
|
||||
// ps is a unsafe.Pointer of the variable
|
||||
func (d *Decoder) DecodePtr(buf []byte, ps ...unsafe.Pointer) int {
|
||||
d.buf = buf
|
||||
engines := d.engines
|
||||
for i := 0; i < len(engines) && i < len(ps); i++ {
|
||||
engines[i](d, ps[i])
|
||||
}
|
||||
return d.reset()
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeValue(buf []byte, vs ...reflect.Value) int {
|
||||
d.buf = buf
|
||||
engines := d.engines
|
||||
for i := 0; i < len(engines) && i < len(vs); i++ {
|
||||
engines[i](d, unsafe.Pointer(vs[i].UnsafeAddr()))
|
||||
}
|
||||
return d.reset()
|
||||
}
|
|
@ -1,196 +0,0 @@
|
|||
package gotiny
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type encEng func(*Encoder, unsafe.Pointer) //编码器
|
||||
|
||||
var (
|
||||
rt2encEng = map[reflect.Type]encEng{
|
||||
reflect.TypeOf((*bool)(nil)).Elem(): encBool,
|
||||
reflect.TypeOf((*int)(nil)).Elem(): encInt,
|
||||
reflect.TypeOf((*int8)(nil)).Elem(): encInt8,
|
||||
reflect.TypeOf((*int16)(nil)).Elem(): encInt16,
|
||||
reflect.TypeOf((*int32)(nil)).Elem(): encInt32,
|
||||
reflect.TypeOf((*int64)(nil)).Elem(): encInt64,
|
||||
reflect.TypeOf((*uint)(nil)).Elem(): encUint,
|
||||
reflect.TypeOf((*uint8)(nil)).Elem(): encUint8,
|
||||
reflect.TypeOf((*uint16)(nil)).Elem(): encUint16,
|
||||
reflect.TypeOf((*uint32)(nil)).Elem(): encUint32,
|
||||
reflect.TypeOf((*uint64)(nil)).Elem(): encUint64,
|
||||
reflect.TypeOf((*uintptr)(nil)).Elem(): encUintptr,
|
||||
reflect.TypeOf((*unsafe.Pointer)(nil)).Elem(): encPointer,
|
||||
reflect.TypeOf((*float32)(nil)).Elem(): encFloat32,
|
||||
reflect.TypeOf((*float64)(nil)).Elem(): encFloat64,
|
||||
reflect.TypeOf((*complex64)(nil)).Elem(): encComplex64,
|
||||
reflect.TypeOf((*complex128)(nil)).Elem(): encComplex128,
|
||||
reflect.TypeOf((*[]byte)(nil)).Elem(): encBytes,
|
||||
reflect.TypeOf((*string)(nil)).Elem(): encString,
|
||||
reflect.TypeOf((*time.Time)(nil)).Elem(): encTime,
|
||||
reflect.TypeOf((*struct{})(nil)).Elem(): encIgnore,
|
||||
reflect.TypeOf(nil): encIgnore,
|
||||
}
|
||||
|
||||
encEngines = [...]encEng{
|
||||
reflect.Invalid: encIgnore,
|
||||
reflect.Bool: encBool,
|
||||
reflect.Int: encInt,
|
||||
reflect.Int8: encInt8,
|
||||
reflect.Int16: encInt16,
|
||||
reflect.Int32: encInt32,
|
||||
reflect.Int64: encInt64,
|
||||
reflect.Uint: encUint,
|
||||
reflect.Uint8: encUint8,
|
||||
reflect.Uint16: encUint16,
|
||||
reflect.Uint32: encUint32,
|
||||
reflect.Uint64: encUint64,
|
||||
reflect.Uintptr: encUintptr,
|
||||
reflect.UnsafePointer: encPointer,
|
||||
reflect.Float32: encFloat32,
|
||||
reflect.Float64: encFloat64,
|
||||
reflect.Complex64: encComplex64,
|
||||
reflect.Complex128: encComplex128,
|
||||
reflect.String: encString,
|
||||
}
|
||||
|
||||
encLock sync.RWMutex
|
||||
)
|
||||
|
||||
func UnusedUnixNanoEncodeTimeType() {
|
||||
delete(rt2encEng, reflect.TypeOf((*time.Time)(nil)).Elem())
|
||||
delete(rt2decEng, reflect.TypeOf((*time.Time)(nil)).Elem())
|
||||
}
|
||||
|
||||
func getEncEngine(rt reflect.Type) encEng {
|
||||
encLock.RLock()
|
||||
engine := rt2encEng[rt]
|
||||
encLock.RUnlock()
|
||||
if engine != nil {
|
||||
return engine
|
||||
}
|
||||
encLock.Lock()
|
||||
buildEncEngine(rt, &engine)
|
||||
encLock.Unlock()
|
||||
return engine
|
||||
}
|
||||
|
||||
func buildEncEngine(rt reflect.Type, engPtr *encEng) {
|
||||
engine := rt2encEng[rt]
|
||||
if engine != nil {
|
||||
*engPtr = engine
|
||||
return
|
||||
}
|
||||
|
||||
if engine, _ = implementOtherSerializer(rt); engine != nil {
|
||||
rt2encEng[rt] = engine
|
||||
*engPtr = engine
|
||||
return
|
||||
}
|
||||
|
||||
kind := rt.Kind()
|
||||
var eEng encEng
|
||||
switch kind {
|
||||
case reflect.Ptr:
|
||||
defer buildEncEngine(rt.Elem(), &eEng)
|
||||
engine = func(e *Encoder, p unsafe.Pointer) {
|
||||
isNotNil := !isNil(p)
|
||||
e.encIsNotNil(isNotNil)
|
||||
if isNotNil {
|
||||
eEng(e, *(*unsafe.Pointer)(p))
|
||||
}
|
||||
}
|
||||
case reflect.Array:
|
||||
et, l := rt.Elem(), rt.Len()
|
||||
defer buildEncEngine(et, &eEng)
|
||||
size := et.Size()
|
||||
engine = func(e *Encoder, p unsafe.Pointer) {
|
||||
for i := 0; i < l; i++ {
|
||||
eEng(e, unsafe.Pointer(uintptr(p)+uintptr(i)*size))
|
||||
}
|
||||
}
|
||||
case reflect.Slice:
|
||||
et := rt.Elem()
|
||||
size := et.Size()
|
||||
defer buildEncEngine(et, &eEng)
|
||||
engine = func(e *Encoder, p unsafe.Pointer) {
|
||||
isNotNil := !isNil(p)
|
||||
e.encIsNotNil(isNotNil)
|
||||
if isNotNil {
|
||||
header := (*reflect.SliceHeader)(p)
|
||||
l := header.Len
|
||||
e.encLength(l)
|
||||
for i := 0; i < l; i++ {
|
||||
eEng(e, unsafe.Pointer(header.Data+uintptr(i)*size))
|
||||
}
|
||||
}
|
||||
}
|
||||
case reflect.Map:
|
||||
var kEng encEng
|
||||
defer buildEncEngine(rt.Key(), &kEng)
|
||||
defer buildEncEngine(rt.Elem(), &eEng)
|
||||
engine = func(e *Encoder, p unsafe.Pointer) {
|
||||
isNotNil := !isNil(p)
|
||||
e.encIsNotNil(isNotNil)
|
||||
if isNotNil {
|
||||
v := reflect.NewAt(rt, p).Elem()
|
||||
e.encLength(v.Len())
|
||||
keys := v.MapKeys()
|
||||
for i := 0; i < len(keys); i++ {
|
||||
val := v.MapIndex(keys[i])
|
||||
kEng(e, getUnsafePointer(&keys[i]))
|
||||
eEng(e, getUnsafePointer(&val))
|
||||
}
|
||||
}
|
||||
}
|
||||
case reflect.Struct:
|
||||
fields, offs := getFieldType(rt, 0)
|
||||
nf := len(fields)
|
||||
fEngines := make([]encEng, nf)
|
||||
defer func() {
|
||||
for i := 0; i < nf; i++ {
|
||||
buildEncEngine(fields[i], &fEngines[i])
|
||||
}
|
||||
}()
|
||||
engine = func(e *Encoder, p unsafe.Pointer) {
|
||||
for i := 0; i < len(fEngines) && i < len(offs); i++ {
|
||||
fEngines[i](e, unsafe.Pointer(uintptr(p)+offs[i]))
|
||||
}
|
||||
}
|
||||
case reflect.Interface:
|
||||
if rt.NumMethod() > 0 {
|
||||
engine = func(e *Encoder, p unsafe.Pointer) {
|
||||
isNotNil := !isNil(p)
|
||||
e.encIsNotNil(isNotNil)
|
||||
if isNotNil {
|
||||
v := reflect.ValueOf(*(*interface {
|
||||
M()
|
||||
})(p))
|
||||
et := v.Type()
|
||||
e.encString(getNameOfType(et))
|
||||
getEncEngine(et)(e, getUnsafePointer(&v))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
engine = func(e *Encoder, p unsafe.Pointer) {
|
||||
isNotNil := !isNil(p)
|
||||
e.encIsNotNil(isNotNil)
|
||||
if isNotNil {
|
||||
v := reflect.ValueOf(*(*interface{})(p))
|
||||
et := v.Type()
|
||||
e.encString(getNameOfType(et))
|
||||
getEncEngine(et)(e, getUnsafePointer(&v))
|
||||
}
|
||||
}
|
||||
}
|
||||
case reflect.Chan, reflect.Func:
|
||||
//panic("not support " + rt.String() + " type")
|
||||
default:
|
||||
engine = encEngines[kind]
|
||||
}
|
||||
rt2encEng[rt] = engine
|
||||
*engPtr = engine
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
package gotiny
|
||||
|
||||
import (
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (e *Encoder) encBool(v bool) {
|
||||
if e.boolBit == 0 {
|
||||
e.boolPos = len(e.buf)
|
||||
e.buf = append(e.buf, 0)
|
||||
e.boolBit = 1
|
||||
}
|
||||
if v {
|
||||
e.buf[e.boolPos] |= e.boolBit
|
||||
}
|
||||
e.boolBit <<= 1
|
||||
}
|
||||
|
||||
func (e *Encoder) encUint64(v uint64) {
|
||||
switch {
|
||||
case v < 1<<7-1:
|
||||
e.buf = append(e.buf, byte(v))
|
||||
case v < 1<<14-1:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7))
|
||||
case v < 1<<21-1:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7)|0x80, byte(v>>14))
|
||||
case v < 1<<28-1:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7)|0x80, byte(v>>14)|0x80, byte(v>>21))
|
||||
case v < 1<<35-1:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7)|0x80, byte(v>>14)|0x80, byte(v>>21)|0x80, byte(v>>28))
|
||||
case v < 1<<42-1:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7)|0x80, byte(v>>14)|0x80, byte(v>>21)|0x80, byte(v>>28)|0x80, byte(v>>35))
|
||||
case v < 1<<49-1:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7)|0x80, byte(v>>14)|0x80, byte(v>>21)|0x80, byte(v>>28)|0x80, byte(v>>35)|0x80, byte(v>>42))
|
||||
case v < 1<<56-1:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7)|0x80, byte(v>>14)|0x80, byte(v>>21)|0x80, byte(v>>28)|0x80, byte(v>>35)|0x80, byte(v>>42)|0x80, byte(v>>49))
|
||||
default:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7)|0x80, byte(v>>14)|0x80, byte(v>>21)|0x80, byte(v>>28)|0x80, byte(v>>35)|0x80, byte(v>>42)|0x80, byte(v>>49)|0x80, byte(v>>56))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) encUint16(v uint16) {
|
||||
if v < 1<<7-1 {
|
||||
e.buf = append(e.buf, byte(v))
|
||||
} else if v < 1<<14-1 {
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7))
|
||||
} else {
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7)|0x80, byte(v>>14))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) encUint32(v uint32) {
|
||||
switch {
|
||||
case v < 1<<7-1:
|
||||
e.buf = append(e.buf, byte(v))
|
||||
case v < 1<<14-1:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7))
|
||||
case v < 1<<21-1:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7)|0x80, byte(v>>14))
|
||||
case v < 1<<28-1:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7)|0x80, byte(v>>14)|0x80, byte(v>>21))
|
||||
default:
|
||||
e.buf = append(e.buf, byte(v)|0x80, byte(v>>7)|0x80, byte(v>>14)|0x80, byte(v>>21)|0x80, byte(v>>28))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) encLength(v int) { e.encUint32(uint32(v)) }
|
||||
func (e *Encoder) encString(s string) { e.encUint32(uint32(len(s))); e.buf = append(e.buf, s...) }
|
||||
func (e *Encoder) encIsNotNil(v bool) { e.encBool(v) }
|
||||
|
||||
func encIgnore(*Encoder, unsafe.Pointer) {}
|
||||
func encBool(e *Encoder, p unsafe.Pointer) { e.encBool(*(*bool)(p)) }
|
||||
func encInt(e *Encoder, p unsafe.Pointer) { e.encUint64(int64ToUint64(int64(*(*int)(p)))) }
|
||||
func encInt8(e *Encoder, p unsafe.Pointer) { e.buf = append(e.buf, *(*uint8)(p)) }
|
||||
func encInt16(e *Encoder, p unsafe.Pointer) { e.encUint16(int16ToUint16(*(*int16)(p))) }
|
||||
func encInt32(e *Encoder, p unsafe.Pointer) { e.encUint32(int32ToUint32(*(*int32)(p))) }
|
||||
func encInt64(e *Encoder, p unsafe.Pointer) { e.encUint64(int64ToUint64(*(*int64)(p))) }
|
||||
func encUint8(e *Encoder, p unsafe.Pointer) { e.buf = append(e.buf, *(*uint8)(p)) }
|
||||
func encUint16(e *Encoder, p unsafe.Pointer) { e.encUint16(*(*uint16)(p)) }
|
||||
func encUint32(e *Encoder, p unsafe.Pointer) { e.encUint32(*(*uint32)(p)) }
|
||||
func encUint64(e *Encoder, p unsafe.Pointer) { e.encUint64(uint64(*(*uint64)(p))) }
|
||||
func encUint(e *Encoder, p unsafe.Pointer) { e.encUint64(uint64(*(*uint)(p))) }
|
||||
func encUintptr(e *Encoder, p unsafe.Pointer) { e.encUint64(uint64(*(*uintptr)(p))) }
|
||||
func encPointer(e *Encoder, p unsafe.Pointer) { e.encUint64(uint64(*(*uintptr)(p))) }
|
||||
func encFloat32(e *Encoder, p unsafe.Pointer) { e.encUint32(float32ToUint32(p)) }
|
||||
func encFloat64(e *Encoder, p unsafe.Pointer) { e.encUint64(float64ToUint64(p)) }
|
||||
func encString(e *Encoder, p unsafe.Pointer) {
|
||||
s := *(*string)(p)
|
||||
e.encUint32(uint32(len(s)))
|
||||
e.buf = append(e.buf, s...)
|
||||
}
|
||||
func encTime(e *Encoder, p unsafe.Pointer) { e.encUint64(uint64((*time.Time)(p).UnixNano())) }
|
||||
func encComplex64(e *Encoder, p unsafe.Pointer) { e.encUint64(*(*uint64)(p)) }
|
||||
func encComplex128(e *Encoder, p unsafe.Pointer) {
|
||||
e.encUint64(*(*uint64)(p))
|
||||
e.encUint64(*(*uint64)(unsafe.Pointer(uintptr(p) + ptr1Size)))
|
||||
}
|
||||
|
||||
func encBytes(e *Encoder, p unsafe.Pointer) {
|
||||
isNotNil := !isNil(p)
|
||||
e.encIsNotNil(isNotNil)
|
||||
if isNotNil {
|
||||
buf := *(*[]byte)(p)
|
||||
e.encLength(len(buf))
|
||||
e.buf = append(e.buf, buf...)
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
package gotiny
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type Encoder struct {
|
||||
buf []byte //编码目的数组
|
||||
off int
|
||||
boolPos int //下一次要设置的bool在buf中的下标,即buf[boolPos]
|
||||
boolBit byte //下一次要设置的bool的buf[boolPos]中的bit位
|
||||
|
||||
engines []encEng
|
||||
length int
|
||||
}
|
||||
|
||||
func Marshal(is ...interface{}) []byte {
|
||||
return NewEncoderWithPtr(is...).Encode(is...)
|
||||
}
|
||||
|
||||
// 创建一个编码ps 指向类型的编码器
|
||||
func NewEncoderWithPtr(ps ...interface{}) *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,
|
||||
}
|
||||
}
|
||||
|
||||
// 创建一个编码is 类型的编码器
|
||||
func NewEncoder(is ...interface{}) *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,
|
||||
}
|
||||
}
|
||||
|
||||
// 入参是要编码值的指针
|
||||
func (e *Encoder) Encode(is ...interface{}) []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()
|
||||
}
|
||||
|
||||
// 入参是要编码的值得unsafe.Pointer 指针
|
||||
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 是持有要编码的值
|
||||
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()
|
||||
}
|
||||
|
||||
// 编码产生的数据将append到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
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
package gotiny
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
type2name = map[reflect.Type]string{}
|
||||
name2type = map[string]reflect.Type{}
|
||||
)
|
||||
|
||||
func GetName(obj interface{}) string {
|
||||
return GetNameByType(reflect.TypeOf(obj))
|
||||
}
|
||||
func GetNameByType(rt reflect.Type) string {
|
||||
return string(getName([]byte(nil), rt))
|
||||
}
|
||||
|
||||
func getName(prefix []byte, rt reflect.Type) []byte {
|
||||
if rt == nil || rt.Kind() == reflect.Invalid {
|
||||
return append(prefix, []byte("<nil>")...)
|
||||
}
|
||||
if rt.Name() == "" { //未命名的,组合类型
|
||||
switch rt.Kind() {
|
||||
case reflect.Ptr:
|
||||
return getName(append(prefix, '*'), rt.Elem())
|
||||
case reflect.Array:
|
||||
return getName(append(prefix, "["+strconv.Itoa(rt.Len())+"]"...), rt.Elem())
|
||||
case reflect.Slice:
|
||||
return getName(append(prefix, '[', ']'), rt.Elem())
|
||||
case reflect.Struct:
|
||||
prefix = append(prefix, "struct {"...)
|
||||
nf := rt.NumField()
|
||||
if nf > 0 {
|
||||
prefix = append(prefix, ' ')
|
||||
}
|
||||
for i := 0; i < nf; i++ {
|
||||
field := rt.Field(i)
|
||||
if field.Anonymous {
|
||||
prefix = getName(prefix, field.Type)
|
||||
} else {
|
||||
prefix = getName(append(prefix, field.Name+" "...), field.Type)
|
||||
}
|
||||
if i != nf-1 {
|
||||
prefix = append(prefix, ';', ' ')
|
||||
} else {
|
||||
prefix = append(prefix, ' ')
|
||||
}
|
||||
}
|
||||
return append(prefix, '}')
|
||||
case reflect.Map:
|
||||
return getName(append(getName(append(prefix, "map["...), rt.Key()), ']'), rt.Elem())
|
||||
case reflect.Interface:
|
||||
prefix = append(prefix, "interface {"...)
|
||||
nm := rt.NumMethod()
|
||||
if nm > 0 {
|
||||
prefix = append(prefix, ' ')
|
||||
}
|
||||
for i := 0; i < nm; i++ {
|
||||
method := rt.Method(i)
|
||||
fn := getName([]byte(nil), method.Type)
|
||||
prefix = append(prefix, method.Name+string(fn[4:])...)
|
||||
if i != nm-1 {
|
||||
prefix = append(prefix, ';', ' ')
|
||||
} else {
|
||||
prefix = append(prefix, ' ')
|
||||
}
|
||||
}
|
||||
return append(prefix, '}')
|
||||
case reflect.Func:
|
||||
prefix = append(prefix, "func("...)
|
||||
for i := 0; i < rt.NumIn(); i++ {
|
||||
prefix = getName(prefix, rt.In(i))
|
||||
if i != rt.NumIn()-1 {
|
||||
prefix = append(prefix, ',', ' ')
|
||||
}
|
||||
}
|
||||
prefix = append(prefix, ')')
|
||||
no := rt.NumOut()
|
||||
if no > 0 {
|
||||
prefix = append(prefix, ' ')
|
||||
}
|
||||
if no > 1 {
|
||||
prefix = append(prefix, '(')
|
||||
}
|
||||
for i := 0; i < no; i++ {
|
||||
prefix = getName(prefix, rt.Out(i))
|
||||
if i != no-1 {
|
||||
prefix = append(prefix, ',', ' ')
|
||||
}
|
||||
}
|
||||
if no > 1 {
|
||||
prefix = append(prefix, ')')
|
||||
}
|
||||
return prefix
|
||||
}
|
||||
}
|
||||
|
||||
if rt.PkgPath() == "" {
|
||||
prefix = append(prefix, rt.Name()...)
|
||||
} else {
|
||||
prefix = append(prefix, rt.PkgPath()+"."+rt.Name()...)
|
||||
}
|
||||
return prefix
|
||||
}
|
||||
|
||||
func getNameOfType(rt reflect.Type) string {
|
||||
if name, has := type2name[rt]; has {
|
||||
return name
|
||||
} else {
|
||||
return registerType(rt)
|
||||
}
|
||||
}
|
||||
|
||||
func Register(i interface{}) string {
|
||||
return registerType(reflect.TypeOf(i))
|
||||
}
|
||||
|
||||
func registerType(rt reflect.Type) string {
|
||||
name := GetNameByType(rt)
|
||||
RegisterName(name, rt)
|
||||
return name
|
||||
}
|
||||
|
||||
func RegisterName(name string, rt reflect.Type) {
|
||||
if name == "" {
|
||||
panic("attempt to register empty name")
|
||||
}
|
||||
|
||||
if rt == nil || rt.Kind() == reflect.Invalid {
|
||||
panic("attempt to register nil type or invalid type")
|
||||
}
|
||||
|
||||
if _, has := type2name[rt]; has {
|
||||
panic("gotiny: registering duplicate types for " + GetNameByType(rt))
|
||||
}
|
||||
|
||||
if _, has := name2type[name]; has {
|
||||
panic("gotiny: registering name" + name + " is exist")
|
||||
}
|
||||
name2type[name] = rt
|
||||
type2name[rt] = name
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
package gotiny
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
kindDirectIface = 1 << 5
|
||||
)
|
||||
|
||||
// rtype is the common implementation of most values.
|
||||
// It is embedded in other struct types.
|
||||
//
|
||||
// rtype must be kept in sync with reflect/type.go:/^type._type.
|
||||
type rtype struct {
|
||||
_ uintptr
|
||||
_ uintptr // number of bytes in the type that can contain pointers
|
||||
_ uint32 // hash of type; avoids computation in hash tables
|
||||
_ uint8 // extra type information flags
|
||||
_ uint8 // alignment of variable with this type
|
||||
_ uint8 // alignment of struct field with this type
|
||||
kind uint8 // enumeration for C
|
||||
_ uintptr // algorithm table
|
||||
_ uintptr // garbage collection data
|
||||
_ int32 // string form
|
||||
_ int32 // type for pointer to this type, may be zero
|
||||
}
|
||||
|
||||
// ifaceIndir reports whether t is stored indirectly in an interface value.
|
||||
func ifaceDirect(t *rtype) bool {
|
||||
return t.kind&kindDirectIface != 0
|
||||
}
|
||||
|
||||
func directType(rt *reflect.Type) bool {
|
||||
return ifaceDirect((*rtype)((*[2]unsafe.Pointer)(unsafe.Pointer(rt))[1]))
|
||||
}
|
||||
|
||||
type refVal struct {
|
||||
_ unsafe.Pointer
|
||||
ptr unsafe.Pointer
|
||||
flag flag
|
||||
}
|
||||
|
||||
type flag uintptr
|
||||
|
||||
//go:linkname flagIndir reflect.flagIndir
|
||||
const flagIndir flag = 1 << 7
|
||||
|
||||
func getUnsafePointer(rv *reflect.Value) unsafe.Pointer {
|
||||
vv := (*refVal)(unsafe.Pointer(rv))
|
||||
if vv.flag&flagIndir == 0 {
|
||||
return unsafe.Pointer(&vv.ptr)
|
||||
} else {
|
||||
return vv.ptr
|
||||
}
|
||||
}
|
|
@ -1,185 +0,0 @@
|
|||
package gotiny
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/gob"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
ptr1Size = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const
|
||||
)
|
||||
|
||||
func float64ToUint64(v unsafe.Pointer) uint64 {
|
||||
return reverse64Byte(*(*uint64)(v))
|
||||
}
|
||||
|
||||
func uint64ToFloat64(u uint64) float64 {
|
||||
u = reverse64Byte(u)
|
||||
return *((*float64)(unsafe.Pointer(&u)))
|
||||
}
|
||||
|
||||
func reverse64Byte(u uint64) uint64 {
|
||||
u = (u << 32) | (u >> 32)
|
||||
u = ((u << 16) & 0xFFFF0000FFFF0000) | ((u >> 16) & 0xFFFF0000FFFF)
|
||||
u = ((u << 8) & 0xFF00FF00FF00FF00) | ((u >> 8) & 0xFF00FF00FF00FF)
|
||||
return u
|
||||
}
|
||||
|
||||
func float32ToUint32(v unsafe.Pointer) uint32 {
|
||||
return reverse32Byte(*(*uint32)(v))
|
||||
}
|
||||
|
||||
func uint32ToFloat32(u uint32) float32 {
|
||||
u = reverse32Byte(u)
|
||||
return *((*float32)(unsafe.Pointer(&u)))
|
||||
}
|
||||
|
||||
func reverse32Byte(u uint32) uint32 {
|
||||
u = (u << 16) | (u >> 16)
|
||||
return ((u << 8) & 0xFF00FF00) | ((u >> 8) & 0xFF00FF)
|
||||
}
|
||||
|
||||
// int -5 -4 -3 -2 -1 0 1 2 3 4 5 6
|
||||
// uint 9 7 5 3 1 0 2 4 6 8 10 12
|
||||
func int64ToUint64(v int64) uint64 {
|
||||
return uint64((v << 1) ^ (v >> 63))
|
||||
}
|
||||
|
||||
// uint 9 7 5 3 1 0 2 4 6 8 10 12
|
||||
// int -5 -4 -3 -2 -1 0 1 2 3 4 5 6
|
||||
func uint64ToInt64(u uint64) int64 {
|
||||
v := int64(u)
|
||||
return (-(v & 1)) ^ (v>>1)&0x7FFFFFFFFFFFFFFF
|
||||
}
|
||||
|
||||
// int -5 -4 -3 -2 -1 0 1 2 3 4 5 6
|
||||
// uint 9 7 5 3 1 0 2 4 6 8 10 12
|
||||
func int32ToUint32(v int32) uint32 {
|
||||
return uint32((v << 1) ^ (v >> 31))
|
||||
}
|
||||
|
||||
// uint 9 7 5 3 1 0 2 4 6 8 10 12
|
||||
// int -5 -4 -3 -2 -1 0 1 2 3 4 5 6
|
||||
func uint32ToInt32(u uint32) int32 {
|
||||
v := int32(u)
|
||||
return (-(v & 1)) ^ (v>>1)&0x7FFFFFFF
|
||||
}
|
||||
|
||||
// int -5 -4 -3 -2 -1 0 1 2 3 4 5 6
|
||||
// uint 9 7 5 3 1 0 2 4 6 8 10 12
|
||||
func int16ToUint16(v int16) uint16 {
|
||||
return uint16((v << 1) ^ (v >> 15))
|
||||
}
|
||||
|
||||
// uint 9 7 5 3 1 0 2 4 6 8 10 12
|
||||
// int -5 -4 -3 -2 -1 0 1 2 3 4 5 6
|
||||
func uint16ToInt16(u uint16) int16 {
|
||||
v := int16(u)
|
||||
return (-(v & 1)) ^ (v>>1)&0x7FFF
|
||||
}
|
||||
|
||||
func isNil(p unsafe.Pointer) bool {
|
||||
return *(*unsafe.Pointer)(p) == nil
|
||||
}
|
||||
|
||||
type gobInter interface {
|
||||
gob.GobEncoder
|
||||
gob.GobDecoder
|
||||
}
|
||||
|
||||
type binInter interface {
|
||||
encoding.BinaryMarshaler
|
||||
encoding.BinaryUnmarshaler
|
||||
}
|
||||
|
||||
// 只应该由指针来实现该接口
|
||||
type GoTinySerializer interface {
|
||||
// 编码方法,将对象的序列化结果append到入参数并返回,方法不应该修改入参数值原有的值
|
||||
GotinyEncode([]byte) []byte
|
||||
// 解码方法,将入参解码到对象里并返回使用的长度。方法从入参的第0个字节开始使用,并且不应该修改入参中的任何数据
|
||||
GotinyDecode([]byte) int
|
||||
}
|
||||
|
||||
func implementOtherSerializer(rt reflect.Type) (encEng encEng, decEng decEng) {
|
||||
rtNil := reflect.Zero(reflect.PtrTo(rt)).Interface()
|
||||
if _, ok := rtNil.(GoTinySerializer); ok {
|
||||
encEng = func(e *Encoder, p unsafe.Pointer) {
|
||||
e.buf = reflect.NewAt(rt, p).Interface().(GoTinySerializer).GotinyEncode(e.buf)
|
||||
}
|
||||
decEng = func(d *Decoder, p unsafe.Pointer) {
|
||||
d.index += reflect.NewAt(rt, p).Interface().(GoTinySerializer).GotinyDecode(d.buf[d.index:])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if _, ok := rtNil.(binInter); ok {
|
||||
encEng = func(e *Encoder, p unsafe.Pointer) {
|
||||
buf, err := reflect.NewAt(rt, p).Interface().(encoding.BinaryMarshaler).MarshalBinary()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
e.encLength(len(buf))
|
||||
e.buf = append(e.buf, buf...)
|
||||
}
|
||||
|
||||
decEng = func(d *Decoder, p unsafe.Pointer) {
|
||||
length := d.decLength()
|
||||
start := d.index
|
||||
d.index += length
|
||||
if err := reflect.NewAt(rt, p).Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(d.buf[start:d.index]); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if _, ok := rtNil.(gobInter); ok {
|
||||
encEng = func(e *Encoder, p unsafe.Pointer) {
|
||||
buf, err := reflect.NewAt(rt, p).Interface().(gob.GobEncoder).GobEncode()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
e.encLength(len(buf))
|
||||
e.buf = append(e.buf, buf...)
|
||||
}
|
||||
decEng = func(d *Decoder, p unsafe.Pointer) {
|
||||
length := d.decLength()
|
||||
start := d.index
|
||||
d.index += length
|
||||
if err := reflect.NewAt(rt, p).Interface().(gob.GobDecoder).GobDecode(d.buf[start:d.index]); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// rt.kind is reflect.struct
|
||||
func getFieldType(rt reflect.Type, baseOff uintptr) (fields []reflect.Type, offs []uintptr) {
|
||||
for i := 0; i < rt.NumField(); i++ {
|
||||
field := rt.Field(i)
|
||||
if ignoreField(field) {
|
||||
continue
|
||||
}
|
||||
ft := field.Type
|
||||
if ft.Kind() == reflect.Struct {
|
||||
if _, engine := implementOtherSerializer(ft); engine == nil {
|
||||
fFields, fOffs := getFieldType(ft, field.Offset+baseOff)
|
||||
fields = append(fields, fFields...)
|
||||
offs = append(offs, fOffs...)
|
||||
continue
|
||||
}
|
||||
}
|
||||
fields = append(fields, ft)
|
||||
offs = append(offs, field.Offset+baseOff)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ignoreField(field reflect.StructField) bool {
|
||||
tinyTag, ok := field.Tag.Lookup("gotiny")
|
||||
return ok && strings.TrimSpace(tinyTag) == "-"
|
||||
}
|
|
@ -9,14 +9,14 @@ import (
|
|||
// don't forget to replace the msgp import path to:
|
||||
// "github.com/gofiber/fiber/v2/internal/msgp"
|
||||
type data struct {
|
||||
sync.RWMutex `gotiny:"-"`
|
||||
d map[string]interface{} `gotiny:"d"`
|
||||
sync.RWMutex
|
||||
Data map[string]interface{}
|
||||
}
|
||||
|
||||
var dataPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
d := new(data)
|
||||
d.d = make(map[string]interface{})
|
||||
d.Data = make(map[string]interface{})
|
||||
return d
|
||||
},
|
||||
}
|
||||
|
@ -32,31 +32,31 @@ func releaseData(d *data) {
|
|||
|
||||
func (d *data) Reset() {
|
||||
d.Lock()
|
||||
for key := range d.d {
|
||||
delete(d.d, key)
|
||||
for key := range d.Data {
|
||||
delete(d.Data, key)
|
||||
}
|
||||
d.Unlock()
|
||||
}
|
||||
|
||||
func (d *data) Get(key string) interface{} {
|
||||
d.RLock()
|
||||
v := d.d[key]
|
||||
v := d.Data[key]
|
||||
d.RUnlock()
|
||||
return v
|
||||
}
|
||||
|
||||
func (d *data) Set(key string, value interface{}) {
|
||||
d.Lock()
|
||||
d.d[key] = value
|
||||
d.Data[key] = value
|
||||
d.Unlock()
|
||||
}
|
||||
|
||||
func (d *data) Delete(key string) {
|
||||
d.Lock()
|
||||
delete(d.d, key)
|
||||
delete(d.Data, key)
|
||||
d.Unlock()
|
||||
}
|
||||
|
||||
func (d *data) Len() int {
|
||||
return len(d.d)
|
||||
return len(d.Data)
|
||||
}
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/internal/gotiny"
|
||||
"github.com/gofiber/fiber/v2/utils"
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
id string // session id
|
||||
fresh bool // if new session
|
||||
ctx *fiber.Ctx // fiber context
|
||||
config *Store // store configuration
|
||||
data *data // key value data
|
||||
id string // session id
|
||||
fresh bool // if new session
|
||||
ctx *fiber.Ctx // fiber context
|
||||
config *Store // store configuration
|
||||
data *data // key value data
|
||||
byteBuffer *bytes.Buffer // byte buffer for the en- and decode
|
||||
}
|
||||
|
||||
var sessionPool = sync.Pool{
|
||||
|
@ -29,6 +31,9 @@ func acquireSession() *Session {
|
|||
if s.data == nil {
|
||||
s.data = acquireData()
|
||||
}
|
||||
if s.byteBuffer == nil {
|
||||
s.byteBuffer = new(bytes.Buffer)
|
||||
}
|
||||
s.fresh = true
|
||||
return s
|
||||
}
|
||||
|
@ -40,6 +45,9 @@ func releaseSession(s *Session) {
|
|||
if s.data != nil {
|
||||
s.data.Reset()
|
||||
}
|
||||
if s.byteBuffer != nil {
|
||||
s.byteBuffer.Reset()
|
||||
}
|
||||
sessionPool.Put(s)
|
||||
}
|
||||
|
||||
|
@ -134,11 +142,15 @@ func (s *Session) Save() error {
|
|||
|
||||
// Convert data to bytes
|
||||
mux.Lock()
|
||||
data := gotiny.Marshal(&s.data)
|
||||
encCache := gob.NewEncoder(s.byteBuffer)
|
||||
err := encCache.Encode(&s.data.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mux.Unlock()
|
||||
|
||||
// pass raw bytes with session id to provider
|
||||
if err := s.config.Storage.Set(s.id, data, s.config.Expiration); err != nil {
|
||||
if err := s.config.Storage.Set(s.id, s.byteBuffer.Bytes(), s.config.Expiration); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,7 @@ func Test_Session_Types(t *testing.T) {
|
|||
type User struct {
|
||||
Name string
|
||||
}
|
||||
store.RegisterType(User{})
|
||||
var vuser = User{
|
||||
Name: "John",
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"sync"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/internal/gotiny"
|
||||
"github.com/gofiber/fiber/v2/internal/storage/memory"
|
||||
"github.com/gofiber/fiber/v2/utils"
|
||||
"github.com/valyala/fasthttp"
|
||||
|
@ -32,7 +32,7 @@ func New(config ...Config) *Store {
|
|||
// RegisterType will allow you to encode/decode custom types
|
||||
// into any Storage provider
|
||||
func (s *Store) RegisterType(i interface{}) {
|
||||
gotiny.Register(i)
|
||||
gob.Register(i)
|
||||
}
|
||||
|
||||
// Get will get/create a session
|
||||
|
@ -70,7 +70,12 @@ func (s *Store) Get(c *fiber.Ctx) (*Session, error) {
|
|||
// Unmashal if we found data
|
||||
if raw != nil && err == nil {
|
||||
mux.Lock()
|
||||
gotiny.Unmarshal(raw, &sess.data)
|
||||
_, _ = sess.byteBuffer.Write(raw)
|
||||
encCache := gob.NewDecoder(sess.byteBuffer)
|
||||
err := encCache.Decode(&sess.data.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mux.Unlock()
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
|
|
Loading…
Reference in New Issue