You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

382 lines
12 KiB

// ------------------------------------------------------------------------
// 🚀 Project active3
// 🔗 Active Thing (activething.com) git.activething.com/go
//
// File name packer.go
// ✍️ Created by DEV
// 📅 Modified 30/05/2024
//
// 🔒 Copyright 2024 activething.com
//
// 📜 LICENSE --------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package pkjson
import (
"apacks"
"apacks/pkstate"
"blds"
"cdcs/cjson"
"core/tups"
"encoding/json"
"reflect"
"sort"
"sync"
"time"
)
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 (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(pkstate.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(pkstate.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]
if hs {
p.mux.RUnlock()
return fn
}
for _,i := range p.ifcs {
if fn = i(rtype); fn != nil {
break
}
}
p.mux.RUnlock()
if fn == nil {
fn = p.buildRPacker(rtype)
}
p.mux.Lock()
p.fncs[rtype]=fn
p.mux.Unlock()
return fn
}
func (p *rpackers) buildRPacker (rtype reflect.Type) rPackFnc {
switch rtype.Kind() {
case reflect.Pointer:
eleFn := p.getRPacker(rtype.Elem())
return func(b *Builder, v reflect.Value) {
if v.IsNil() {
if !b.preValue() {
return
}
b.B.W(cjson.G.NullValue)
b.postValue()
return
}
b.Level++
if b.Level > maxCyclesAfter {
if fn,ok := b.CheckCycle(v.Interface()); ok {
defer fn()
} else {
return
}
}
eleFn(b,v.Elem())
b.Level--
}
case reflect.Interface:
return func(b *Builder, v reflect.Value) {
if v.IsNil() {
if !b.preValue() {
return
}
b.B.W(cjson.G.NullValue)
b.postValue()
return
}
p.getRPacker(v.Elem().Type())(b,v.Elem())
}
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(pkstate.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.getRStringer(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++ {
rs := kfn(mi.Key())
if !rs.Ok() {
b.SetError(apack.G.ErrInvalidKey.WithCause(rs.Fail()))
return
}
ls[i]=tups.GTuple[string,reflect.Value]{
A : rs.Value(),
B : mi.Value(),
}
}
sort.Slice(ls,func(i,j int) bool {
return ls[i].A < ls[j].A
})
b.buildLevel(pkstate.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 (*newRObject(rtype)).pack
default:
return func(b *Builder, v reflect.Value) {
b.SetError(apack.G.ErrInvalidValue) }
}
}

Powered by TurnKey Linux.