|
|
|
|
@ -26,11 +26,15 @@ package pkj
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"apack"
|
|
|
|
|
"apack/pstate"
|
|
|
|
|
"blds"
|
|
|
|
|
"cdcs/cjson"
|
|
|
|
|
"core/tups"
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"reflect"
|
|
|
|
|
"sort"
|
|
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type (
|
|
|
|
|
@ -38,29 +42,183 @@ type (
|
|
|
|
|
rpackers struct {
|
|
|
|
|
mux sync.RWMutex
|
|
|
|
|
fncs map[reflect.Type]rPackFnc
|
|
|
|
|
ifcs []func(rtype reflect.Type) rPackFnc
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rpackersFnc func(p *rpackers)
|
|
|
|
|
|
|
|
|
|
rPackFnc func(b *Builder, v reflect.Value)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func newRPackers () *rpackers {
|
|
|
|
|
return &rpackers{
|
|
|
|
|
fncs : make(map[reflect.Type]rPackFnc),
|
|
|
|
|
func newRPackers (options ...rpackersFnc) *rpackers {
|
|
|
|
|
ib := reflect.TypeOf((*blds.Buildable)(nil)).Elem()
|
|
|
|
|
ij := reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
|
|
|
|
ie := reflect.TypeOf((*error)(nil)).Elem()
|
|
|
|
|
|
|
|
|
|
ifcs := []func(rt reflect.Type) rPackFnc {
|
|
|
|
|
// Buildable
|
|
|
|
|
func(t reflect.Type) rPackFnc {
|
|
|
|
|
if t.Implements(ib) {
|
|
|
|
|
return func(b *Builder, v reflect.Value) {
|
|
|
|
|
b.Buildable(v.Interface().(blds.Buildable))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
},
|
|
|
|
|
// jsonMarshaler
|
|
|
|
|
func(t reflect.Type) rPackFnc {
|
|
|
|
|
if t.Implements(ij) {
|
|
|
|
|
return func(b *Builder, v reflect.Value) {
|
|
|
|
|
b.Marshaller(v.Interface().(json.Marshaler))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
},
|
|
|
|
|
// error
|
|
|
|
|
func(t reflect.Type) rPackFnc {
|
|
|
|
|
if t.Implements(ie) {
|
|
|
|
|
return func(b *Builder, v reflect.Value) {
|
|
|
|
|
b.Error(v.Interface().(error))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fncs := map[reflect.Type]rPackFnc {
|
|
|
|
|
reflect.TypeOf("") : func(b *Builder, v reflect.Value) { b.String(v.String())},
|
|
|
|
|
reflect.TypeOf(false) : func(b *Builder, v reflect.Value) { b.Bool (v.Bool())},
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf(int (0)) : func(b *Builder, v reflect.Value) { b.Int64(v.Int()) },
|
|
|
|
|
reflect.TypeOf(int8 (0)) : func(b *Builder, v reflect.Value) { b.Int64(v.Int()) },
|
|
|
|
|
reflect.TypeOf(int16 (0)) : func(b *Builder, v reflect.Value) { b.Int64(v.Int()) },
|
|
|
|
|
reflect.TypeOf(int32 (0)) : func(b *Builder, v reflect.Value) { b.Int64(v.Int()) },
|
|
|
|
|
reflect.TypeOf(int64 (0)) : func(b *Builder, v reflect.Value) { b.Int64(v.Int()) },
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf(uint (0)) : func(b *Builder, v reflect.Value) { b.Uint64(v.Uint()) },
|
|
|
|
|
reflect.TypeOf(uint8 (0)) : func(b *Builder, v reflect.Value) { b.Uint64(v.Uint()) },
|
|
|
|
|
reflect.TypeOf(uint16(0)) : func(b *Builder, v reflect.Value) { b.Uint64(v.Uint()) },
|
|
|
|
|
reflect.TypeOf(uint32(0)) : func(b *Builder, v reflect.Value) { b.Uint64(v.Uint()) },
|
|
|
|
|
reflect.TypeOf(uint64(0)) : func(b *Builder, v reflect.Value) { b.Uint64(v.Uint()) },
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf(float32(0)) : func(b *Builder, v reflect.Value) { b.float(v.Float(),32)},
|
|
|
|
|
reflect.TypeOf(float64(0)) : func(b *Builder, v reflect.Value) { b.float(v.Float(),64)},
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf(time.Time{}) : func(b *Builder, v reflect.Value) { b.Time(v.Interface().(time.Time)) },
|
|
|
|
|
reflect.TypeOf(time.Duration(0)): func(b *Builder, v reflect.Value) { b.Duration(v.Interface().(time.Duration))},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf([]string(nil)) : func(b *Builder, v reflect.Value) { packListG[string ] (b,v.Interface().([]string ), b.String)},
|
|
|
|
|
reflect.TypeOf([]bool (nil)) : func(b *Builder, v reflect.Value) { packListG[bool ] (b,v.Interface().([]bool ), b.Bool) },
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf([]int (nil)) : func(b *Builder, v reflect.Value) { packListG[int ] (b,v.Interface().([]int ), b.Int) },
|
|
|
|
|
reflect.TypeOf([]int8 (nil)) : func(b *Builder, v reflect.Value) { packListG[int8 ] (b,v.Interface().([]int8 ), b.Int8) },
|
|
|
|
|
reflect.TypeOf([]int16 (nil)) : func(b *Builder, v reflect.Value) { packListG[int16 ] (b,v.Interface().([]int16 ), b.Int16) },
|
|
|
|
|
reflect.TypeOf([]int32 (nil)) : func(b *Builder, v reflect.Value) { packListG[int32 ] (b,v.Interface().([]int32 ), b.Int32) },
|
|
|
|
|
reflect.TypeOf([]int64 (nil)) : func(b *Builder, v reflect.Value) { packListG[int64 ] (b,v.Interface().([]int64 ), b.Int64) },
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf([]uint (nil)) : func(b *Builder, v reflect.Value) { packListG[uint ] (b,v.Interface().([]uint ), b.Uint) },
|
|
|
|
|
reflect.TypeOf([]uint8 (nil)) : func(b *Builder, v reflect.Value) { packListG[uint8 ] (b,v.Interface().([]uint8 ), b.Uint8) },
|
|
|
|
|
reflect.TypeOf([]uint16(nil)) : func(b *Builder, v reflect.Value) { packListG[uint16 ] (b,v.Interface().([]uint16 ), b.Uint16)},
|
|
|
|
|
reflect.TypeOf([]uint32(nil)) : func(b *Builder, v reflect.Value) { packListG[uint32 ] (b,v.Interface().([]uint32 ), b.Uint32)},
|
|
|
|
|
reflect.TypeOf([]uint64(nil)) : func(b *Builder, v reflect.Value) { packListG[uint64 ] (b,v.Interface().([]uint64 ), b.Uint64)},
|
|
|
|
|
reflect.TypeOf([]uintptr(nil)): func(b *Builder, v reflect.Value) { packListG[uintptr] (b,v.Interface().([]uintptr), b.Uintptr)},
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf([]float32(nil)): func(b *Builder, v reflect.Value) { packListG[float32] (b,v.Interface().([]float32), b.Float32)},
|
|
|
|
|
reflect.TypeOf([]float64(nil)): func(b *Builder, v reflect.Value) { packListG[float64] (b,v.Interface().([]float64), b.Float64)},
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf([]time.Time (nil)): func(b *Builder, v reflect.Value) { packListG[time.Time ] (b,v.Interface().([]time.Time) , b.Time)},
|
|
|
|
|
reflect.TypeOf([]time.Duration(nil)): func(b *Builder, v reflect.Value) { packListG[time.Duration] (b,v.Interface().([]time.Duration), b.Duration)},
|
|
|
|
|
reflect.TypeOf([]error(nil)) : func(b *Builder, v reflect.Value) {
|
|
|
|
|
var l []error
|
|
|
|
|
if !v.IsNil() {
|
|
|
|
|
l = v.Interface().([]error)
|
|
|
|
|
}
|
|
|
|
|
b.buildLevel(pstate.ModeList, l == nil, len(l) == 0, func(bl *Builder) {
|
|
|
|
|
for _, e := range l {
|
|
|
|
|
bl.Item()
|
|
|
|
|
if bl.Err == nil {
|
|
|
|
|
bl.Error(e)
|
|
|
|
|
}
|
|
|
|
|
if bl.Err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf(map[string]string(nil)) : func(b *Builder, v reflect.Value) { packMapG[string ] (b,v.Interface().(map[string]string ), b.String)},
|
|
|
|
|
reflect.TypeOf(map[string]bool (nil)) : func(b *Builder, v reflect.Value) { packMapG[bool ] (b,v.Interface().(map[string]bool ), b.Bool) },
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf(map[string]int (nil)) : func(b *Builder, v reflect.Value) { packMapG[int ] (b,v.Interface().(map[string]int ), b.Int) },
|
|
|
|
|
reflect.TypeOf(map[string]int8 (nil)) : func(b *Builder, v reflect.Value) { packMapG[int8 ] (b,v.Interface().(map[string]int8 ), b.Int8) },
|
|
|
|
|
reflect.TypeOf(map[string]int16 (nil)) : func(b *Builder, v reflect.Value) { packMapG[int16 ] (b,v.Interface().(map[string]int16 ), b.Int16) },
|
|
|
|
|
reflect.TypeOf(map[string]int32 (nil)) : func(b *Builder, v reflect.Value) { packMapG[int32 ] (b,v.Interface().(map[string]int32 ), b.Int32) },
|
|
|
|
|
reflect.TypeOf(map[string]int64 (nil)) : func(b *Builder, v reflect.Value) { packMapG[int64 ] (b,v.Interface().(map[string]int64 ), b.Int64) },
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf(map[string]uint (nil)) : func(b *Builder, v reflect.Value) { packMapG[uint ] (b,v.Interface().(map[string]uint ), b.Uint) },
|
|
|
|
|
reflect.TypeOf(map[string]uint8 (nil)) : func(b *Builder, v reflect.Value) { packMapG[uint8 ] (b,v.Interface().(map[string]uint8 ), b.Uint8) },
|
|
|
|
|
reflect.TypeOf(map[string]uint16(nil)) : func(b *Builder, v reflect.Value) { packMapG[uint16 ] (b,v.Interface().(map[string]uint16 ), b.Uint16)},
|
|
|
|
|
reflect.TypeOf(map[string]uint32(nil)) : func(b *Builder, v reflect.Value) { packMapG[uint32 ] (b,v.Interface().(map[string]uint32 ), b.Uint32)},
|
|
|
|
|
reflect.TypeOf(map[string]uint64(nil)) : func(b *Builder, v reflect.Value) { packMapG[uint64 ] (b,v.Interface().(map[string]uint64 ), b.Uint64)},
|
|
|
|
|
reflect.TypeOf(map[string]uintptr(nil)): func(b *Builder, v reflect.Value) { packMapG[uintptr] (b,v.Interface().(map[string]uintptr), b.Uintptr)},
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf(map[string]float32(nil)): func(b *Builder, v reflect.Value) { packMapG[float32] (b,v.Interface().(map[string]float32), b.Float32)},
|
|
|
|
|
reflect.TypeOf(map[string]float64(nil)): func(b *Builder, v reflect.Value) { packMapG[float64] (b,v.Interface().(map[string]float64), b.Float64)},
|
|
|
|
|
|
|
|
|
|
reflect.TypeOf(map[string]time.Time (nil)) : func(b *Builder, v reflect.Value) { packMapG[time.Time ] (b,v.Interface().(map[string]time.Time) , b.Time)},
|
|
|
|
|
reflect.TypeOf(map[string]time.Duration(nil)): func(b *Builder, v reflect.Value) { packMapG[time.Duration] (b,v.Interface().(map[string]time.Duration), b.Duration)},
|
|
|
|
|
reflect.TypeOf(map[string]error(nil)) : func(b *Builder, v reflect.Value) {
|
|
|
|
|
var l map[string]error
|
|
|
|
|
if !v.IsNil() {
|
|
|
|
|
l = v.Interface().(map[string]error)
|
|
|
|
|
}
|
|
|
|
|
b.buildLevel(pstate.ModeMap, l == nil, len(l) == 0, func(bl *Builder) {
|
|
|
|
|
for k,v := range l {
|
|
|
|
|
bl.Field(k)
|
|
|
|
|
if bl.Err == nil {
|
|
|
|
|
bl.Error(v)
|
|
|
|
|
}
|
|
|
|
|
if bl.Err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p := &rpackers{
|
|
|
|
|
fncs: fncs,
|
|
|
|
|
ifcs: ifcs,
|
|
|
|
|
}
|
|
|
|
|
for _,o := range options {
|
|
|
|
|
o(p)
|
|
|
|
|
}
|
|
|
|
|
return p
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *rpackers) getRPacker (rtype reflect.Type) rPackFnc {
|
|
|
|
|
p.mux.RLock()
|
|
|
|
|
fn, hs := p.fncs[rtype]
|
|
|
|
|
p.mux.RUnlock()
|
|
|
|
|
if hs {
|
|
|
|
|
p.mux.RUnlock()
|
|
|
|
|
return fn
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
for _,i := range p.ifcs {
|
|
|
|
|
if fn = i(rtype); fn != nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p.mux.RUnlock()
|
|
|
|
|
|
|
|
|
|
fn = p.buildRPacker(rtype)
|
|
|
|
|
if fn == nil {
|
|
|
|
|
fn = p.buildRPacker(rtype)
|
|
|
|
|
}
|
|
|
|
|
p.mux.Lock()
|
|
|
|
|
p.fncs[rtype]=fn
|
|
|
|
|
p.mux.Unlock()
|
|
|
|
|
@ -69,54 +227,12 @@ func (p *rpackers) getRPacker (rtype reflect.Type) rPackFnc {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *rpackers) buildRPacker (rtype reflect.Type) rPackFnc {
|
|
|
|
|
|
|
|
|
|
if rtype.Implements(g.buildableType) {
|
|
|
|
|
return func(b *Builder, v reflect.Value) {
|
|
|
|
|
b.Buildable(v.Interface().(blds.Buildable))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if rtype.Implements(g.jsonMarshalerType) {
|
|
|
|
|
return func(b *Builder, v reflect.Value) {
|
|
|
|
|
b.Marshaller(v.Interface().(json.Marshaler))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if rtype.Implements(g.errorType) {
|
|
|
|
|
return func(b *Builder, v reflect.Value) {
|
|
|
|
|
b.Error(v.Interface().(error)) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *rpackers) buildRPacker (rtype reflect.Type) rPackFnc {
|
|
|
|
|
|
|
|
|
|
switch rtype.Kind() {
|
|
|
|
|
|
|
|
|
|
case reflect.Bool:
|
|
|
|
|
return func(b *Builder, v reflect.Value) { b.Bool(v.Bool()) }
|
|
|
|
|
|
|
|
|
|
case reflect.String:
|
|
|
|
|
return func(b *Builder, v reflect.Value) { b.String(v.String()) }
|
|
|
|
|
|
|
|
|
|
case reflect.Int,
|
|
|
|
|
reflect.Int8,
|
|
|
|
|
reflect.Int16,
|
|
|
|
|
reflect.Int32,
|
|
|
|
|
reflect.Int64:
|
|
|
|
|
return func(b *Builder, v reflect.Value) { b.Int64(v.Int()) }
|
|
|
|
|
|
|
|
|
|
case reflect.Uint,
|
|
|
|
|
reflect.Uint8,
|
|
|
|
|
reflect.Uint16,
|
|
|
|
|
reflect.Uint32,
|
|
|
|
|
reflect.Uint64,
|
|
|
|
|
reflect.Uintptr:
|
|
|
|
|
return func(b *Builder, v reflect.Value) { b.Uint64(v.Uint()) }
|
|
|
|
|
|
|
|
|
|
case reflect.Float32:
|
|
|
|
|
return func(b *Builder, v reflect.Value) { b.float(v.Float(), 32) }
|
|
|
|
|
case reflect.Float64:
|
|
|
|
|
return func(b *Builder, v reflect.Value) { b.float(v.Float(), 64) }
|
|
|
|
|
|
|
|
|
|
case reflect.Pointer:
|
|
|
|
|
eleFn := p.getRPacker(rtype.Elem())
|
|
|
|
|
return func(b *Builder, v reflect.Value) {
|
|
|
|
|
@ -157,9 +273,92 @@ func (p *rpackers) buildRPacker (rtype reflect.Type) rPackFnc {
|
|
|
|
|
case reflect.Slice,
|
|
|
|
|
reflect.Array :
|
|
|
|
|
|
|
|
|
|
eleFn := p.getRPacker(rtype.Elem())
|
|
|
|
|
return func(b *Builder, v reflect.Value) {
|
|
|
|
|
if v.IsNil() {
|
|
|
|
|
if b.preValue() {
|
|
|
|
|
b.B.W(cjson.G.NullValue)
|
|
|
|
|
}
|
|
|
|
|
b.postValue()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if b.Level > maxCyclesAfter {
|
|
|
|
|
c := struct {
|
|
|
|
|
p any
|
|
|
|
|
l int
|
|
|
|
|
}{
|
|
|
|
|
p: v.UnsafePointer(),
|
|
|
|
|
l: v.Len(),
|
|
|
|
|
}
|
|
|
|
|
if fn,ok := b.CheckCycle(c); ok {
|
|
|
|
|
defer fn()
|
|
|
|
|
} else {
|
|
|
|
|
b.SetError(apack.G.ErrRedundantPack)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b.buildLevel(pstate.ModeList, false, v.Len() == 0, func(bl *Builder){
|
|
|
|
|
for i:=0; i<v.Len();i++ {
|
|
|
|
|
bl.Item()
|
|
|
|
|
eleFn(bl,v.Index(i))
|
|
|
|
|
if bl.Err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case reflect.Map :
|
|
|
|
|
kfn := g.stringer.getStringer(rtype.Key())
|
|
|
|
|
if kfn == nil {
|
|
|
|
|
return func(b *Builder, _ reflect.Value) {
|
|
|
|
|
b.SetError(apack.G.ErrInvalidKey)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
vfn := p.getRPacker(rtype.Elem())
|
|
|
|
|
|
|
|
|
|
return func(b *Builder, v reflect.Value) {
|
|
|
|
|
if b.Level > maxCyclesAfter {
|
|
|
|
|
if fn,ok := b.CheckCycle(v.UnsafePointer()); ok {
|
|
|
|
|
defer fn()
|
|
|
|
|
} else {
|
|
|
|
|
b.SetError(apack.G.ErrRedundantPack)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mi := v.MapRange()
|
|
|
|
|
ls := make([]tups.GTuple[string,reflect.Value],v.Len())
|
|
|
|
|
for i:=0; mi.Next(); i++ {
|
|
|
|
|
ls[i]=tups.GTuple[string,reflect.Value]{
|
|
|
|
|
A : kfn(mi.Key()),
|
|
|
|
|
B : mi.Value(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sort.Slice(ls,func(i,j int) bool {
|
|
|
|
|
return ls[i].A < ls[j].A
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
b.buildLevel(pstate.ModeMap,v.IsNil(),v.Len() == 0,func(bl *Builder){
|
|
|
|
|
for i:=0; i<len(ls); i++ {
|
|
|
|
|
bl.Field(ls[i].A)
|
|
|
|
|
if b.Err == nil {
|
|
|
|
|
vfn(bl,ls[i].B)
|
|
|
|
|
}
|
|
|
|
|
if b.Err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case reflect.Struct :
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
|
|
|