pack reestructurado terminado

master
DEV 2 years ago
parent 05afeda60e
commit e637d6752e

@ -2,7 +2,7 @@ package main
import (
"apack/pkj"
"blds"
"errs"
"fmt"
"math/rand"
"time"
@ -25,11 +25,13 @@ func randomInt(min, max int) int {
return rand.Intn(max-min+1) + min
}
/*
func (s S) Build (b blds.Builder) {
b.String("Esto es un campo S")
}
*/
func main() {
@ -62,21 +64,47 @@ func main() {
r := p.Pack(myMap)
if !r.Ok() {
fmt.Printf("%s \n",string(errs.Encode(r.Fail(), eftext.Formatter())))
fmt.Printf("%s \n",string(errs.Format(r.Fail(), eftext.Formatter())))
return
}
fmt.Printf("Data\n\n%s",string(r.Value()))
*/
//l := []int {1,2,3,4}
//m := map[string]error {"1" : fmt.Errorf("un Error %s","ww"), "443" : fmt.Errorf("otro Error %s","des"),"UnoNulo":nil, "null":nil}
*/
b := pkj.NewBuilder()
r := b.Pack(S{ A : "SOOOOOO"})
//r := b.Pack(S{ A : "SOOOOOO"})
r := b.Pack(
map[interface{}]interface{}{
//1: "uno",
"dos": 2,
3.0: true,
true: 4.5,
"cinco": "seis",
7: 8,
"nueve": false,
10.11: "doce",
false: 13,
"catorce": 15.16,
"dfate": time.Now(),
time.Now(): "ff",
"SSSS" : S{A:"a"},
},
)
if !r.Ok() {
fmt.Printf("ERROR %s\n",r.Fail())
fmt.Printf("ERROR %s\n",errs.Format(r.Fail(),nil))
return
}
fmt.Printf("Data\n\n%s\n",string(r.Value()))

@ -249,7 +249,11 @@ func (b *Builder) String (value string) {
b.postValue()
}
func (b *Builder) Bool (value bool) {}
func (b *Builder) Bool (value bool) {
if !b.preValue() { return }
cjson.WriteBool(b.B,value)
b.postValue()
}
func (b *Builder) Int (value int ){ b.Int64(int64(value)) }
func (b *Builder) Int8 (value int8 ){ b.Int64(int64(value)) }
@ -409,7 +413,12 @@ func (b *Builder) Key (key any) blds.ValueBuilder {
b.SetError(apack.G.ErrInvalidKey.WithMessage("key is null"))
return b
}
return b.Field(g.stringer.getStringer(key))
rs := g.stringer.getStringer(key)
if !rs.Ok() {
b.SetError(apack.G.ErrInvalidKey.WithCause(rs.Fail()))
return b
}
return b.Field(rs.Value())
}
func (b *Builder) Field (name string) blds.ValueBuilder {

@ -312,7 +312,7 @@ func (p *rpackers) buildRPacker (rtype reflect.Type) rPackFnc {
}
case reflect.Map :
kfn := g.stringer.getStringer(rtype.Key())
kfn := g.stringer.getRStringer(rtype.Key())
if kfn == nil {
return func(b *Builder, _ reflect.Value) {
b.SetError(apack.G.ErrInvalidKey)
@ -333,8 +333,13 @@ func (p *rpackers) buildRPacker (rtype reflect.Type) rPackFnc {
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 : kfn(mi.Key()),
A : rs.Value(),
B : mi.Value(),
}
}
@ -358,7 +363,7 @@ func (p *rpackers) buildRPacker (rtype reflect.Type) rPackFnc {
case reflect.Struct :
return nil
return (*newRObject(rtype)).pack
default:

@ -0,0 +1,60 @@
// ------------------------------------------------------------------------
// 🚀 Project active3
// 🔗 Active Thing (activething.com) git.activething.com/go
//
// File name rfield.go
// ✍️ Created by DEV
// 📅 Modified 12/06/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 pkj
import (
"apack"
"reflect"
)
type (
rField struct {
name string
nameUns string
nameHtm string
nameBin []byte
isTagged bool
index []int
rtype reflect.Type
flags apack.Flags
foldFn apack.FoldFnc
packFn func(b *Builder, v reflect.Value)
}
)
func (f rField) typeByIndex (rtype reflect.Type) reflect.Type {
for _,i:= range f.index {
if rtype.Kind() == reflect.Pointer {
rtype = rtype.Elem()
}
rtype = rtype.Field(i).Type
}
return rtype
}

@ -0,0 +1,60 @@
// ------------------------------------------------------------------------
// 🚀 Project active3
// 🔗 Active Thing (activething.com) git.activething.com/go
//
// File name rfields.go
// ✍️ Created by DEV
// 📅 Modified 12/06/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 pkj
type rFields []rField
func (l rFields) dominant () (rField,bool) {
if len(l) > 1 && len(l[0].index) == len(l[1].index) && l[0].isTagged == l[1].isTagged {
return rField{},false
}
return l[0],true
}
func (l rFields) Len() int { return len(l) }
func (l rFields) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l rFields) Less(i, j int) bool {
for k, xik := range l[i].index {
if k >= len(l[j].index) {
return false
}
if xik != l[j].index[k] {
return xik < l[j].index[k]
}
}
return len(l[i].index) < len(l[j].index)
}

@ -0,0 +1,275 @@
// ------------------------------------------------------------------------
// 🚀 Project active3
// 🔗 Active Thing (activething.com) git.activething.com/go
//
// File name rstruct.go
// ✍️ Created by DEV
// 📅 Modified 12/06/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 pkj
import (
"apack"
"bfrs"
"reflect"
"sort"
)
type (
rObject struct {
fields rFields
idxs map[string]int
}
)
func newRObject (rtype reflect.Type) *rObject {
var (
cur = rFields{}
nxt = rFields{{ rtype : rtype }}
vis = map[reflect.Type]bool{}
nms = bfrs.NewABuffer()
fls rFields
cnt,nxCnt map[reflect.Type]int
)
for len(nxt) > 0 {
cur,nxt = nxt, cur[:0]
cnt,nxCnt = nxCnt,map[reflect.Type]int{}
for _,f := range cur {
if vis[f.rtype] {
continue
}
vis[f.rtype]=true
for i:=0; i<f.rtype.NumField(); i++ {
sf := f.rtype.Field(i)
if sf.Anonymous {
tp := sf.Type
if tp.Kind() == reflect.Pointer {
tp = tp.Elem()
}
if !sf.IsExported() && tp.Kind() != reflect.Struct {
continue
}
} else if !sf.IsExported() {
continue
}
nm,fg, has := apack.FlagsFromPackTag(sf.Tag)
if !has {
nm,fg,has = jsonTags(sf.Tag)
}
if has {
if nm == "-" || fg.OmitEmpty() {
continue
}
if !apack.CheckTag(nm) {
nm = ""
}
}
index := make([]int,len(f.index)+1)
copy(index,f.index)
index[len(f.index)] = i
ft := sf.Type
if ft.Name() == "" && ft.Kind() == reflect.Pointer {
ft = ft.Elem()
}
if fg.String() && !fg.Quote() {
switch ft.Kind() {
case reflect.Bool,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
reflect.Float32, reflect.Float64,
reflect.String:
fg = fg| apack.FlagQuote
}
}
if nm != "" || sf.Anonymous || ft.Kind() != reflect.Struct {
tged := nm != ""
if nm == "" {
nm = sf.Name
}
of := rField{
name : nm,
isTagged: tged,
index: index,
rtype: ft,
flags: fg,
}
of.nameBin = []byte(of.name)
of.foldFn = apack.GetFoldFunc(of.nameBin)
// BuildPack nameEscHTML and nameNonEsc ahead of time.
nms.Reset()
nms.WriteByte('"')
nms.WriteHTML(of.nameBin)
nms.Write2Byte('"',':')
of.name = nms.String()
of.nameUns = `"` + of.name + `":`
fls = append(fls,of)
if cnt[f.rtype] > 1 {
fls = append(fls,fls[len(fls)-1])
}
continue
}
nxCnt[ft]++
if nxCnt[ft] == 1 {
nxt = append(nxt,rField{ name: ft.Name(), index: index, rtype: ft})
}
}
}
}
sort.Slice(fls,func(i,j int) bool {
ls := fls
if ls[i].name != ls[j].name {
return ls[i].name < ls[j].name
}
if len(ls[i].index) != len(ls[j].index) {
return len(ls[i].index) < len(ls[j].index)
}
if ls[i].isTagged != ls[j].isTagged {
return ls[i].isTagged
}
return ls.Less(i, j)
})
out := fls[:0]
for ad,i :=0,0; i< len(fls); i += ad {
fi := fls[i]
nm := fi.name
for ad=1; i+ad <len(fls); ad++ {
fj := fls[i+ad]
if fj.name != nm {
break
}
}
if ad == 1 {
out = append(out,fi)
continue
}
do,ok := fls[i:i+ad].dominant()
if ok {
out = append(out,do)
}
}
fls = out
sort.Sort(fls)
for i:= range fls {
f := &fls[i]
f.packFn = g.rpackers.getRPacker(f.typeByIndex(rtype))
}
nmIdx := make(map[string]int,len(fls))
for i,fd := range fls {
nmIdx[fd.name]=i
}
return &rObject{
fields : fls,
idxs: nmIdx,
}
}
func (o rObject) pack (b *Builder, v reflect.Value) {
nx := byte('{')
FieldLoop:
for i:= range o.fields {
fd := &o.fields[i]
fv := v
for _,i := range fd.index {
if fv.Kind() == reflect.Pointer {
if fv.IsNil() {
continue FieldLoop
}
fv = fv.Elem()
}
fv = fv.Field(i)
}
if fd.flags.OmitEmpty() && isEmptyValue(v) {
continue
}
b.B.WriteByte(nx)
nx = ','
if fd.flags.EscapeHTML() {
b.B.WriteString(fd.nameHtm)
} else {
b.B.WriteString(fd.nameUns)
}
fd.packFn(b,fv)
}
if nx == '{' {
b.B.Write2Byte('{','}')
} else {
b.B.WriteByte('}')
}
}
func jsonTags (tag reflect.StructTag) (string,apack.Flags,bool) {
return apack.FlagsFromTag(tag,jsonTag,func(n string) apack.Flags {
switch n {
case "omitempty" : return apack.FlagOmitEmpty
case "quote" : return apack.FlagQuote
default : return 0
}
})
}
func isEmptyValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Pointer:
return v.IsNil()
default:
return false
}
}

@ -25,7 +25,12 @@
package pkj
import (
"apack"
"cdcs/cjson"
"encoding"
"encoding/json"
"reflect"
"rsls"
"strconv"
"sync"
"time"
@ -42,33 +47,71 @@ type (
stringersFnc func (s *stringers)
stringerFnc func (b *Builder, v reflect.Value) string
stringerFnc func (v reflect.Value) rsls.String
)
func newStringers (options ...stringersFnc) *stringers {
ifcs := []func(t reflect.Type) stringerFnc {
func(r reflect.Type) stringerFnc {
if r.Implements(reflect.TypeOf((*stringify)(nil)).Elem()) {
return func(v reflect.Value) rsls.String {
if v.Kind() == reflect.Pointer && v.IsNil() {
return rsls.MakeStringError(apack.G.ErrInvalidKey)
}
return rsls.StringSuccess((v.Interface().(stringify)).String())
}
}
return nil
},
func(r reflect.Type) stringerFnc {
if r.Implements(reflect.TypeOf((*json.Marshaler)(nil)).Elem()) {
return func(v reflect.Value) rsls.String {
if v.Kind() == reflect.Pointer && v.IsNil() {
return rsls.MakeStringError(apack.G.ErrInvalidKey)
}
tx,er := (v.Interface().(encoding.TextMarshaler)).MarshalText()
if er == nil {
return rsls.StringSuccess(tx)
}
return rsls.MakeStringError(er)
}
}
return nil
},
}
fncs := map[reflect.Type]stringerFnc {
reflect.TypeOf("") : func(b *Builder, v reflect.Value) string {
return v.String() },
reflect.TypeOf(int (0)) : func(b *Builder, v reflect.Value) string { return strconv.FormatInt (v.Int (),10) },
reflect.TypeOf(int8 (0)) : func(b *Builder, v reflect.Value) string { return strconv.FormatInt (v.Int (),10) },
reflect.TypeOf(int16 (0)) : func(b *Builder, v reflect.Value) string { return strconv.FormatInt (v.Int (),10) },
reflect.TypeOf(int32 (0)) : func(b *Builder, v reflect.Value) string { return strconv.FormatInt (v.Int (),10) },
reflect.TypeOf(int64 (0)) : func(b *Builder, v reflect.Value) string { return strconv.FormatInt (v.Int (),10) },
reflect.TypeOf(uint (0)) : func(b *Builder, v reflect.Value) string { return strconv.FormatUint(v.Uint(),10) } ,
reflect.TypeOf(uint8 (0)) : func(b *Builder, v reflect.Value) string { return strconv.FormatUint(v.Uint(),10) },
reflect.TypeOf(uint16 (0)) : func(b *Builder, v reflect.Value) string { return strconv.FormatUint(v.Uint(),10) },
reflect.TypeOf(uint32 (0)) : func(b *Builder, v reflect.Value) string { return strconv.FormatUint(v.Uint(),10) },
reflect.TypeOf(uint64 (0)) : func(b *Builder, v reflect.Value) string { return strconv.FormatUint(v.Uint(),10) },
reflect.TypeOf(uintptr(0)) : func(b *Builder, v reflect.Value) string { return strconv.FormatUint(v.Uint(),10) },
reflect.TypeOf(time.Duration(0)): func(b *Builder, v reflect.Value) string {
return strconv.FormatInt (int64(v.Interface().(time.Duration)),10) },
}
s := &stringers{ fncs : fncs }
reflect.TypeOf("") : func(v reflect.Value) rsls.String { return rsls.StringSuccess(v.String()) },
reflect.TypeOf(false) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatBool(v.Bool())) },
reflect.TypeOf(int (0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatInt (v.Int (),10)) },
reflect.TypeOf(int8 (0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatInt (v.Int (),10)) },
reflect.TypeOf(int16 (0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatInt (v.Int (),10)) },
reflect.TypeOf(int32 (0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatInt (v.Int (),10)) },
reflect.TypeOf(int64 (0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatInt (v.Int (),10)) },
reflect.TypeOf(uint (0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatUint(v.Uint(),10)) } ,
reflect.TypeOf(uint8 (0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatUint(v.Uint(),10)) },
reflect.TypeOf(uint16 (0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatUint(v.Uint(),10)) },
reflect.TypeOf(uint32 (0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatUint(v.Uint(),10)) },
reflect.TypeOf(uint64 (0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatUint(v.Uint(),10)) },
reflect.TypeOf(uintptr(0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(strconv.FormatUint(v.Uint(),10)) },
reflect.TypeOf(float32(0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(cjson.JSONFloat(v.Float(),32)) },
reflect.TypeOf(float64(0)) : func(v reflect.Value) rsls.String { return rsls.StringSuccess(cjson.JSONFloat(v.Float(),64)) },
reflect.TypeOf(time.Duration(0)): func(v reflect.Value) rsls.String {
return rsls.StringSuccess(strconv.FormatInt (int64(v.Interface().(time.Duration)),10)) },
reflect.TypeOf(time.Time{}): func(v reflect.Value) rsls.String {
return rsls.StringSuccess(v.Interface().(time.Time).Format(time.RFC822Z))
},
}
s := &stringers{
fncs : fncs,
ifcs : ifcs,
}
for _,o := range options {
o(s)
}
@ -76,38 +119,61 @@ func newStringers (options ...stringersFnc) *stringers {
}
func (s *stringers) getStringer (b *Builder, key any) string {
func (s *stringers) getStringer (key any) rsls.String {
switch k := key.(type) {
case string : return k
case string : return rsls.StringSuccess(k)
default:
rv := reflect.ValueOf(key)
rv := reflect.ValueOf(key).Elem()
kf := s.getRStringer(rv.Type())
if kf != nil {
return kf(b,rv)
return kf(rv)
}
return rsls.MakeStringError(apack.G.ErrInvalidKey)
}
}
func (s *stringers) getRStringer (rtype reflect.Type) stringerFnc {
s.mux.RLock()
fn,ok := s.fncs[rtype]
if ok {
s.mux.RUnlock()
return fn
if rtype.Kind() == reflect.Interface {
return s.defaultStringer
}
for i:=0; i<len(s.ifcs); i++ {
s.mux.RLock()
fn,ok := s.fncs[rtype]
if !ok {
for i:= 0; i<len(s.ifcs); i++ {
if fn = s.ifcs[i](rtype); fn != nil {
break
}
}
}
s.mux.RUnlock()
if fn != nil {
return fn
}
return s.defaultStringer
}
func (s *stringers) defaultStringer(k reflect.Value) rsls.String {
if k.Kind() == reflect.Interface {
k = k.Elem()
}
fn := s.fncs[k.Type()]
if fn != nil {
return fn(k)
}
for i:=0; i<len(s.ifcs); i++ {
if fn = s.ifcs[i](k.Type()); fn != nil {
return fn(k)
}
}
return rsls.MakeStringError(apack.G.ErrInvalidKey.WithMessageF("%s", k.String()))
}

@ -60,7 +60,7 @@ func newKeyStringer (options...keyStringerFnc) *keyStringer {
func (s *keyStringer) packStringifyKey (b *Builder, key any) {
switch v := key.(type) {
case string : b.packString(v,apack.FlagScapeHTML)
case string : b.packString(v,apack.FlagScapeHTML)//
case bool : cjson.WriteBool (b.B,v)
case uint : cjson.WriteUint (b.B,uint64(v))
case uint8 : cjson.WriteUint (b.B,uint64(v))

@ -25,7 +25,7 @@
package errs
import (
"errs/efjson"
"errs/eftext"
"errs/stack"
"errs/wrap"
"fmt"
@ -61,7 +61,7 @@ var (
ErrParamNil : ErrCode(CodeParamNilError),
ErrParamOutOfRange : ErrCode(CodeParamOutOfRangeError),
Formatter : efjson.Formatter(),
Formatter : eftext.Formatter(),
}
)
@ -88,7 +88,7 @@ func ToError(err any) error {
func Encode(err error, encoder ErrorFormatter) string {
func Format(err error, encoder ErrorFormatter) string {
if encoder != nil {
return string(encoder.Format(err))
}

@ -62,8 +62,8 @@ func (s StringSuccess) Value() string {
// StringError -> Result, G.Result Implementation
func MakeStringError(cause error) IntError {
return IntError{cause} }
func MakeStringError(cause error) StringError {
return StringError{cause} }
func (e StringError) Ok() bool {
return false }

Loading…
Cancel
Save

Powered by TurnKey Linux.