redefiniendo el builder

packs2
DEV 3 years ago
parent 63f83a353b
commit 0d97e820e4

@ -0,0 +1,40 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name bin_encoder.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// 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 js
type (
binEncoder interface {
EncodedLen (size int) int
Encode(dst, src []byte)
}
binEncoderWriter interface {
Write ([]byte) (int,error)
}
)

@ -33,15 +33,19 @@ const (
FlagOmitEmpty Flags = 1 << iota
FlagQuote
FlagScapeHTML
FlagBinary
FlagBinary64 Flags = 0b0000100000000000
FlagBinary32 Flags = 0b0000010000000000
FlagDateRFC822 Flags = 0b0001000000000000
FlagDateUnix Flags = 0b0010000000000000
FlagDateANSIC Flags = 0b0100000000000000
FlagDateRFC850 Flags = 0b1000000000000000
binMask = 0b0000110000000000
dateMask = 0b1111000000000000
flagMask Flags = 0b0000111111111111
flagMaskBin Flags = 0b1111001111111111
flagMaskDate Flags = 0b0000111111111111
)
@ -62,24 +66,34 @@ func (f Flags) EscapeHTML () bool {
}
func (f Flags) Binary () bool {
return f&FlagBinary != 0
return f&(FlagBinary64|FlagBinary32) != 0
}
func (f Flags) Bin64 () bool {
return f&FlagBinary64 != 0
}
func (f Flags) Bin32 () bool {
return f&FlagBinary32 != 0
}
func (f Flags) SetWithName(flag string) Flags {
switch strings.ToLower(flag) {
case "o","omitempty": return f | FlagOmitEmpty
case "q","quote" : return f | FlagQuote
case "b","binary" : return f | FlagBinary
case "h","html" : return f | FlagScapeHTML
case "b64","bin64" : return (f & flagMaskBin) | FlagBinary64
case "b32","bin32" : return (f & flagMaskBin) | FlagBinary32
// formatos de fechas
case "unix" : return (f & flagMask) | FlagDateUnix
case "rfc822" : return (f & flagMask) | FlagDateRFC822
case "ansic" : return (f & flagMask) | FlagDateANSIC
case "rfc850" : return (f & flagMask) | FlagDateRFC850
case "rfc822z": return f & flagMask
case "unix" : return (f & flagMaskDate) | FlagDateUnix
case "rfc822" : return (f & flagMaskDate) | FlagDateRFC822
case "ansic" : return (f & flagMaskDate) | FlagDateANSIC
case "rfc850" : return (f & flagMaskDate) | FlagDateRFC850
case "rfc822z": return f & flagMaskDate
default: return f
}
@ -93,15 +107,17 @@ func (f Flags) SetWithNames(flags ... string) Flags {
switch strings.ToLower(n) {
case "o","omitempty": nf |= FlagOmitEmpty
case "q","quote" : nf |= FlagQuote
case "b","binary" : nf |= FlagBinary
case "h","html" : nf |= FlagScapeHTML
case "b32","bin32" : nf = (nf & flagMaskBin) | FlagBinary32
case "b64","bin64" : nf = (nf & flagMaskBin) | FlagBinary64
// formatos de fechas
case "unix" : nf = (nf & flagMask) | FlagDateUnix
case "rfc822" : nf = (nf & flagMask) | FlagDateRFC822
case "ansic" : nf = (nf & flagMask) | FlagDateANSIC
case "rfc850" : nf = (nf & flagMask) | FlagDateRFC850
case "rfc822z": nf &= flagMask
case "unix" : nf = (nf & flagMaskDate) | FlagDateUnix
case "rfc822" : nf = (nf & flagMaskDate) | FlagDateRFC822
case "ansic" : nf = (nf & flagMaskDate) | FlagDateANSIC
case "rfc850" : nf = (nf & flagMaskDate) | FlagDateRFC850
case "rfc822z": nf &= flagMaskDate
}
}
return nf
@ -127,7 +143,9 @@ func (f Flags) Names () string {
if f&FlagOmitEmpty != 0 { ls = append(ls,"omitempty")}
if f&FlagQuote != 0 { ls = append(ls,"quote")}
if f&FlagScapeHTML != 0 { ls = append(ls,"html")}
if f&FlagBinary != 0 { ls = append(ls,"binary")}
if f&flagMaskBin != 0 {
ls = append(ls,f.binName())
}
if f&dateMask != 0 {
ls = append(ls,f.DateName())
}
@ -137,6 +155,14 @@ func (f Flags) Names () string {
return ""
}
func (f Flags) binName () string {
switch f & binMask {
case FlagBinary64 : return "b64"
case FlagBinary32 : return "b32"
}
return ""
}
func (f Flags) DateName () string {
switch f & dateMask {

@ -25,8 +25,12 @@ package js
import (
"activething.com/go/gogo/packs"
"encoding/base32"
"encoding/base64"
"encoding/json"
"io"
"math"
"reflect"
"strconv"
"time"
"unicode/utf8"
@ -34,7 +38,85 @@ import (
func packAny (state *packs.State, value any , flags Flags) {}
func pack (state *packs.State, value any , flags Flags) {
if state.Error != nil {
panic(state.Error)
}
if value == nil {
if flags.Quote() {
state.WriteByte('"')
}
_,_ = state.Write(G.nullValue)
if flags.Quote() {
state.WriteByte('"')
}
return
}
switch v := value.(type) {
case bool : packBool (state,v,flags)
case string : packString(state,v,flags)
case uint : packUInt(state,uint64(v),flags)
case uint8 : packUInt(state,uint64(v),flags)
case uint16 : packUInt(state,uint64(v),flags)
case uint32 : packUInt(state,uint64(v),flags)
case uint64 : packUInt(state,v,flags)
case int : packInt(state,int64(v),flags)
case int8 : packInt(state,int64(v),flags)
case int16 : packInt(state,int64(v),flags)
case int32 : packInt(state,int64(v),flags)
case int64 : packInt(state,v,flags)
case float32: packFloat(state,float64(v),flags)
case float64: packFloat(state,v,flags)
case time.Time : PackDate(v)
case reflect.Value : Pack(v.Elem())
default:
if pb,is := value.(packs.Packabler); is {
d, e := pb.Build(p)
if state.SetError(e) {
return
}
_, _ = state.Write(d)
return
}
if ms,is := value.(json.Marshaler); is {
d,e := ms.MarshalJSON()
if state.SetError(e) {
return
}
_,_ = state.Write(d)
return
}
rv := reflect.ValueOf(value)
switch rv.Kind() {
case reflect.Slice, reflect.Array:
packListReflected(rv)
case reflect.Map:
packMapReflected(rv)
case reflect.Struct:
packObjectReflected(rv)
default:
d,e := options.encoder.Encode(value)
if e != nil {
state.SetError(e)
return
}
state.Write(d)
}
}
}
func packString (state *packs.State, value string , flags Flags) {
if state.Error != nil {
@ -102,7 +184,8 @@ func packString (state *packs.State, value string , flags Flags) {
}
func packBinary (state *packs.State, value []byte , _ Flags) {
func packBinary (state *packs.State, value []byte , f Flags) {
if state.Error != nil {
panic(state.Error)
}
@ -116,25 +199,41 @@ func packBinary (state *packs.State, value []byte , _ Flags) {
return
}
state.WriteByte('"')
ln := base64.StdEncoding.EncodedLen(len(value))
var ec binEncoder = base64.StdEncoding
if f.Bin32() {
ec = base32.StdEncoding
}
ln := ec.EncodedLen(len(value))
if ln <= len(state.Temp) {
dst := state.Temp[:ln]
base64.StdEncoding.Encode(dst, value)
ec.Encode(dst, value)
_,_= state.Write(dst)
} else if ln <= 1024 {
dst := make([]byte, ln)
base64.StdEncoding.Encode(dst, value)
ec.Encode(dst, value)
_,_ = state.Write(dst)
} else {
enc := base64.NewEncoder(base64.StdEncoding, state)
_,_ = enc.Write(value)
state.SetError(enc.Close())
var wc io.WriteCloser
if f.Bin32() {
wc = base32.NewEncoder(base32.StdEncoding, state)
} else if f.Bin64() {
wc = base64.NewEncoder(base64.StdEncoding, state)
} else {
state.SetError(packs.G.ErrUnsupportedType)
return
}
_,_ = wc.Write(value)
state.SetError(wc.Close())
return
}
state.WriteByte('"')
}
func packBool (state *packs.State, value bool , flags Flags) {
if state.Error != nil {
panic(state.Error)

@ -43,7 +43,7 @@ type (
func newRMap (rtype reflect.Type) *rMap {
return &rMap{
valFn : typePacker(rtype.Elem()),
valFn : rTypePacker(rtype.Elem()),
keyFn : stringifyRKey(rtype.Key()),
}
}

@ -26,6 +26,7 @@ package js
import (
"activething.com/go/gogo/packs"
"reflect"
"sync"
)
type (
@ -34,7 +35,6 @@ type (
}
packerFn func (state *packs.State, value reflect.Value, flags Flags)
)
@ -45,16 +45,33 @@ type (
func RPacker(state *packs.State, value any, flags Flags ) {
v := reflect.ValueOf(value)
t := v.Type()
typePacker(t)(state,v,flags)
rTypePacker(t)(state,v,flags)
}
func typePacker (rtype reflect.Type) packerFn {
fn,ok := G.packers.Load(rtype)
if !ok {
fn,_ = G.packers.LoadOrStore(rtype, _rTypePacker(rtype))
}
func rTypePacker(rtype reflect.Type) packerFn {
if fn,ok := G.packers.Load(rtype); ok {
return fn.(packerFn)
}
var wg sync.WaitGroup
var fn packerFn
wg.Add(1)
fi,ld := G.packers.LoadOrStore(rtype, packerFn(func (e *packs.State, v reflect.Value, f Flags) {
wg.Wait()
fn(e,v,f)
}))
if ld {
return fi.(packerFn)
}
fn = _rTypePacker(rtype)
wg.Done()
G.packers.Store(rtype,fn)
return fn
}
@ -78,21 +95,15 @@ func _rTypePacker(t reflect.Type) packerFn {
case reflect.Slice,
reflect.Array :
return (rList{ valFn: typePacker(t.Elem()) }).pack
return (rList{ valFn: rTypePacker(t.Elem()) }).pack
case reflect.Map :
return newRMap(t).pack
}
return func (s *packs.State, v reflect.Value, _ Flags) { unsupportedTypePacker(s,v,0)}
return unsupportedTypePacker
}
func unsupportedTypePacker(state *packs.State, _ reflect.Value, _ Flags) {
state.SetError(packs.G.ErrUnsupportedType)
}

Loading…
Cancel
Save

Powered by TurnKey Linux.