parent
4ef5088582
commit
8ff022c69a
@ -1,40 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name json_char_atts.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 18/01/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
|
|
||||||
|
|
||||||
const (
|
|
||||||
jsonCharAttUnsafe jsonCharAtt = 1 << iota
|
|
||||||
jsonCharAttHtmlUnsafe
|
|
||||||
|
|
||||||
jsonCharAttAllUnsafe = jsonCharAttUnsafe | jsonCharAttHtmlUnsafe
|
|
||||||
)
|
|
||||||
|
|
||||||
type jsonCharAtt uint8
|
|
||||||
|
|
||||||
func (a jsonCharAtt) isUnsafe() bool {
|
|
||||||
return a&jsonCharAttUnsafe != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a jsonCharAtt) isHtmlUnsafe() bool {
|
|
||||||
return a&jsonCharAttHtmlUnsafe != 0
|
|
||||||
}
|
|
||||||
@ -1,188 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name f.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 29/01/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
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
|
|
||||||
FlagOmitEmpty Flags = 1 << iota
|
|
||||||
FlagQuote
|
|
||||||
FlagScapeHTML
|
|
||||||
|
|
||||||
FlagBinary64 Flags = 0b0000100000000000
|
|
||||||
FlagBinary32 Flags = 0b0000010000000000
|
|
||||||
|
|
||||||
FlagDateRFC822 Flags = 0b0001000000000000
|
|
||||||
FlagDateUnix Flags = 0b0010000000000000
|
|
||||||
FlagDateANSIC Flags = 0b0100000000000000
|
|
||||||
FlagDateRFC850 Flags = 0b1000000000000000
|
|
||||||
|
|
||||||
binMask = 0b0000110000000000
|
|
||||||
dateMask = 0b1111000000000000
|
|
||||||
flagMaskBin Flags = 0b1111001111111111
|
|
||||||
flagMaskDate Flags = 0b0000111111111111
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
type Flags uint16
|
|
||||||
|
|
||||||
|
|
||||||
func (f Flags) OmitEmpty () bool {
|
|
||||||
return f&FlagOmitEmpty != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f Flags) Quote () bool {
|
|
||||||
return f&FlagQuote != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f Flags) EscapeHTML () bool {
|
|
||||||
return f&FlagScapeHTML != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f Flags) Binary () bool {
|
|
||||||
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 "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 & 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (f Flags) SetWithNames(flags ... string) Flags {
|
|
||||||
nf := f
|
|
||||||
for _,n := range flags {
|
|
||||||
switch strings.ToLower(n) {
|
|
||||||
case "o","omitempty": nf |= FlagOmitEmpty
|
|
||||||
case "q","quote" : nf |= FlagQuote
|
|
||||||
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 & 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
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f Flags) SetWithString (flags string) Flags {
|
|
||||||
if len(flags) == 0 {
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
nf := f
|
|
||||||
for flags != "" {
|
|
||||||
var op string
|
|
||||||
op,flags,_ = strings.Cut(flags,",")
|
|
||||||
nf |= f.SetWithName(op)
|
|
||||||
}
|
|
||||||
return nf
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (f Flags) Names () string {
|
|
||||||
var ls []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&flagMaskBin != 0 {
|
|
||||||
ls = append(ls,f.binName())
|
|
||||||
}
|
|
||||||
if f&dateMask != 0 {
|
|
||||||
ls = append(ls,f.DateName())
|
|
||||||
}
|
|
||||||
if len(ls) > 0 {
|
|
||||||
return strings.Join(ls,",")
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
case FlagDateUnix : return "unix"
|
|
||||||
case FlagDateRFC822: return "rfc822"
|
|
||||||
case FlagDateANSIC : return "ansic"
|
|
||||||
case FlagDateRFC850: return "rfc8550"
|
|
||||||
default: return time.RFC822Z
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func (f Flags) DateFormat () string {
|
|
||||||
switch f & dateMask {
|
|
||||||
case FlagDateUnix : return time.UnixDate
|
|
||||||
case FlagDateRFC822: return time.RFC822
|
|
||||||
case FlagDateANSIC : return time.ANSIC
|
|
||||||
case FlagDateRFC850: return time.RFC850
|
|
||||||
default: return time.RFC822Z
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,167 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name gogo.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 23/01/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
|
|
||||||
|
|
||||||
import (
|
|
||||||
"activething.com/go/gogo/packs"
|
|
||||||
"encoding"
|
|
||||||
"encoding/json"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
const startDetectingCyclesAfter = 100
|
|
||||||
|
|
||||||
var (
|
|
||||||
G = struct {
|
|
||||||
hex string
|
|
||||||
jsonChars [utf8.RuneSelf]jsonCharAtt
|
|
||||||
|
|
||||||
nullValue []byte
|
|
||||||
zeroValue []byte
|
|
||||||
trueValue []byte
|
|
||||||
falseValue []byte
|
|
||||||
|
|
||||||
floatNaN []byte
|
|
||||||
floatInfPos []byte
|
|
||||||
floatInfNeg []byte
|
|
||||||
|
|
||||||
|
|
||||||
packersCache sync.Map
|
|
||||||
keyersCache sync.Map
|
|
||||||
|
|
||||||
jsonMarshalerType reflect.Type
|
|
||||||
textMarshalerType reflect.Type
|
|
||||||
packMarshalerType reflect.Type
|
|
||||||
|
|
||||||
}{
|
|
||||||
|
|
||||||
hex: "0123456789abcdef",
|
|
||||||
jsonChars: initJSONChars(),
|
|
||||||
|
|
||||||
nullValue: []byte{'n', 'u', 'l', 'l'},
|
|
||||||
zeroValue: []byte{'0'},
|
|
||||||
trueValue: []byte{'"','t', 'r', 'u', 'e','"'},
|
|
||||||
falseValue: []byte{'"','f', 'a', 'l', 's', 'e','"'},
|
|
||||||
|
|
||||||
floatNaN: []byte{'"', 'N', 'a', 'N', '"'},
|
|
||||||
floatInfPos: []byte{'"', 'I', 'n', 'f', '"'},
|
|
||||||
floatInfNeg: []byte{'"', '-', 'I', 'n', 'f', '"'},
|
|
||||||
|
|
||||||
|
|
||||||
jsonMarshalerType: reflect.TypeOf((*json.Marshaler)(nil)).Elem(),
|
|
||||||
textMarshalerType: reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem(),
|
|
||||||
packMarshalerType: reflect.TypeOf((*packs.Packer)(nil)).Elem(),
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func initJSONChars() [utf8.RuneSelf]jsonCharAtt {
|
|
||||||
var tb = [utf8.RuneSelf]jsonCharAtt{
|
|
||||||
'"': jsonCharAttAllUnsafe,
|
|
||||||
'&': jsonCharAttHtmlUnsafe,
|
|
||||||
'<': jsonCharAttHtmlUnsafe,
|
|
||||||
'>': jsonCharAttHtmlUnsafe,
|
|
||||||
'\\': jsonCharAttAllUnsafe,
|
|
||||||
}
|
|
||||||
for i := 0; i <= 31; i++ {
|
|
||||||
tb[i] = jsonCharAttAllUnsafe
|
|
||||||
}
|
|
||||||
return tb
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func stringifyKey(buffer []byte, value any) []byte {
|
|
||||||
if value == nil {
|
|
||||||
return G.nullValue
|
|
||||||
}
|
|
||||||
|
|
||||||
if st,is := value.(string); is {
|
|
||||||
return append(buffer[:0],st...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if tm,is := value.(encoding.TextMarshaler); is {
|
|
||||||
if bf,er := tm.MarshalText(); er == nil {
|
|
||||||
return append(buffer[:0],bf...)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tp := value.(type) {
|
|
||||||
case bool:
|
|
||||||
if tp {
|
|
||||||
return G.trueValue
|
|
||||||
}
|
|
||||||
return G.falseValue
|
|
||||||
|
|
||||||
case int : return strconv.AppendInt (buffer[:0],int64(tp), 10)
|
|
||||||
case int8 : return strconv.AppendInt (buffer[:0],int64(tp), 10)
|
|
||||||
case int16 : return strconv.AppendInt (buffer[:0],int64(tp), 10)
|
|
||||||
case int32 : return strconv.AppendInt (buffer[:0],int64(tp), 10)
|
|
||||||
case int64 : return strconv.AppendInt (buffer[:0],tp, 10)
|
|
||||||
|
|
||||||
case uint : return strconv.AppendUint(buffer[:0],uint64(tp), 10)
|
|
||||||
case uint8 : return strconv.AppendUint(buffer[:0],uint64(tp), 10)
|
|
||||||
case uint16 : return strconv.AppendUint(buffer[:0],uint64(tp), 10)
|
|
||||||
case uint32 : return strconv.AppendUint(buffer[:0],uint64(tp), 10)
|
|
||||||
case uint64 : return strconv.AppendUint(buffer[:0],tp, 10)
|
|
||||||
|
|
||||||
case float32: return stringifyFloat(buffer[:0],float64(tp),32)
|
|
||||||
case float64: return stringifyFloat(buffer[:0],tp,64)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func stringifyFloat (buffer []byte, f float64, bits int) []byte {
|
|
||||||
if math.IsInf(f, 0) || math.IsNaN(f) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
abs := math.Abs(f)
|
|
||||||
fmt := byte('f')
|
|
||||||
|
|
||||||
if abs != 0 {
|
|
||||||
if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
|
|
||||||
fmt = 'e'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer = strconv.AppendFloat(buffer[:0], f, fmt, -1, int(bits))
|
|
||||||
if fmt == 'e' {
|
|
||||||
// clean up e-09 to e-9
|
|
||||||
n := len(buffer)
|
|
||||||
if n >= 4 && buffer[n-4] == 'e' && buffer[n-3] == '-' && buffer[n-2] == '0' {
|
|
||||||
buffer[n-2] = buffer[n-1]
|
|
||||||
buffer = buffer[:n-1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,349 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name value_packer.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 29/01/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
|
|
||||||
|
|
||||||
import (
|
|
||||||
"activething.com/go/gogo/packs"
|
|
||||||
"encoding/base32"
|
|
||||||
"encoding/base64"
|
|
||||||
"io"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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(state,v,flags)
|
|
||||||
|
|
||||||
case reflect.Value : RPacker(state,v.Elem(),0)
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
/*
|
|
||||||
if pb,is := value.(packs.Builder); is {
|
|
||||||
e := pb.Build(pb)
|
|
||||||
if e != nil {
|
|
||||||
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 {
|
|
||||||
panic(state.Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(value) == 0 {
|
|
||||||
state.Write2Byte('"','"')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
state.WriteByte('"')
|
|
||||||
start := 0
|
|
||||||
for i := 0; i < len(value); {
|
|
||||||
if b := value[i]; b < utf8.RuneSelf {
|
|
||||||
if !G.jsonChars[b].isHtmlUnsafe() || (!flags.EscapeHTML() && !G.jsonChars[b].isUnsafe()) {
|
|
||||||
i++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if start < i {
|
|
||||||
state.WriteString(value[start:i])
|
|
||||||
}
|
|
||||||
state.WriteByte('\\')
|
|
||||||
switch b {
|
|
||||||
case '\\', '"': state.WriteByte(b)
|
|
||||||
case '\n': state.WriteByte('n')
|
|
||||||
case '\r': state.WriteByte('r')
|
|
||||||
case '\t': state.WriteByte('t')
|
|
||||||
default:
|
|
||||||
state.WriteString(`u00`)
|
|
||||||
state.Write2Byte(G.hex[b>>4], G.hex[b&0xF])
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
start = i
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
c, size := utf8.DecodeRuneInString(value[i:])
|
|
||||||
if c == utf8.RuneError && size == 1 {
|
|
||||||
if start < i {
|
|
||||||
state.WriteString(value[start:i])
|
|
||||||
}
|
|
||||||
state.WriteString(`\ufffd`)
|
|
||||||
i += size
|
|
||||||
start = i
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if c == '\u2028' || c == '\u2029' {
|
|
||||||
if start < i {
|
|
||||||
state.WriteString(value[start:i])
|
|
||||||
}
|
|
||||||
state.WriteString(`\u202`)
|
|
||||||
state.WriteByte(G.hex[c&0xF])
|
|
||||||
i += size
|
|
||||||
start = i
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
i += size
|
|
||||||
}
|
|
||||||
if start < len(value) {
|
|
||||||
state.WriteString(value[start:])
|
|
||||||
}
|
|
||||||
state.WriteByte('"')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func packBinary (state *packs.State, value []byte , f Flags) {
|
|
||||||
if state.Error != nil {
|
|
||||||
panic(state.Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if value == nil {
|
|
||||||
_,_ = state.Write(G.nullValue)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(value) == 0 {
|
|
||||||
state.Write2Byte('"','"')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
state.WriteByte('"')
|
|
||||||
|
|
||||||
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]
|
|
||||||
ec.Encode(dst, value)
|
|
||||||
_,_= state.Write(dst)
|
|
||||||
} else if ln <= 1024 {
|
|
||||||
dst := make([]byte, ln)
|
|
||||||
ec.Encode(dst, value)
|
|
||||||
_,_ = state.Write(dst)
|
|
||||||
} else {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
if flags.Quote() {
|
|
||||||
state.WriteByte('"')
|
|
||||||
}
|
|
||||||
if value {
|
|
||||||
state.W(G.trueValue)
|
|
||||||
} else {
|
|
||||||
state.W(G.falseValue)
|
|
||||||
}
|
|
||||||
if flags.Quote() {
|
|
||||||
state.WriteByte('"')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func packInt (state *packs.State, value int64 , flags Flags) {
|
|
||||||
if state.Error != nil {
|
|
||||||
panic(state.Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if flags.Quote() {
|
|
||||||
state.WriteByte('"')
|
|
||||||
}
|
|
||||||
if value == 0 {
|
|
||||||
state.WriteByte('0')
|
|
||||||
} else {
|
|
||||||
state.WriteIntStr(value, 10)
|
|
||||||
}
|
|
||||||
if flags.Quote() {
|
|
||||||
state.WriteByte('"')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func packUInt (state *packs.State, value uint64 , flags Flags) {
|
|
||||||
if state.Error != nil {
|
|
||||||
panic(state.Error)
|
|
||||||
}
|
|
||||||
if flags.Quote() {
|
|
||||||
state.WriteByte('"')
|
|
||||||
}
|
|
||||||
if value == 0 {
|
|
||||||
state.WriteByte('0')
|
|
||||||
} else {
|
|
||||||
state.WriteUIntStr(value, 10)
|
|
||||||
}
|
|
||||||
if flags.Quote() {
|
|
||||||
state.WriteByte('"')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func packFloat (state *packs.State, value float64, flags Flags) {
|
|
||||||
packFloatString(state, value,64, flags.Quote())
|
|
||||||
}
|
|
||||||
|
|
||||||
func packFloatString (state *packs.State, f float64, bits int, quote bool) {
|
|
||||||
if state.Error != nil {
|
|
||||||
panic(state.Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if math.IsInf(f, 0) || math.IsNaN(f) {
|
|
||||||
state.SetError(packs.G.ErrInvalidValue)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
abs := math.Abs(f)
|
|
||||||
fmt := byte('f')
|
|
||||||
|
|
||||||
if abs != 0 {
|
|
||||||
if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
|
|
||||||
fmt = 'e'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bf := state.Temp[:0]
|
|
||||||
bf = strconv.AppendFloat(bf, f, fmt, -1, int(bits))
|
|
||||||
if fmt == 'e' {
|
|
||||||
// clean up e-09 to e-9
|
|
||||||
n := len(bf)
|
|
||||||
if n >= 4 && bf[n-4] == 'e' && bf[n-3] == '-' && bf[n-2] == '0' {
|
|
||||||
bf[n-2] = bf[n-1]
|
|
||||||
bf = bf[:n-1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if quote {
|
|
||||||
state.WriteByte('"')
|
|
||||||
}
|
|
||||||
state.W(bf)
|
|
||||||
if quote {
|
|
||||||
state.WriteByte('"')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func PackDate (state *packs.State, value time.Time, flags Flags) {
|
|
||||||
if state.Error != nil {
|
|
||||||
panic(state.Error)
|
|
||||||
}
|
|
||||||
state.WriteByte('"')
|
|
||||||
bf := state.Temp[:0]
|
|
||||||
bf = value.AppendFormat(bf,flags.DateFormat())
|
|
||||||
state.W(bf)
|
|
||||||
state.WriteByte('"')
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,142 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name rkey.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 04/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
|
|
||||||
|
|
||||||
import (
|
|
||||||
"activething.com/go/gogo/packs"
|
|
||||||
"encoding"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func stringifyRKey(rt reflect.Type) rMapEntryFnc {
|
|
||||||
fn,ok := G.keyersCache.Load(rt)
|
|
||||||
if !ok {
|
|
||||||
fn, _ = G.keyersCache.LoadOrStore(rt, _stringifyRKey(rt))
|
|
||||||
}
|
|
||||||
return fn.(rMapEntryFnc)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func _stringifyRKey(rt reflect.Type) rMapEntryFnc {
|
|
||||||
|
|
||||||
if rt.Kind() == reflect.String {
|
|
||||||
return func(e *rMapEntry, k reflect.Value) error {
|
|
||||||
e.k = k.String()
|
|
||||||
e.f = FlagScapeHTML
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if rt.Implements(G.textMarshalerType) {
|
|
||||||
return func(e *rMapEntry, k reflect.Value) error {
|
|
||||||
if k.Kind() == reflect.Pointer && k.IsNil() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
bf, er := (k.Interface().(encoding.TextMarshaler)).MarshalText()
|
|
||||||
if er == nil {
|
|
||||||
e.k = string(bf)
|
|
||||||
e.f = FlagScapeHTML
|
|
||||||
}
|
|
||||||
return er
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch rt.Kind() {
|
|
||||||
|
|
||||||
case reflect.Int,
|
|
||||||
reflect.Int8,
|
|
||||||
reflect.Int16,
|
|
||||||
reflect.Int32,
|
|
||||||
reflect.Int64:
|
|
||||||
return func(e *rMapEntry, k reflect.Value) error {
|
|
||||||
e.k = strconv.FormatInt(k.Int(), 10)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case reflect.Uint,
|
|
||||||
reflect.Uint8,
|
|
||||||
reflect.Uint16,
|
|
||||||
reflect.Uint32,
|
|
||||||
reflect.Uint64,
|
|
||||||
reflect.Uintptr:
|
|
||||||
return func(e *rMapEntry, k reflect.Value) error {
|
|
||||||
e.k = strconv.FormatUint(k.Uint(), 10)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Interface:
|
|
||||||
return func(e *rMapEntry, k reflect.Value) error {
|
|
||||||
k = k.Elem()
|
|
||||||
|
|
||||||
if k.Type().Kind() == reflect.String {
|
|
||||||
e.k = k.String()
|
|
||||||
e.f = FlagScapeHTML
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if t,h := k.Interface().(encoding.TextMarshaler); h {
|
|
||||||
if k.Type().Kind() == reflect.Pointer && k.IsNil() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
bf, er := t.MarshalText()
|
|
||||||
if er == nil {
|
|
||||||
e.k = string(bf)
|
|
||||||
e.f = FlagScapeHTML
|
|
||||||
}
|
|
||||||
return er
|
|
||||||
}
|
|
||||||
|
|
||||||
switch rt.Kind() {
|
|
||||||
|
|
||||||
case reflect.Int,
|
|
||||||
reflect.Int8,
|
|
||||||
reflect.Int16,
|
|
||||||
reflect.Int32,
|
|
||||||
reflect.Int64:
|
|
||||||
e.k = strconv.FormatInt(k.Int(), 10)
|
|
||||||
return nil
|
|
||||||
|
|
||||||
case reflect.Uint,
|
|
||||||
reflect.Uint8,
|
|
||||||
reflect.Uint16,
|
|
||||||
reflect.Uint32,
|
|
||||||
reflect.Uint64,
|
|
||||||
reflect.Uintptr:
|
|
||||||
e.k = strconv.FormatUint(k.Uint(), 10)
|
|
||||||
return nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
return packs.G.ErrInvalidKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name type_slice_packer.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 30/01/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
|
|
||||||
|
|
||||||
import (
|
|
||||||
"activething.com/go/gogo/packs"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
|
|
||||||
rList struct {
|
|
||||||
valFn packerFn
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func (p rList) pack (s *packs.State, v reflect.Value, f Flags) {
|
|
||||||
if v.IsNil() {
|
|
||||||
_,_ = s.Write(G.nullValue)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v.Len() == 0 {
|
|
||||||
s.Write2Byte('[',']')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.Open('[')
|
|
||||||
for i:=0; i<v.Len(); i++ {
|
|
||||||
if i > 0 {
|
|
||||||
s.WriteByte(',')
|
|
||||||
}
|
|
||||||
p.valFn(s,v.Index(i),f)
|
|
||||||
if s.Error != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.Close(']')
|
|
||||||
}
|
|
||||||
@ -1,110 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name key_val_packer.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 03/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
|
|
||||||
|
|
||||||
import (
|
|
||||||
"activething.com/go/gogo/packs"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
|
|
||||||
rMap struct {
|
|
||||||
keyFn rMapEntryFnc
|
|
||||||
valFn packerFn
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func newRMap (rtype reflect.Type) *rMap {
|
|
||||||
return &rMap{
|
|
||||||
valFn : rTypePacker(rtype.Elem()),
|
|
||||||
keyFn : stringifyRKey(rtype.Key()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (p *rMap) pack (s *packs.State, v reflect.Value, f Flags) {
|
|
||||||
if p.keyFn == nil {
|
|
||||||
s.SetError(packs.G.ErrInvalidKey)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.IsNil() {
|
|
||||||
s.W(G.nullValue)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v.Len() == 0{
|
|
||||||
s.Write2Byte('{','}')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.Level > startDetectingCyclesAfter {
|
|
||||||
if fn,ok := s.CheckCycle(v.UnsafePointer()); ok {
|
|
||||||
defer fn()
|
|
||||||
} else {
|
|
||||||
s.SetError(packs.G.ErrRedundantPack)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mi := v.MapRange()
|
|
||||||
ls := make(rMapEntryList,v.Len())
|
|
||||||
|
|
||||||
for i:=0; mi.Next(); i++ {
|
|
||||||
ls[i] = rMapEntry{
|
|
||||||
v: mi.Value(),
|
|
||||||
}
|
|
||||||
if er := p.keyFn(&ls[i], mi.Key()); er != nil {
|
|
||||||
s.SetError(er)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Sort(ls)
|
|
||||||
|
|
||||||
s.Open ('{')
|
|
||||||
for i:=0; i<len(ls); i++ {
|
|
||||||
if i>0 {
|
|
||||||
s.WriteByte(',')
|
|
||||||
}
|
|
||||||
packString(s,ls[i].k,ls[i].f)
|
|
||||||
if s.Error != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.WriteByte(':')
|
|
||||||
p.valFn(s,ls[i].v,0)
|
|
||||||
if s.Error != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.Close('}')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name key_entry.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 02/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
|
|
||||||
|
|
||||||
import "reflect"
|
|
||||||
|
|
||||||
type (
|
|
||||||
|
|
||||||
|
|
||||||
rMapEntry struct {
|
|
||||||
f Flags // flags
|
|
||||||
v reflect.Value // value
|
|
||||||
k string // Key
|
|
||||||
}
|
|
||||||
|
|
||||||
rMapEntryFnc func(entry *rMapEntry, rkey reflect.Value) error
|
|
||||||
|
|
||||||
rMapEntryList []rMapEntry
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (e rMapEntryList) Len() int {
|
|
||||||
return len(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e rMapEntryList) Less(i, j int) bool {
|
|
||||||
return e[i].k < e[j].k
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e rMapEntryList) Swap(i, j int) {
|
|
||||||
e[i], e[j] = e[j], e[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,110 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name type_packer.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 29/01/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
|
|
||||||
|
|
||||||
import (
|
|
||||||
"activething.com/go/gogo/packs"
|
|
||||||
"reflect"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
|
|
||||||
packer interface {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
packerFn func (state *packs.State, value reflect.Value, flags Flags)
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func RPacker(state *packs.State, value any, flags Flags ) {
|
|
||||||
v := reflect.ValueOf(value)
|
|
||||||
t := v.Type()
|
|
||||||
rTypePacker(t)(state,v,flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func rTypePacker(rtype reflect.Type) packerFn {
|
|
||||||
if fn,ok := G.packersCache.Load(rtype); ok {
|
|
||||||
return fn.(packerFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
var fn packerFn
|
|
||||||
|
|
||||||
wg.Add(1)
|
|
||||||
|
|
||||||
fi,ld := G.packersCache.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.packersCache.Store(rtype,fn)
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func _rTypePacker(t reflect.Type) packerFn {
|
|
||||||
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Bool : return func(s *packs.State, v reflect.Value, f Flags) { packBool (s,v.Bool (),f )}
|
|
||||||
case reflect.String : return func(s *packs.State, v reflect.Value, f Flags) { packString(s,v.String(),f )}
|
|
||||||
case reflect.Int,
|
|
||||||
reflect.Int8,
|
|
||||||
reflect.Int16,
|
|
||||||
reflect.Int32,
|
|
||||||
reflect.Int64 : return func(s *packs.State, v reflect.Value, f Flags) { packInt (s,v.Int (),f )}
|
|
||||||
case reflect.Uint,
|
|
||||||
reflect.Uint8,
|
|
||||||
reflect.Uint16,
|
|
||||||
reflect.Uint32,
|
|
||||||
reflect.Uint64 : return func(s *packs.State, v reflect.Value, f Flags) { packUInt (s,v.Uint (),f )}
|
|
||||||
case reflect.Float32: return func(s *packs.State, v reflect.Value, f Flags) { packFloatString(s,v.Float(),32, f.Quote()) }
|
|
||||||
case reflect.Float64: return func(s *packs.State, v reflect.Value, f Flags) { packFloatString(s,v.Float(),64, f.Quote()) }
|
|
||||||
|
|
||||||
case reflect.Slice,
|
|
||||||
reflect.Array :
|
|
||||||
return (rList{ valFn: rTypePacker(t.Elem()) }).pack
|
|
||||||
|
|
||||||
case reflect.Map :
|
|
||||||
return newRMap(t).pack
|
|
||||||
}
|
|
||||||
return unsupportedTypePacker
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func unsupportedTypePacker(state *packs.State, _ reflect.Value, _ Flags) {
|
|
||||||
state.SetError(packs.G.ErrUnsupportedType)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
module activething.com/go/gogo/packs/reflects
|
|
||||||
|
|
||||||
go 1.20
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name gogo.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 28/01/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 reflects
|
|
||||||
|
|
||||||
import (
|
|
||||||
"activething.com/go/gogo/packs"
|
|
||||||
"reflect"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
|
|
||||||
G = struct {
|
|
||||||
|
|
||||||
locker sync.Mutex
|
|
||||||
cache map[reflect.Type]RStruct
|
|
||||||
|
|
||||||
}{
|
|
||||||
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func GetRTypePacker (rtype reflect.Type, packer packs.Packer) *RStruct {
|
|
||||||
G.locker.Lock()
|
|
||||||
if G.cache == nil {
|
|
||||||
G.cache = make(map[reflect.Type]RStruct)
|
|
||||||
}
|
|
||||||
|
|
||||||
G.locker.Unlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,112 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name reflect_struct_field.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 26/01/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 reflects
|
|
||||||
|
|
||||||
import (
|
|
||||||
"activething.com/go/gogo/core/opts"
|
|
||||||
"activething.com/go/gogo/core/slices"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
|
|
||||||
RField struct {
|
|
||||||
RType reflect.Type
|
|
||||||
RField reflect.StructField
|
|
||||||
|
|
||||||
Name string
|
|
||||||
SName string // scaped name
|
|
||||||
HName string // html name
|
|
||||||
|
|
||||||
BName []byte // name bytes
|
|
||||||
Index []int
|
|
||||||
|
|
||||||
Tags map[string]slices.String
|
|
||||||
Flags uint16
|
|
||||||
|
|
||||||
EqualFoldFn func(s, t []byte) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func NewRField (rfield reflect.StructField, options ...opts.OptionFnc[RField]) *RField {
|
|
||||||
rf := &RField{
|
|
||||||
RField: rfield,
|
|
||||||
Tags : make(map[string]slices.String),
|
|
||||||
}
|
|
||||||
rf.parseTag("json",nil)
|
|
||||||
return opts.Apply(rf,options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (f *RField) parseTag (tagKey string, onOptionFn func(*RField,int,string)) {
|
|
||||||
if _,h := f.Tags[tagKey]; !h {
|
|
||||||
t := f.RField.Tag.Get(tagKey)
|
|
||||||
if len(t) > 0 {
|
|
||||||
l := strings.Split(t,",")
|
|
||||||
f.Tags[tagKey]= l
|
|
||||||
if onOptionFn != nil {
|
|
||||||
for i,o := range l {
|
|
||||||
onOptionFn(f,i,o)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func parseTag (field reflect.StructField, tagKey string, onOptionFn func(int,string)) (slices.String,bool) {
|
|
||||||
t := field.Tag.Get(tagKey)
|
|
||||||
if len(t) > 0 {
|
|
||||||
l := strings.Split(t,",")
|
|
||||||
if onOptionFn != nil {
|
|
||||||
for i,o := range l {
|
|
||||||
onOptionFn(i,o)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return l,true
|
|
||||||
}
|
|
||||||
return nil,true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func isValidTag(s string) bool {
|
|
||||||
if s == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, c := range s {
|
|
||||||
switch {
|
|
||||||
case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
|
|
||||||
case !unicode.IsLetter(c) && !unicode.IsDigit(c):
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name rfield_tag.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 27/01/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 reflects
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
|
|
||||||
RFieldTag struct {
|
|
||||||
Tag string
|
|
||||||
parsed bool
|
|
||||||
Name string
|
|
||||||
Flags uint8
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func NewRFieldTag (rfield reflect.StructField, tag string, onOption func(rf reflect.Type, position int, option string) uint8) *RFieldTag {
|
|
||||||
f := &RFieldTag{
|
|
||||||
Tag : rfield.Tag.Get(tag),
|
|
||||||
}
|
|
||||||
var ops string
|
|
||||||
f.Name,ops,_ = strings.Cut(f.Tag,",")
|
|
||||||
|
|
||||||
if len(ops) == 0 {
|
|
||||||
f.parsed = true
|
|
||||||
} else if onOption != nil {
|
|
||||||
f.parsed = true
|
|
||||||
for pos:=0; ops != ""; pos++ {
|
|
||||||
var name string
|
|
||||||
name, ops, _ = strings.Cut(ops, ",")
|
|
||||||
f.Flags = onOption(rfield.Type, pos,name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name rfields.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 27/01/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 reflects
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type (
|
|
||||||
|
|
||||||
RFields []RField
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
func (f RFields) Dominant() (RField, bool) {
|
|
||||||
// The Fields are sorted in increasing index-length order, then by presence of tag.
|
|
||||||
// That means that the first RField is the dominant one. We need only check
|
|
||||||
// for error cases: two Fields at top level, either both tagged or neither tagged.
|
|
||||||
if len(f) > 1 && len(f[0].Index) == len(f[1].Index) && f[0].Tagged() == f[1].Tagged() {
|
|
||||||
return RField{}, false
|
|
||||||
}
|
|
||||||
return f[0], true
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (f RFields) Len() int { return len(f) }
|
|
||||||
|
|
||||||
func (f RFields) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
|
|
||||||
|
|
||||||
func (f RFields) Less(i, j int) bool {
|
|
||||||
for k, xik := range f[i].Index {
|
|
||||||
if k >= len(f[j].Index) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if xik != f[j].Index[k] {
|
|
||||||
return xik < f[j].Index[k]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len(f[i].Index) < len(f[j].Index)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,72 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name rmap.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 28/01/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 reflects
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
type (
|
|
||||||
|
|
||||||
RMap struct {
|
|
||||||
KeyValues []RKeyValue
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func NewRMap (value reflect.Value, stringifyFn func(v reflect.Value) (string,error), scapeFn func(string)string) (*RMap,error) {
|
|
||||||
ls := make([]RKeyValue,value.Len())
|
|
||||||
mi := value.MapRange()
|
|
||||||
|
|
||||||
sf := scapeFn
|
|
||||||
if sf == nil {
|
|
||||||
sf = func(v string) string { return v }
|
|
||||||
}
|
|
||||||
|
|
||||||
for i:=0; mi.Next(); i++ {
|
|
||||||
k,e := NewRKeyValue(mi.Key(),mi.Value(), stringifyFn,sf)
|
|
||||||
if e != nil {
|
|
||||||
return nil,e
|
|
||||||
}
|
|
||||||
ls[i]=*k
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Slice(ls,func(i,j int) bool { return ls[i].Key < ls[j].Key })
|
|
||||||
|
|
||||||
return &RMap {
|
|
||||||
KeyValues: ls,
|
|
||||||
},nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func ensureScapeFn (sfn func(string)string) func(string)string {
|
|
||||||
if sfn == nil {
|
|
||||||
return func(v string) string { return v }
|
|
||||||
}
|
|
||||||
return sfn
|
|
||||||
}
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name rmap.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 28/01/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 reflects
|
|
||||||
|
|
||||||
import (
|
|
||||||
"activething.com/go/gogo/packs"
|
|
||||||
"encoding"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
|
|
||||||
RKeyValue struct {
|
|
||||||
RKey reflect.Value
|
|
||||||
RVal reflect.Value
|
|
||||||
Key string
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func NewRKeyValue(key reflect.Value, value reflect.Value, stringifyFn func(v reflect.Value) (string,error), scapeFn func(string) string) (*RKeyValue,error) {
|
|
||||||
kv := &RKeyValue{
|
|
||||||
RKey : key,
|
|
||||||
RVal : value,
|
|
||||||
}
|
|
||||||
if kv.RKey.Kind() == reflect.String {
|
|
||||||
kv.Key = scapeFn(kv.RKey.String())
|
|
||||||
return kv,nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if tm,hs := kv.RKey.Interface().(encoding.TextMarshaler); hs {
|
|
||||||
if kv.RKey.Kind() == reflect.Pointer && kv.RKey.IsNil() {
|
|
||||||
return nil,packs.G.ErrInvalidKey
|
|
||||||
}
|
|
||||||
b,e := tm.MarshalText()
|
|
||||||
if e != nil {
|
|
||||||
return nil,packs.G.ErrInvalidKey
|
|
||||||
}
|
|
||||||
kv.Key = string(b)
|
|
||||||
return kv,nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if stringifyFn != nil {
|
|
||||||
b,e := stringifyFn(kv.RKey)
|
|
||||||
if e != nil {
|
|
||||||
return nil,packs.G.ErrInvalidKey.WithCause(e)
|
|
||||||
}
|
|
||||||
kv.Key = scapeFn(b)
|
|
||||||
return kv,nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch key.Kind() {
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
kv.Key = strconv.FormatInt(kv.RKey.Int(), 10)
|
|
||||||
return kv,nil
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
||||||
kv.Key= strconv.FormatUint(kv.RKey.Uint(), 10)
|
|
||||||
return kv,nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil,packs.G.ErrInvalidKey
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,153 +0,0 @@
|
|||||||
// ------------------------------------------------------------------------
|
|
||||||
// Project atila
|
|
||||||
// Active Thing (activething.com) git.activething.com/go
|
|
||||||
//
|
|
||||||
// File name rRFields_type.go
|
|
||||||
// Created by DEV
|
|
||||||
// Modified 26/01/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 reflects
|
|
||||||
|
|
||||||
type (
|
|
||||||
|
|
||||||
RStruct struct {
|
|
||||||
Fields RFields
|
|
||||||
NameIndex map[string]int
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
func NewRStruct (rtype reflect.Type) *RStruct {
|
|
||||||
res := &RStruct{
|
|
||||||
Fields : make(RFields,0,rtype.NumField()),
|
|
||||||
NameIndex: make(map[string]int),
|
|
||||||
}
|
|
||||||
|
|
||||||
cur := RFields{}
|
|
||||||
nxt := RFields{{ RType: rtype }}
|
|
||||||
|
|
||||||
var (
|
|
||||||
cnt,nxc map[reflect.Type]int
|
|
||||||
vis map[reflect.Type]struct{}
|
|
||||||
nms bytes.Buffer
|
|
||||||
)
|
|
||||||
|
|
||||||
for len(nxt) > 0 {
|
|
||||||
cur, nxt = nxt, cur[:0]
|
|
||||||
cnt, nxc = nxc, map[reflect.Type]int{}
|
|
||||||
|
|
||||||
for _,f := range cur {
|
|
||||||
if _,h := vis[f.RType]; h {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
vis[f.RType]=struct{}{}
|
|
||||||
|
|
||||||
for i :=0; i<f.RType.NumField(); i++ {
|
|
||||||
sf := f.RType.Field(i)
|
|
||||||
if sf.Anonymous {
|
|
||||||
st := sf.Type
|
|
||||||
if st.Kind() == reflect.Pointer {
|
|
||||||
st = st.Elem()
|
|
||||||
}
|
|
||||||
if !sf.IsExported() && st.Kind() != reflect.Struct {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else if !sf.IsExported() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
nm := false
|
|
||||||
tags,ok := parseTag(sf,"json",nil)
|
|
||||||
if ok {
|
|
||||||
if tags.Has("-") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if isValidTag(tags[0]) {
|
|
||||||
nm=true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ft := sf.Type
|
|
||||||
if ft.Name() == "" && ft.Kind() == reflect.Pointer {
|
|
||||||
ft=ft.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//qt := false
|
|
||||||
//if tags.Has("string") {
|
|
||||||
// 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:
|
|
||||||
// qt = true
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
index := make([]int, len(f.Index)+1)
|
|
||||||
copy(index, f.Index)
|
|
||||||
index[len(f.Index)] = i
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var name string
|
|
||||||
if nm || sf.Anonymous || ft.Kind() != reflect.Struct {
|
|
||||||
if nm {
|
|
||||||
name = tags[0]
|
|
||||||
} else {
|
|
||||||
name = sf.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
res.Fields = append(res.Fields, RField{
|
|
||||||
RField: sf,
|
|
||||||
RType: ft,
|
|
||||||
Name: name,
|
|
||||||
BName: []byte(name),
|
|
||||||
Tags: map[string]slices.String{"json": append(slices.String(nil), tags...)},
|
|
||||||
})
|
|
||||||
if cnt[f.RType] > 1 {
|
|
||||||
res.Fields = append(res.Fields, res.Fields[len(res.Fields)-1])
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
nxc[ft]++
|
|
||||||
if nxc[ft] == 1 {
|
|
||||||
nxt = append(nxt, RField{
|
|
||||||
RType: ft,
|
|
||||||
Name: ft.Name(),
|
|
||||||
Index: index,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i,f := range res.Fields {
|
|
||||||
res.NameIndex[f.Name]=i
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
Loading…
Reference in new issue