parent
2b776dd35f
commit
d6e5498605
@ -0,0 +1,54 @@
|
||||
// =============================================================================
|
||||
// GO·AT Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 11/06/2025
|
||||
// =============================================================================
|
||||
|
||||
package cdts
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
g = struct {
|
||||
minTime,
|
||||
maxTime time.Time
|
||||
}{
|
||||
minTime: time.Unix(0, math.MinInt64),
|
||||
maxTime: time.Unix(0, math.MaxInt64),
|
||||
}
|
||||
|
||||
|
||||
E = struct {
|
||||
InvalidCValueReflected,
|
||||
InvalidCValueForType string
|
||||
}{
|
||||
InvalidCValueReflected : "::invalid_reflect_value",
|
||||
InvalidCValueForType : "::invalid_value_for_type",
|
||||
}
|
||||
)
|
||||
@ -0,0 +1,81 @@
|
||||
// =============================================================================
|
||||
// GO·AT Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 10/06/2025
|
||||
// =============================================================================
|
||||
|
||||
package cdts
|
||||
|
||||
import "strings"
|
||||
|
||||
const (
|
||||
|
||||
CStateInvalid CState = 1 << iota // El valor almacenado es un valor invalido
|
||||
CStateNil // Indica que el valor es nulo
|
||||
CStateZero // Indica que el valor tiene valor 0
|
||||
CStateReflected // Indica que el valor guardado es un value.reflect
|
||||
CStateShort // Indica que el valor es la versión corta del valor, por ejemplo: los dates
|
||||
CStateSensitive // Indica que el valor es delicado, por ejemplo no mostrar o no serializar
|
||||
CStateEncoded // Indica que el valor está codificado
|
||||
CStateError // Indica que el valor no ha podido ser establecido por un error que esta representado en el
|
||||
// valor
|
||||
|
||||
CStateNone CState = 0
|
||||
|
||||
CStateOps CState = CStateEncoded|CStateSensitive
|
||||
)
|
||||
|
||||
|
||||
type CState uint8
|
||||
|
||||
|
||||
func (s CState) HasInvalid () bool { return s&CStateInvalid != 0 }
|
||||
func (s CState) HasNil () bool { return s&CStateNil != 0 }
|
||||
func (s CState) HasZero () bool { return s&CStateZero != 0 }
|
||||
func (s CState) HasReflected() bool { return s&CStateReflected != 0 }
|
||||
func (s CState) HasShort () bool { return s&CStateShort != 0 }
|
||||
func (s CState) HasSensitive() bool { return s&CStateSensitive != 0 }
|
||||
func (s CState) HasEncoded () bool { return s&CStateEncoded != 0 }
|
||||
func (s CState) HasError () bool { return s&CStateError != 0 }
|
||||
|
||||
func (s CState) HasNilOrZero() bool { return s&(CStateZero|CStateNil) != 0 }
|
||||
|
||||
func (s CState) setOption (options CState) CState { return s|(options&CStateOps) }
|
||||
|
||||
|
||||
func (s CState) String() string {
|
||||
states := [...]string{"invalid","nil","zero","reflected","short","sensitive","encoded","error"}
|
||||
c := make([]string,0,4)
|
||||
for i:=0; i<7; i++ {
|
||||
if s& (1<<i) != 0 {
|
||||
c=append(c,states[i])
|
||||
}
|
||||
}
|
||||
if len(c) == 0 {
|
||||
return ""
|
||||
}
|
||||
return strings.Join(c,":")
|
||||
|
||||
}
|
||||
@ -0,0 +1,223 @@
|
||||
// =============================================================================
|
||||
// GO·AT Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 10/06/2025
|
||||
// =============================================================================
|
||||
|
||||
package cdts
|
||||
|
||||
import "math/bits"
|
||||
|
||||
const (
|
||||
CTypeInvalid CType = 0
|
||||
|
||||
// Tipos Bases
|
||||
|
||||
|
||||
CTypeAny CType = 1 << 0
|
||||
|
||||
CTypeBool CType = 1 << 1
|
||||
|
||||
CTypeInt CType = 1 << 2
|
||||
CTypeInt8 CType = 1 << 3
|
||||
CTypeInt16 CType = 1 << 4
|
||||
CTypeInt32 CType = 1 << 5
|
||||
CTypeInt64 CType = 1 << 6
|
||||
|
||||
|
||||
CTypeUint CType = 1 << 7
|
||||
CTypeUint8 CType = 1 << 8
|
||||
CTypeUint16 CType = 1 << 9
|
||||
CTypeUint32 CType = 1 << 10
|
||||
CTypeUint64 CType = 1 << 11
|
||||
|
||||
CTypeUintptr CType = 1 << 12
|
||||
|
||||
CTypeFloat32 CType = 1 << 13
|
||||
CTypeFloat64 CType = 1 << 14
|
||||
|
||||
CTypeComplex64 CType = 1 << 15
|
||||
CTypeComplex128 CType = 1 << 16
|
||||
|
||||
|
||||
// CTypeDate time.Time
|
||||
CTypeDate CType = 1 << 17
|
||||
// CTypeDuration = time.Durations
|
||||
CTypeDuration CType = 1 << 18
|
||||
|
||||
CTypeString CType = 1 << 19
|
||||
CTypeBytes CType = 1 << 20
|
||||
CTypeStack CType = 1 << 21
|
||||
|
||||
// Objetos
|
||||
|
||||
// CTypeCValue
|
||||
// Es un valor compacto
|
||||
CTypeCValue CType = 1 << 22
|
||||
|
||||
// Tipos base - Interfaces
|
||||
|
||||
CTypePackable CType = 1 << 23
|
||||
CTypeContext CType = 1 << 24
|
||||
CTypeError CType = 1 << 25
|
||||
|
||||
|
||||
// CTypeNil Nulo Explícito
|
||||
CTypeNil CType = 1 << 26
|
||||
|
||||
// CTypeObject, Structs, se le pone para determinar, este tipo siempre sera
|
||||
// resultado de la reflexion del tipo ya que no se puede determinar si una
|
||||
// variable es una struct o cualquier otro tipo
|
||||
CTypeObject CType = 1 << 27
|
||||
|
||||
// Tipos compuestos
|
||||
|
||||
CTypeLazy CType = 1 << 28
|
||||
CTypeList CType = 1 << 29
|
||||
CTypeMap CType = 1 << 30
|
||||
CTypeMapKey CType = 1 << 31
|
||||
|
||||
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
// Mascaras de bits
|
||||
maskCTypeComposite = CTypeList | CTypeMap | CTypePackable
|
||||
maskCTypeBase = ^(maskCTypeComposite|CTypeMapKey)
|
||||
|
||||
maskCTypeInt = CTypeInt | CTypeInt8 | CTypeInt16 | CTypeInt32 | CTypeInt64
|
||||
maskCTypeUint = CTypeUint | CTypeUint8 | CTypeUint16 | CTypeUint32 | CTypeUint64
|
||||
maskCTypeNums = maskCTypeInt | maskCTypeUint
|
||||
maskCTypeFloat = CTypeFloat32 | CTypeFloat64
|
||||
maskCTypeComplex = CTypeComplex64 | CTypeComplex128
|
||||
maskCTypeInterfaces = CTypePackable|CTypeError|CTypeContext
|
||||
maskCTypeNullable= maskCTypeInterfaces | CTypeBytes | CTypeStack | CTypeString
|
||||
)
|
||||
|
||||
|
||||
const (
|
||||
|
||||
maxCTypes = 32
|
||||
)
|
||||
|
||||
|
||||
type CType uint32
|
||||
|
||||
|
||||
func (t CType) IsComposite() bool { return t&maskCTypeComposite != 0 }
|
||||
|
||||
func (t CType) BaseType () CType {
|
||||
if t&CTypeMap == 0 {
|
||||
return t &maskCTypeBase
|
||||
}
|
||||
_,vt := t.MapType()
|
||||
return vt
|
||||
}
|
||||
|
||||
func (t CType) IsLazy () bool { return t&CTypeLazy != 0 }
|
||||
func (t CType) IsList () bool { return t&CTypeList != 0 }
|
||||
func (t CType) IsMap () bool { return t&CTypeMap != 0 }
|
||||
|
||||
func (t CType) MapType () (CType, CType) {
|
||||
if t&CTypeMap == 0 {
|
||||
return CTypeInvalid, CTypeInvalid
|
||||
}
|
||||
bs := t &maskCTypeBase
|
||||
switch bits.OnesCount32(uint32(bs)) {
|
||||
case 1: return bs,bs
|
||||
case 2:
|
||||
if t&CTypeMapKey == 0 {
|
||||
return bs&-bs,bs&^(bs&-bs)
|
||||
}
|
||||
return bs&^(bs&-bs),bs&-bs
|
||||
default:
|
||||
return CTypeInvalid, CTypeInvalid
|
||||
}
|
||||
}
|
||||
|
||||
func (t CType) IsInvalid() bool { return t&maskCTypeBase == CTypeInvalid }
|
||||
|
||||
func (t CType) IsAny() bool { return t&maskCTypeBase == CTypeAny }
|
||||
func (t CType) IsBool() bool { return t&maskCTypeBase == CTypeBool }
|
||||
|
||||
func (t CType) IsInt() bool { return t&maskCTypeBase == CTypeInt }
|
||||
func (t CType) IsInt8() bool { return t&maskCTypeBase == CTypeInt8 }
|
||||
func (t CType) IsInt16() bool { return t&maskCTypeBase == CTypeInt16 }
|
||||
func (t CType) IsInt32() bool { return t&maskCTypeBase == CTypeInt32 }
|
||||
func (t CType) IsInt64() bool { return t&maskCTypeBase == CTypeInt64 }
|
||||
func (t CType) IsUint() bool { return t&maskCTypeBase == CTypeUint }
|
||||
func (t CType) IsUint8() bool { return t&maskCTypeBase == CTypeUint8 }
|
||||
func (t CType) IsUint16() bool { return t&maskCTypeBase == CTypeUint16 }
|
||||
func (t CType) IsUint32() bool { return t&maskCTypeBase == CTypeUint32 }
|
||||
func (t CType) IsUint64() bool { return t&maskCTypeBase == CTypeUint64 }
|
||||
func (t CType) IsUintptr() bool { return t&maskCTypeBase == CTypeUintptr }
|
||||
|
||||
func (t CType) IsFloat32() bool { return t&maskCTypeBase == CTypeFloat32 }
|
||||
func (t CType) IsFloat64() bool { return t&maskCTypeBase == CTypeFloat64 }
|
||||
func (t CType) IsComplex64 () bool { return t&maskCTypeBase == CTypeComplex64 }
|
||||
func (t CType) IsComplex128() bool { return t&maskCTypeBase == CTypeComplex128 }
|
||||
|
||||
func (t CType) IsDuration() bool { return t&maskCTypeBase == CTypeDuration }
|
||||
func (t CType) IsDate() bool { return t&maskCTypeBase == CTypeDate }
|
||||
|
||||
func (t CType) IsString() bool { return t&maskCTypeBase == CTypeString }
|
||||
func (t CType) IsBytes() bool { return t&maskCTypeBase == CTypeBytes }
|
||||
func (t CType) IsStack() bool { return t&maskCTypeBase == CTypeStack }
|
||||
func (t CType) IsCValue() bool { return t&maskCTypeBase == CTypeCValue }
|
||||
|
||||
func (t CType) IsPackable() bool { return t&maskCTypeBase == CTypePackable }
|
||||
func (t CType) IsContext () bool { return t&maskCTypeBase == CTypeContext }
|
||||
func (t CType) IsError() bool { return t&maskCTypeBase == CTypeError }
|
||||
|
||||
func (t CType) IsNil() bool { return t&maskCTypeBase == CTypeNil }
|
||||
|
||||
func (t CType) IsObject() bool { return t&maskCTypeBase == CTypeObject }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func setMapType(keyType, valType CType) CType {
|
||||
if keyType == CTypeInvalid || valType == CTypeInvalid {
|
||||
return CTypeInvalid
|
||||
}
|
||||
if keyType == valType {
|
||||
return CTypeMap|keyType
|
||||
}
|
||||
if keyType < valType {
|
||||
return CTypeMap|keyType|valType
|
||||
}
|
||||
return CTypeMap |valType|keyType| CTypeMapKey
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,103 @@
|
||||
// =============================================================================
|
||||
// GO·AT Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 10/06/2025
|
||||
// =============================================================================
|
||||
|
||||
package cdts
|
||||
|
||||
|
||||
|
||||
const(
|
||||
createByValue = iota
|
||||
createByPtr
|
||||
createByList
|
||||
createByLazy
|
||||
|
||||
maxCValueCreators = 4
|
||||
)
|
||||
|
||||
|
||||
type (
|
||||
|
||||
cTypeInfo struct {
|
||||
ctype CType
|
||||
name string
|
||||
creators [maxCValueCreators]func(any) CValue
|
||||
}
|
||||
|
||||
cTypeInfoFnc func(info *cTypeInfo)
|
||||
|
||||
|
||||
)
|
||||
|
||||
|
||||
func createCTypeInfo [T any](cType CType, name string, createFnc func(value T) CValue, ops ...cTypeInfoFnc) cTypeInfo {
|
||||
ti := cTypeInfo{
|
||||
ctype : cType,
|
||||
name : name,
|
||||
|
||||
creators: [maxCValueCreators]func(any) CValue{
|
||||
/* createByValue */ func(v any) CValue { return createFnc(v.(T)) },
|
||||
|
||||
/* createByPtr */ func(v any) CValue {
|
||||
value := v.(*T)
|
||||
if value == nil {
|
||||
return CValue{vType: cType, vState: CStateNil}
|
||||
}
|
||||
return createFnc(*value)
|
||||
},
|
||||
|
||||
/* createByList */ func(v any) CValue {
|
||||
tp := cType|CTypeList
|
||||
vl := v.([]T)
|
||||
ln := len(vl)
|
||||
if ln == 0 {
|
||||
if vl == nil {
|
||||
return CValue{vType: tp, vState: CStateNil}
|
||||
}
|
||||
return CValue{vType: tp, vState: CStateZero}
|
||||
}
|
||||
return CValue{ vType: tp, intVal: int64(ln), anyVal: vl}
|
||||
},
|
||||
|
||||
/* createByLazy */ func(v any) CValue {
|
||||
tp := cType|CTypeLazy
|
||||
vl := v.(func()T)
|
||||
if vl == nil {
|
||||
return CValue{ vType: tp, vState: CStateNil }
|
||||
}
|
||||
return CValue{ vType: tp, anyVal: vl}
|
||||
},
|
||||
},
|
||||
}
|
||||
for _,f := range ops {
|
||||
f(&ti)
|
||||
}
|
||||
return ti
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,557 @@
|
||||
// =============================================================================
|
||||
// GO·AT Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 10/06/2025
|
||||
// =============================================================================
|
||||
|
||||
package cdts
|
||||
|
||||
import (
|
||||
"math/bits"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
|
||||
type (
|
||||
|
||||
cTypeInfos struct {
|
||||
mux sync.RWMutex
|
||||
types [maxCTypes+1]cTypeInfo
|
||||
cache map[reflect.Type]func(any)CValue
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
func newCTypeInfos() *cTypeInfos {
|
||||
return &cTypeInfos{
|
||||
mux : sync.RWMutex{},
|
||||
cache: make(map[reflect.Type]func(value any)CValue),
|
||||
types: [maxCTypes+1]cTypeInfo{
|
||||
|
||||
/* 0 */ createCTypeInfo[any ](CTypeInvalid,"invalid" ,createCValueInvalid,
|
||||
func(i *cTypeInfo) {
|
||||
i.creators[createByPtr] = createCValueInvalid
|
||||
i.creators[createByList] = createCValueInvalid
|
||||
i.creators[createByLazy] = createCValueInvalid
|
||||
}),
|
||||
/* 1 */createCTypeInfo [any ](CTypeAny ,"any" ,CreateCValueAny),
|
||||
/* 2 */createCTypeInfo [bool ](CTypeBool ,"bool" ,CreateCValueBool),
|
||||
/* 3 */createCTypeInfo [int ](CTypeInt ,"int" ,CreateCValueInt),
|
||||
/* 4 */createCTypeInfo [int8 ](CTypeInt8 ,"int8" ,CreateCValueInt8),
|
||||
/* 5 */createCTypeInfo [int16 ](CTypeInt16 ,"int16" ,CreateCValueInt16),
|
||||
/* 6 */createCTypeInfo [int32 ](CTypeInt32 ,"int32" ,CreateCValueInt32),
|
||||
/* 7 */createCTypeInfo [int64 ](CTypeInt64 ,"int64" ,CreateCValueInt64),
|
||||
/* 8 */createCTypeInfo [uint ](CTypeUint ,"uint" ,CreateCValueUint),
|
||||
|
||||
/* 9 */createCTypeInfo [uint8 ](CTypeUint8 ,"uint8" ,CreateCValueUint8,
|
||||
func(i *cTypeInfo) {
|
||||
// El []uint8 debe de ser considerado como de tipo bytes
|
||||
i.creators[createByList] = func(v any) CValue { return CreateCValueBytes(v.([]uint8)) }
|
||||
}),
|
||||
|
||||
/* 10 */createCTypeInfo [uint16 ](CTypeUint16 ,"uint16" ,CreateCValueUint16),
|
||||
/* 11 */createCTypeInfo [uint32 ](CTypeUint32 ,"uint32" ,CreateCValueUint32),
|
||||
/* 12 */createCTypeInfo [uint64 ](CTypeUint64 ,"uint64" ,CreateCValueUint64),
|
||||
/* 13 */createCTypeInfo [uintptr ](CTypeUintptr ,"uintptr" ,CreateCValueUintptr),
|
||||
/* 14 */createCTypeInfo [float32 ](CTypeFloat32 ,"float32" ,CreateCValueFloat32),
|
||||
/* 15 */createCTypeInfo [float64 ](CTypeFloat64 ,"float64" ,CreateCValueFloat64),
|
||||
/* 16 */createCTypeInfo [complex64 ](CTypeComplex64,"complex64" ,CreateCValueComplex64),
|
||||
/* 17 */createCTypeInfo [complex128 ](CTypeComplex128,"complex128" ,CreateCValueComplex128),
|
||||
/* 18 */createCTypeInfo [Date ](CTypeDate ,"date" ,CreateCValueDate),
|
||||
/* 19 */createCTypeInfo [Duration ](CTypeDuration ,"duration" ,CreateCValueDuration),
|
||||
/* 20 */createCTypeInfo [string ](CTypeString ,"string" ,CreateCValueString),
|
||||
/* 21 */createCTypeInfo [Bytes ](CTypeBytes ,"bytes" ,CreateCValueBytes),
|
||||
/* 22 */createCTypeInfo [Stack ](CTypeStack ,"stack" ,CreateCValueStack),
|
||||
/* 23 */createCTypeInfo [CValue ](CTypeCValue ,"cvalue" ,createCValueCValue),
|
||||
|
||||
/* 24 */createCTypeInfo [Packable ](CTypePackable ,"packable" ,CreateCValuePackable),
|
||||
/* 25 */createCTypeInfo [Context ](CTypeContext ,"context" ,CreateCValueContext),
|
||||
/* 26 */createCTypeInfo [error ](CTypeError ,"error" ,CreateCValueError),
|
||||
|
||||
/* 27 */createCTypeInfo [any ](CTypeNil ,"nil" ,CreateCValueNil),
|
||||
|
||||
|
||||
// Los tipos compuestos, solo pueden crearse por reflexion, las listas de los tipos claves ya estan
|
||||
// definidas en el switch .(Type)
|
||||
/* 28 */createCTypeInfo [any ](CTypeObject ,"object" , CreateCValueObject),
|
||||
/* 29 */createCTypeInfo [any ](CTypeObject ,"lazy" , CreateCValueLazy),
|
||||
/* 30 */createCTypeInfo [any ](CTypeList ,"list" , CreateCValueList),
|
||||
/* 31 */createCTypeInfo [any ](CTypeMap ,"map" , CreateCValueMap),
|
||||
|
||||
// Corresponde con el bit del flag del tipo de mapa, por lo que no puede generar un cvalue valido
|
||||
//
|
||||
/* 32 */createCTypeInfo[any ](CTypeInvalid,"invalid" ,createCValueInvalid,
|
||||
func(i *cTypeInfo) {
|
||||
i.creators[createByPtr] = createCValueInvalid
|
||||
i.creators[createByList] = createCValueInvalid
|
||||
i.creators[createByLazy] = createCValueInvalid
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (i *cTypeInfos) getName(cType CType) string {
|
||||
if cType.IsComposite() {
|
||||
if cType.IsLazy () {
|
||||
return "lazy|" + i.getName(cType.BaseType())
|
||||
}
|
||||
if cType.IsList () {
|
||||
return "list|" + i.getName(cType.BaseType())
|
||||
}
|
||||
if cType.IsMap () {
|
||||
k, v := cType.MapType()
|
||||
return "map@" + i.getName(k) + "|" + i.getName(v)
|
||||
}
|
||||
}
|
||||
return i.types[getPos(cType)].name
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (i *cTypeInfos) createCValue (value any) CValue {
|
||||
if value == nil {
|
||||
return CValue{ vType: CTypeAny, vState: CStateNil }
|
||||
}
|
||||
|
||||
var f func(any) CValue
|
||||
|
||||
switch value.(type) {
|
||||
/* Valores simples */
|
||||
//case any : f = i.types[getPos(CTypeAny )].creators[createByValue]
|
||||
case bool : f = i.types[getPos(CTypeBool )].creators[createByValue]
|
||||
case int : f = i.types[getPos(CTypeInt )].creators[createByValue]
|
||||
case int8 : f = i.types[getPos(CTypeInt8 )].creators[createByValue]
|
||||
case int16 : f = i.types[getPos(CTypeInt16 )].creators[createByValue]
|
||||
case int32 : f = i.types[getPos(CTypeInt32 )].creators[createByValue]
|
||||
case int64 : f = i.types[getPos(CTypeInt64 )].creators[createByValue]
|
||||
case uint : f = i.types[getPos(CTypeUint )].creators[createByValue]
|
||||
case uint8 : f = i.types[getPos(CTypeUint8 )].creators[createByValue]
|
||||
case uint16 : f = i.types[getPos(CTypeUint16 )].creators[createByValue]
|
||||
case uint32 : f = i.types[getPos(CTypeUint32 )].creators[createByValue]
|
||||
case uint64 : f = i.types[getPos(CTypeUint64 )].creators[createByValue]
|
||||
case uintptr : f = i.types[getPos(CTypeUintptr )].creators[createByValue]
|
||||
case float32 : f = i.types[getPos(CTypeFloat32 )].creators[createByValue]
|
||||
case float64 : f = i.types[getPos(CTypeFloat64 )].creators[createByValue]
|
||||
case complex64 : f = i.types[getPos(CTypeComplex64 )].creators[createByValue]
|
||||
case complex128 : f = i.types[getPos(CTypeComplex128)].creators[createByValue]
|
||||
case Date : f = i.types[getPos(CTypeDate )].creators[createByValue]
|
||||
case Duration : f = i.types[getPos(CTypeDuration )].creators[createByValue]
|
||||
case string : f = i.types[getPos(CTypeString )].creators[createByValue]
|
||||
case Bytes : f = i.types[getPos(CTypeBytes )].creators[createByValue]
|
||||
case Stack : f = i.types[getPos(CTypeStack )].creators[createByValue]
|
||||
case CValue : f = i.types[getPos(CTypeCValue )].creators[createByValue]
|
||||
case Packable : f = i.types[getPos(CTypePackable )].creators[createByValue]
|
||||
case Context : f = i.types[getPos(CTypeContext )].creators[createByValue]
|
||||
case error : f = i.types[getPos(CTypeError )].creators[createByValue]
|
||||
|
||||
/* Valores Listas */
|
||||
case []any : f = i.types[getPos(CTypeAny )].creators[createByList]
|
||||
case []bool : f = i.types[getPos(CTypeBool )].creators[createByList]
|
||||
case []int : f = i.types[getPos(CTypeInt )].creators[createByList]
|
||||
case []int8 : f = i.types[getPos(CTypeInt8 )].creators[createByList]
|
||||
case []int16 : f = i.types[getPos(CTypeInt16 )].creators[createByList]
|
||||
case []int32 : f = i.types[getPos(CTypeInt32 )].creators[createByList]
|
||||
case []int64 : f = i.types[getPos(CTypeInt64 )].creators[createByList]
|
||||
case []uint : f = i.types[getPos(CTypeUint )].creators[createByList]
|
||||
// ya establecido como tipo base Bytes
|
||||
//case []uint8 :
|
||||
//
|
||||
case []uint16 : f = i.types[getPos(CTypeUint16 )].creators[createByList]
|
||||
case []uint32 : f = i.types[getPos(CTypeUint32 )].creators[createByList]
|
||||
case []uint64 : f = i.types[getPos(CTypeUint64 )].creators[createByList]
|
||||
case []uintptr : f = i.types[getPos(CTypeUintptr )].creators[createByList]
|
||||
case []float32 : f = i.types[getPos(CTypeFloat32 )].creators[createByList]
|
||||
case []float64 : f = i.types[getPos(CTypeFloat64 )].creators[createByList]
|
||||
case []complex64: f = i.types[getPos(CTypeComplex64 )].creators[createByList]
|
||||
case []complex128:f = i.types[getPos(CTypeComplex128)].creators[createByList]
|
||||
case []Duration : f = i.types[getPos(CTypeDate )].creators[createByList]
|
||||
case []Date : f = i.types[getPos(CTypeDuration )].creators[createByList]
|
||||
case []string : f = i.types[getPos(CTypeString )].creators[createByList]
|
||||
case []Bytes : f = i.types[getPos(CTypeBytes )].creators[createByList]
|
||||
case []Stack : f = i.types[getPos(CTypeStack )].creators[createByList]
|
||||
case []CValue : f = i.types[getPos(CTypeCValue )].creators[createByList]
|
||||
case []Packable : f = i.types[getPos(CTypePackable )].creators[createByList]
|
||||
case []Context : f = i.types[getPos(CTypeContext )].creators[createByList]
|
||||
case []error : f = i.types[getPos(CTypeError )].creators[createByList]
|
||||
|
||||
|
||||
/* Valores pasados por punteros */
|
||||
//case *any : f = i.types[ 1/* Any */].creators[createByPtr]
|
||||
case *bool : f = i.types[getPos(CTypeBool )].creators[createByPtr]
|
||||
case *int : f = i.types[getPos(CTypeInt )].creators[createByPtr]
|
||||
case *int8 : f = i.types[getPos(CTypeInt8 )].creators[createByPtr]
|
||||
case *int16 : f = i.types[getPos(CTypeInt16 )].creators[createByPtr]
|
||||
case *int32 : f = i.types[getPos(CTypeInt32 )].creators[createByPtr]
|
||||
case *int64 : f = i.types[getPos(CTypeInt64 )].creators[createByPtr]
|
||||
case *uint : f = i.types[getPos(CTypeUint )].creators[createByPtr]
|
||||
case *uint8 : f = i.types[getPos(CTypeUint8 )].creators[createByPtr]
|
||||
case *uint16 : f = i.types[getPos(CTypeUint16 )].creators[createByPtr]
|
||||
case *uint32 : f = i.types[getPos(CTypeUint32 )].creators[createByPtr]
|
||||
case *uint64 : f = i.types[getPos(CTypeUint64 )].creators[createByPtr]
|
||||
case *uintptr : f = i.types[getPos(CTypeUintptr )].creators[createByPtr]
|
||||
case *float32 : f = i.types[getPos(CTypeFloat32 )].creators[createByPtr]
|
||||
case *float64 : f = i.types[getPos(CTypeFloat64 )].creators[createByPtr]
|
||||
case *complex64 : f = i.types[getPos(CTypeComplex64 )].creators[createByPtr]
|
||||
case *complex128: f = i.types[getPos(CTypeComplex128)].creators[createByPtr]
|
||||
case *Duration : f = i.types[getPos(CTypeDate )].creators[createByPtr]
|
||||
case *Date : f = i.types[getPos(CTypeDuration )].creators[createByPtr]
|
||||
case *string : f = i.types[getPos(CTypeString )].creators[createByPtr]
|
||||
case *Bytes : f = i.types[getPos(CTypeBytes )].creators[createByPtr]
|
||||
case *Stack : f = i.types[getPos(CTypeStack )].creators[createByPtr]
|
||||
case *CValue : f = i.types[getPos(CTypeCValue )].creators[createByPtr]
|
||||
case *Packable : f = i.types[getPos(CTypePackable )].creators[createByPtr]
|
||||
case *Context : f = i.types[getPos(CTypeContext )].creators[createByPtr]
|
||||
case *error : f = i.types[getPos(CTypeError )].creators[createByPtr]
|
||||
|
||||
/* Valores pasados por functions Lazys */
|
||||
case func()any : f = i.types[getPos(CTypeAny )].creators[createByLazy]
|
||||
case func()bool : f = i.types[getPos(CTypeBool )].creators[createByLazy]
|
||||
case func()int : f = i.types[getPos(CTypeInt )].creators[createByLazy]
|
||||
case func()int8 : f = i.types[getPos(CTypeInt8 )].creators[createByLazy]
|
||||
case func()int16 : f = i.types[getPos(CTypeInt16 )].creators[createByLazy]
|
||||
case func()int32 : f = i.types[getPos(CTypeInt32 )].creators[createByLazy]
|
||||
case func()int64 : f = i.types[getPos(CTypeInt64 )].creators[createByLazy]
|
||||
case func()uint : f = i.types[getPos(CTypeUint )].creators[createByLazy]
|
||||
case func()uint8 : f = i.types[getPos(CTypeUint8 )].creators[createByLazy]
|
||||
case func()uint16 : f = i.types[getPos(CTypeUint16 )].creators[createByLazy]
|
||||
case func()uint32 : f = i.types[getPos(CTypeUint32 )].creators[createByLazy]
|
||||
case func()uint64 : f = i.types[getPos(CTypeUint64 )].creators[createByLazy]
|
||||
case func()uintptr : f = i.types[getPos(CTypeUintptr )].creators[createByLazy]
|
||||
case func()float32 : f = i.types[getPos(CTypeFloat32 )].creators[createByLazy]
|
||||
case func()float64 : f = i.types[getPos(CTypeFloat64 )].creators[createByLazy]
|
||||
case func()complex64: f = i.types[getPos(CTypeComplex64 )].creators[createByLazy]
|
||||
case func()complex128:f = i.types[getPos(CTypeComplex128)].creators[createByLazy]
|
||||
case func()Duration : f = i.types[getPos(CTypeDate )].creators[createByLazy]
|
||||
case func()Date : f = i.types[getPos(CTypeDuration )].creators[createByLazy]
|
||||
case func()string : f = i.types[getPos(CTypeString )].creators[createByLazy]
|
||||
case func()Bytes : f = i.types[getPos(CTypeBytes )].creators[createByLazy]
|
||||
case func()Stack : f = i.types[getPos(CTypeStack )].creators[createByLazy]
|
||||
case func()CValue : f = i.types[getPos(CTypeCValue )].creators[createByLazy]
|
||||
case func()Packable : f = i.types[getPos(CTypePackable )].creators[createByLazy]
|
||||
case func()Context : f = i.types[getPos(CTypeContext )].creators[createByLazy]
|
||||
case func()error : f = i.types[getPos(CTypeError )].creators[createByLazy]
|
||||
|
||||
default:
|
||||
|
||||
rv := reflect.ValueOf(value)
|
||||
if !rv.IsValid() {
|
||||
return createCValueWithError(value, CTypeAny,0,E.InvalidCValueReflected)
|
||||
}
|
||||
rt := rv.Type()
|
||||
|
||||
i.mux.RLock()
|
||||
f,ok := i.cache[rt]
|
||||
if ok {
|
||||
i.mux.RUnlock()
|
||||
break
|
||||
}
|
||||
i.mux.RUnlock()
|
||||
|
||||
vt := CTypeAny
|
||||
|
||||
switch rt.Kind() {
|
||||
// Los tipos soportados deben de haber sido capturados
|
||||
// por el switch de tipos
|
||||
case reflect.Struct : // createCValueAny
|
||||
vt = CTypeObject
|
||||
|
||||
case reflect.Func :
|
||||
if rt.NumIn() == 0 && rt.NumOut() == 1 {
|
||||
vt = CTypeLazy | CTypeAny
|
||||
}
|
||||
|
||||
case reflect.Map :
|
||||
var kt,et CType
|
||||
if kt = reflectKindToCType(rt.Key().Kind(),true); kt != CTypeInvalid {
|
||||
if et = reflectKindToCType(rt.Elem().Kind(),true); et != CTypeInvalid {
|
||||
vt = setMapType(kt,et)
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Slice,
|
||||
reflect.Array :
|
||||
ke := reflectKindToCType(rt.Elem().Kind(),true)
|
||||
if ke != CTypeInvalid {
|
||||
vt = ke| CTypeList
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
f = func(v any) CValue {
|
||||
t := vt
|
||||
return createCValueReflected(v,reflect.ValueOf(v), t,false)
|
||||
}
|
||||
|
||||
i.mux.Lock()
|
||||
i.cache[rv.Type()] = f
|
||||
i.mux.Unlock()
|
||||
}
|
||||
|
||||
|
||||
return f(value)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
func createCValueReflected (value any, rv reflect.Value, vtype CType, check bool) CValue {
|
||||
if !rv.IsValid() {
|
||||
return createCValueWithError(value,vtype,0,E.InvalidCValueReflected)
|
||||
}
|
||||
rt := rv.Type()
|
||||
vs := CStateReflected
|
||||
tn := rt.String()
|
||||
|
||||
switch rt.Kind() {
|
||||
|
||||
case reflect.Slice,
|
||||
reflect.Array:
|
||||
if check {
|
||||
if !vtype.IsList() {
|
||||
return createCValueWithError(value,vtype,vs,E.InvalidCValueForType)
|
||||
}
|
||||
ke := reflectKindToCType(rt.Elem().Kind(), true)
|
||||
if ke == CTypeInvalid {
|
||||
return createCValueWithError(value,vtype,vs,E.InvalidCValueForType)
|
||||
}
|
||||
vtype |= ke
|
||||
}
|
||||
ln := rv.Len()
|
||||
if ln == 0 {
|
||||
if rv.IsNil() {
|
||||
vs|=CStateNil
|
||||
} else {
|
||||
vs|= CStateZero
|
||||
}
|
||||
}
|
||||
return CValue{ vType: vtype,vState: vs, anyVal: value, strVal: tn, intVal: int64(ln) }
|
||||
|
||||
|
||||
case reflect.Map :
|
||||
if check {
|
||||
if !vtype.IsMap() {
|
||||
return createCValueWithError(value,vtype,vs|CStateInvalid,E.InvalidCValueForType)
|
||||
}
|
||||
kt := reflectKindToCType(rt.Key().Kind(), true)
|
||||
if kt == CTypeInvalid {
|
||||
return createCValueWithError(value,vtype,vs|CStateInvalid,E.InvalidCValueForType)
|
||||
}
|
||||
et := reflectKindToCType(rt.Elem().Kind(), true)
|
||||
if et == CTypeInvalid {
|
||||
return createCValueWithError(value,vtype,vs|CStateInvalid,E.InvalidCValueForType)
|
||||
}
|
||||
vtype = setMapType(kt, et)
|
||||
}
|
||||
ln := rv.Len()
|
||||
if ln == 0 {
|
||||
if rv.IsNil() {
|
||||
vs|=CStateNil
|
||||
} else {
|
||||
vs|= CStateZero
|
||||
}
|
||||
}
|
||||
return CValue{ vType: vtype,vState: vs, anyVal: value, strVal: tn, intVal: int64(ln) }
|
||||
|
||||
|
||||
case reflect.Func :
|
||||
if check {
|
||||
if !vtype.IsLazy() {
|
||||
return createCValueWithError(value,vtype,vs,E.InvalidCValueForType)
|
||||
}
|
||||
if rt.NumIn() != 0 || rt.NumOut() != 1 {
|
||||
return createCValueWithError(value,vtype,vs,E.InvalidCValueForType)
|
||||
}
|
||||
vtype = CTypeLazy | CTypeAny
|
||||
}
|
||||
if rv.IsNil() {
|
||||
vs|=CStateNil
|
||||
}
|
||||
return CValue{ vType: vtype,vState: vs, strVal: tn,
|
||||
anyVal: func() any {
|
||||
return (rv.Call(nil))[0].Interface()
|
||||
},
|
||||
}
|
||||
|
||||
case reflect.Struct :
|
||||
if check {
|
||||
if !vtype.IsObject() {
|
||||
return createCValueWithError(value,vtype,vs,E.InvalidCValueForType)
|
||||
}
|
||||
}
|
||||
return CValue{vType: vtype,vState: vs, anyVal: value, strVal: tn}
|
||||
|
||||
case reflect.Ptr:
|
||||
if rv.IsNil() {
|
||||
vs|=CStateNil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return CValue{ vType: vtype,vState: vs, anyVal: value, strVal: tn }
|
||||
}
|
||||
|
||||
|
||||
func createCValueRList (rv reflect.Value, vtype CType, check bool) CValue {
|
||||
vs := CStateReflected
|
||||
rt := rv.Type()
|
||||
tn := rt.String()
|
||||
|
||||
if check {
|
||||
if !vtype.IsList() {
|
||||
return createCValueWithError(rv,vtype,vs,E.InvalidCValueForType)
|
||||
}
|
||||
ke := reflectKindToCType(rt.Elem().Kind(), true)
|
||||
if ke == CTypeInvalid {
|
||||
return createCValueWithError(rv,vtype,vs,E.InvalidCValueForType)
|
||||
}
|
||||
vtype |= ke
|
||||
}
|
||||
ln := rv.Len()
|
||||
if ln == 0 {
|
||||
if rv.IsNil() {
|
||||
vs|=CStateNil
|
||||
} else {
|
||||
vs|= CStateZero
|
||||
}
|
||||
}
|
||||
|
||||
return CValue{ vType: vtype,vState: vs, anyVal: rv, strVal: tn, intVal: int64(ln) }
|
||||
}
|
||||
|
||||
|
||||
|
||||
func createCValueRMap (rv reflect.Value, vtype CType, check bool) CValue {
|
||||
vs := CStateReflected
|
||||
rt := rv.Type()
|
||||
tn := rt.String()
|
||||
|
||||
if check {
|
||||
if !vtype.IsMap() {
|
||||
return createCValueWithError(rv,vtype,vs|CStateInvalid,E.InvalidCValueForType)
|
||||
}
|
||||
kt := reflectKindToCType(rt.Key().Kind(), true)
|
||||
if kt == CTypeInvalid {
|
||||
return createCValueWithError(rv,vtype,vs|CStateInvalid,E.InvalidCValueForType)
|
||||
}
|
||||
et := reflectKindToCType(rt.Elem().Kind(), true)
|
||||
if et == CTypeInvalid {
|
||||
return createCValueWithError(rv,vtype,vs|CStateInvalid,E.InvalidCValueForType)
|
||||
}
|
||||
vtype = setMapType(kt, et)
|
||||
}
|
||||
|
||||
ln := rv.Len()
|
||||
if ln == 0 {
|
||||
if rv.IsNil() {
|
||||
vs|=CStateNil
|
||||
} else {
|
||||
vs|= CStateZero
|
||||
}
|
||||
}
|
||||
return CValue{ vType: vtype,vState: vs, anyVal: rv, strVal: tn, intVal: int64(ln) }
|
||||
}
|
||||
|
||||
|
||||
func createCValueRLazy (rv reflect.Value, vtype CType, check bool) CValue {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func getPos (t CType) int {
|
||||
if t == 0 {
|
||||
// Si 't' es CType(0) (que corresponde a CTypeInvalid),
|
||||
// se le asigna el índice 0. Esto es consistente con 'cTypeInfos[0]'
|
||||
// albergando la información para el tipo inválido.
|
||||
return 0
|
||||
}
|
||||
// Calcula la posición del bit '1' más a la derecha en la representación binaria de 't'.
|
||||
//
|
||||
// Para los CType definidos como potencias de 2 (ej. 1 << iota, donde iota es el índice del bit),
|
||||
// bits.TrailingZeros32(uint32(t)) devuelve precisamente ese índice del bit (0-based).
|
||||
//
|
||||
// Al sumar '+1' al resultado, convertimos este índice de bit (0-based)
|
||||
// en una "posición" o "rango" basado en 1.
|
||||
//
|
||||
// Esto es crucial para indexar el array 'cTypeInfos [33]CTypeInfo',
|
||||
// ya que:
|
||||
// - CTypeInvalid (0) mapea a 'cTypeInfos[0]'.
|
||||
// - El CType correspondiente al bit 0 (valor 1) mapea a 'cTypeInfos[1]'.
|
||||
// - El CType correspondiente al bit 1 (valor 2) mapea a 'cTypeInfos[2]'.
|
||||
// - ... y así sucesivamente, hasta el CType para el bit 31 (valor 1 << 31)
|
||||
// que mapearía al índice 32, el último índice válido en el array de 33 posiciones.
|
||||
return bits.TrailingZeros32(uint32(t))+1
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func reflectKindToCType (kind reflect.Kind, base bool) CType {
|
||||
switch kind {
|
||||
case reflect.Invalid: return CTypeInvalid
|
||||
case reflect.Bool: return CTypeBool
|
||||
case reflect.Int: return CTypeInt
|
||||
case reflect.Int8: return CTypeInt8
|
||||
case reflect.Int16: return CTypeInt16
|
||||
case reflect.Int32: return CTypeInt32
|
||||
case reflect.Int64: return CTypeInt64
|
||||
case reflect.Uint: return CTypeUint
|
||||
case reflect.Uint8: return CTypeUint8
|
||||
case reflect.Uint16: return CTypeUint16
|
||||
case reflect.Uint32: return CTypeUint32
|
||||
case reflect.Uint64: return CTypeUint64
|
||||
case reflect.Uintptr: return CTypeUintptr
|
||||
case reflect.Float32: return CTypeFloat32
|
||||
case reflect.Float64: return CTypeFloat64
|
||||
case reflect.Complex64: return CTypeComplex64
|
||||
case reflect.Complex128:return CTypeComplex128
|
||||
case reflect.String: return CTypeString
|
||||
case reflect.Struct: return CTypeObject
|
||||
|
||||
case reflect.Array,
|
||||
reflect.Slice:
|
||||
if base {
|
||||
return CTypeList
|
||||
}
|
||||
case reflect.Map:
|
||||
if base {
|
||||
return CTypeMap
|
||||
}
|
||||
case reflect.Func:
|
||||
if base {
|
||||
return CTypeLazy
|
||||
}
|
||||
}
|
||||
|
||||
return CTypeAny
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,286 @@
|
||||
// =============================================================================
|
||||
// GO·AT Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 10/06/2025
|
||||
// =============================================================================
|
||||
|
||||
package cdts
|
||||
|
||||
import "math"
|
||||
|
||||
type (
|
||||
|
||||
CValue struct {
|
||||
_ [0]func()
|
||||
|
||||
vType CType
|
||||
vState CState
|
||||
|
||||
intVal int64
|
||||
strVal string
|
||||
anyVal any
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
func CreateCValue (value any) CValue {
|
||||
|
||||
|
||||
return CreateCValueAny(value)
|
||||
}
|
||||
|
||||
|
||||
func CreateCValueAny (value any) CValue {
|
||||
if value == nil {
|
||||
return CValue{ vType: CTypeAny, vState: CStateNil }
|
||||
}
|
||||
return CValue{ vType: CTypeAny, anyVal: value }
|
||||
}
|
||||
|
||||
|
||||
func CreateCValueBool (value bool) CValue {
|
||||
if !value {
|
||||
return CValue{ vType: CTypeBool, vState: CStateZero }
|
||||
}
|
||||
return CValue{vType: CTypeBool, intVal: 1}
|
||||
}
|
||||
|
||||
|
||||
// Int's
|
||||
|
||||
func CreateCValueInt (value int) CValue {
|
||||
if value == 0 {
|
||||
return CValue{ vType: CTypeInt, vState: CStateZero }
|
||||
}
|
||||
return CValue{vType: CTypeInt, intVal: int64(value) }
|
||||
}
|
||||
|
||||
func CreateCValueInt8 (value int8) CValue {
|
||||
if value == 0 {
|
||||
return CValue{ vType: CTypeInt8, vState: CStateZero }
|
||||
}
|
||||
return CValue{vType: CTypeInt8, intVal: int64(value)}
|
||||
}
|
||||
|
||||
func CreateCValueInt16(value int16) CValue {
|
||||
if value == 0 {
|
||||
return CValue{ vType: CTypeInt16, vState: CStateZero }
|
||||
}
|
||||
return CValue{vType: CTypeInt16, intVal: int64(value)}
|
||||
}
|
||||
|
||||
func CreateCValueInt32 (value int32) CValue {
|
||||
if value == 0 {
|
||||
return CValue{ vType: CTypeInt32, vState: CStateZero }
|
||||
}
|
||||
return CValue{vType: CTypeInt32, intVal: int64(value)}
|
||||
}
|
||||
|
||||
func CreateCValueInt64 (value int64 ) CValue {
|
||||
if value == 0 { return CValue{ vType: CTypeInt64, vState: CStateZero } }
|
||||
return CValue{ vType: CTypeInt64, intVal: value }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Uint's
|
||||
|
||||
func CreateCValueUint (value uint) CValue {
|
||||
if value == 0 { return CValue{ vType: CTypeUint, vState: CStateZero } }
|
||||
return CValue{ vType: CTypeUint, intVal: int64(value) }
|
||||
}
|
||||
|
||||
func CreateCValueUint8 (value uint8) CValue {
|
||||
if value == 0 { return CValue{ vType: CTypeUint8, vState: CStateZero } }
|
||||
return CValue{ vType: CTypeUint8, intVal: int64(value) }
|
||||
}
|
||||
|
||||
func CreateCValueUint16 (value uint16) CValue {
|
||||
if value == 0 { return CValue{ vType: CTypeUint16, vState: CStateZero } }
|
||||
return CValue{ vType: CTypeUint16, intVal: int64(value) }
|
||||
}
|
||||
|
||||
func CreateCValueUint32 (value uint32) CValue {
|
||||
if value == 0 { return CValue{ vType: CTypeUint32, vState: CStateZero } }
|
||||
return CValue{ vType: CTypeUint32, intVal: int64(value) }
|
||||
}
|
||||
|
||||
func CreateCValueUint64 (value uint64) CValue {
|
||||
if value == 0 { return CValue{ vType: CTypeUint64, vState: CStateZero } }
|
||||
return CValue{ vType: CTypeUint64, intVal: int64(value) }
|
||||
}
|
||||
|
||||
|
||||
func CreateCValueUintptr (value uintptr) CValue {
|
||||
if value == 0 { return CValue{ vType: CTypeUintptr, vState: CStateZero } }
|
||||
return CValue{ vType: CTypeUintptr, intVal: int64(value) }
|
||||
}
|
||||
|
||||
|
||||
// Floats
|
||||
|
||||
func CreateCValueFloat32 (value float32) CValue {
|
||||
if value == 0.0 { // Comprobación directa para el valor cero
|
||||
return CValue{vType: CTypeFloat32, vState: CStateZero}
|
||||
}
|
||||
return CValue{vType: CTypeFloat32, intVal: int64(math.Float32bits(value))}
|
||||
}
|
||||
|
||||
func CreateCValueFloat64 (value float64) CValue {
|
||||
if value == 0.0 { // Comprobación directa para el valor cero
|
||||
return CValue{vType: CTypeFloat64, vState: CStateZero}
|
||||
}
|
||||
return CValue{vType: CTypeFloat64, intVal: int64(math.Float64bits(value))}
|
||||
}
|
||||
|
||||
func CreateCValueComplex64 (value complex64) CValue {
|
||||
if value == 0 { // Comprobación directa para el valor cero
|
||||
return CValue{vType: CTypeComplex64, vState: CStateZero }
|
||||
}
|
||||
return CValue{vType: CTypeComplex64, anyVal: value}
|
||||
}
|
||||
|
||||
func CreateCValueComplex128 (value complex128) CValue {
|
||||
if value == 0 { // Comprobación directa para el valor cero
|
||||
return CValue{vType: CTypeComplex128, vState: CStateZero }
|
||||
}
|
||||
return CValue{vType: CTypeComplex128, anyVal: value}
|
||||
}
|
||||
|
||||
|
||||
func CreateCValueDuration (value Duration) CValue {
|
||||
if value == 0 {
|
||||
return CValue{vType: CTypeDuration, vState: CStateZero}
|
||||
}
|
||||
return CValue{vType: CTypeDuration, intVal: int64(value)}
|
||||
}
|
||||
|
||||
func CreateCValueDate (value Date) CValue {
|
||||
if value.IsZero() { // Comprobación directa para el valor cero
|
||||
return CValue{vType: CTypeDate, vState: CStateZero}
|
||||
}
|
||||
if value.After(g.minTime) && value.Before(g.maxTime) {
|
||||
return CValue{vType: CTypeDate, vState: CStateShort,intVal: value.UnixNano(), anyVal: value.Location()}
|
||||
}
|
||||
return CValue{vType: CTypeDate, anyVal: value }
|
||||
}
|
||||
|
||||
|
||||
func CreateCValueString (value string) CValue {
|
||||
if value == "" { // Comprobación directa para el valor cero
|
||||
return CValue{vType: CTypeString, vState: CStateZero}
|
||||
}
|
||||
return CValue{vType: CTypeString, strVal: value}
|
||||
}
|
||||
|
||||
func CreateCValueBytes (value []uint8) CValue {
|
||||
l := len(value)
|
||||
if l == 0 {
|
||||
if value == nil {
|
||||
return CValue{vType: CTypeBytes, vState: CStateNil}
|
||||
} else {
|
||||
return CValue{vType: CTypeBytes, vState: CStateZero,anyVal: value}
|
||||
}
|
||||
}
|
||||
return CValue{vType: CTypeBytes, anyVal: value, intVal: int64(l)}
|
||||
}
|
||||
|
||||
func CreateCValueStack (value Stack) CValue {
|
||||
l := len(value)
|
||||
if l == 0 {
|
||||
if value == nil {
|
||||
return CValue{vType: CTypeStack, vState: CStateNil}
|
||||
} else {
|
||||
return CValue{vType: CTypeStack, vState: CStateZero,anyVal: value}
|
||||
}
|
||||
}
|
||||
return CValue{vType: CTypeStack, anyVal: value, intVal: int64(l)}
|
||||
}
|
||||
|
||||
|
||||
func createCValueCValue (value CValue) CValue {
|
||||
return CValue{vType: CTypeCValue, anyVal: value } }
|
||||
|
||||
|
||||
|
||||
func CreateCValuePackable (value Packable) CValue {
|
||||
if value == nil {
|
||||
return CValue{vType: CTypePackable, vState: CStateNil}
|
||||
}
|
||||
return CValue{ vType: CTypePackable, anyVal: value }
|
||||
}
|
||||
|
||||
func CreateCValueContext (value Context) CValue {
|
||||
if value == nil {
|
||||
return CValue{vType: CTypeContext, vState: CStateNil}
|
||||
}
|
||||
return CValue{vType: CTypeContext, anyVal: value}
|
||||
}
|
||||
|
||||
func CreateCValueError (value error) CValue {
|
||||
if value == nil {
|
||||
return CValue{vType: CTypeError, vState: CStateNil}
|
||||
}
|
||||
return CValue{ vType: CTypeError, anyVal: value }
|
||||
}
|
||||
|
||||
func CreateCValueNil (_ any) CValue {
|
||||
return CValue{ vType: CTypeNil, vState: CStateNil }
|
||||
}
|
||||
|
||||
|
||||
func CreateCValueObject(value any) CValue {
|
||||
return createCValueReflected(value,CTypeObject)
|
||||
}
|
||||
|
||||
func CreateCValueLazy(value any) CValue {
|
||||
return createCValueReflected(value,CTypeLazy)
|
||||
}
|
||||
|
||||
func CreateCValueList(value any) CValue {
|
||||
return createCValueReflected(value,CTypeList)
|
||||
}
|
||||
|
||||
func CreateCValueMap(value any) CValue {
|
||||
return createCValueReflected(value,CTypeMap)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func createCValueInvalid (_ any) CValue {
|
||||
return CValue{ vType: CTypeInvalid, vState: CStateNil|CStateZero|CStateInvalid }
|
||||
}
|
||||
|
||||
func createCValueWithError (value any, vtype CType, vstate CState, er string) CValue {
|
||||
return CValue{
|
||||
vType : CTypeInvalid,
|
||||
vState: CStateInvalid|CStateError|vstate,
|
||||
intVal: int64(vtype),
|
||||
anyVal: value,
|
||||
strVal: er,
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
// =============================================================================
|
||||
// GO·AT Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 10/06/2025
|
||||
// =============================================================================
|
||||
|
||||
package cdts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
Date = time.Time
|
||||
Duration = time.Duration
|
||||
|
||||
Bytes = []uint8
|
||||
Stack = []interface { m () int }
|
||||
|
||||
Context = context.Context
|
||||
|
||||
Packable = interface { a()}
|
||||
MapPackable = interface { p()}
|
||||
ObjectPackable = interface {}
|
||||
ListPackable = interface {}
|
||||
)
|
||||
@ -0,0 +1,3 @@
|
||||
module base
|
||||
|
||||
go 1.24
|
||||
@ -0,0 +1,228 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 07/05/2025
|
||||
// =============================================================================
|
||||
|
||||
// Package errs provides a robust infrastructure for structured error management
|
||||
// in Go, specifically designed for distributed systems and microservices.
|
||||
// It allows for hierarchical error classification, contextual metadata composition,
|
||||
// and rich formatting to facilitate debugging and monitoring.
|
||||
package errs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// errModuleSep is the separator used between the module name and the error class.
|
||||
errModuleSep string = "::"
|
||||
// errClassSep is the separator used between subclasses of an error.
|
||||
errClassSep string = "."
|
||||
|
||||
// moduleName defines the default module name for internal package errors.
|
||||
moduleName = errModuleSep
|
||||
)
|
||||
|
||||
const (
|
||||
// MetaClassName is the standard key name for the metadata representing the error class.
|
||||
MetaClassName string = "class"
|
||||
// MetaCauseName is the standard key name for the metadata representing the cause of an error.
|
||||
MetaCauseName string = "cause"
|
||||
// MetaStackName is the standard key name for the metadata representing the cause of an error.
|
||||
MetaStackName string = "stack"
|
||||
)
|
||||
|
||||
var (
|
||||
// g contains global variables and configurations for the errs package.
|
||||
g = struct {
|
||||
// Regular expression validators for metadata names, subclasses, and error classes.
|
||||
metaValidator,
|
||||
subclassValidator,
|
||||
classValidator *regexp.Regexp
|
||||
|
||||
// formatOptions defines the formatting options for error representation.
|
||||
formatOptions *FormatOptions
|
||||
// errorFormatter is the function used to format errors.
|
||||
errorFormatter func(w io.Writer, e error, o *FormatOptions, l int, s FormatShow)
|
||||
}{
|
||||
// metaValidator checks if a metadata name is valid.
|
||||
metaValidator: regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]{0,62}[a-zA-Z0-9]$`),
|
||||
// classValidator checks if an error class name (including optional module) is valid.
|
||||
classValidator: regexp.MustCompile(`^(?:[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9])?|)::[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9])?$`),
|
||||
// subclassValidator checks if a subclass name is valid.
|
||||
subclassValidator: regexp.MustCompile("^[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9])?$"),
|
||||
|
||||
// formatOptions is initialized with default color formatting options.
|
||||
formatOptions: NewFormatOptionsColor(),
|
||||
// errorFormatter is initialized with the default error formatting function.
|
||||
errorFormatter: defaultFormatError,
|
||||
}
|
||||
|
||||
// E contains a collection of predefined errors used internally by the errs package.
|
||||
E = struct {
|
||||
// Multiple indicates that an operation resulted in multiple errors.
|
||||
Multiple,
|
||||
// InvalidNilError indicates that a nil error was provided where not allowed.
|
||||
InvalidNilError,
|
||||
// InvalidClass indicates that the provided error class name is invalid.
|
||||
InvalidClass,
|
||||
// InvalidErrValue indicates that the provided Err value is invalid.
|
||||
InvalidErrValue,
|
||||
// InvalidMetaName indicates that the provided metadata name is invalid.
|
||||
InvalidMetaName,
|
||||
// InvalidMetaType indicates that the provided metadata type is invalid.
|
||||
InvalidMetaType,
|
||||
// InvalidNilCause indicates that a nil cause was provided where not allowed.
|
||||
InvalidNilCause Err
|
||||
}{
|
||||
Multiple: Err(moduleName + "multiple_errors"),
|
||||
InvalidErrValue: Err(moduleName + "invalid_err_name"),
|
||||
InvalidClass: Err(moduleName + "invalid_class"),
|
||||
InvalidNilError: Err(moduleName + "invalid_nil_error"),
|
||||
InvalidMetaName: Err(moduleName + "invalid_meta_name"),
|
||||
InvalidMetaType: Err(moduleName + "invalid_meta_type"),
|
||||
InvalidNilCause: Err(moduleName + "invalid_nil_cause"),
|
||||
}
|
||||
)
|
||||
|
||||
// CreateSubclassOf creates a new subclass of an existing parent error.
|
||||
// The subclass name is appended to the parent error name using errClassSep.
|
||||
// Panic if the parent or subclass are not valid error names.
|
||||
func CreateSubclassOf(parent Err, subclass string) Err {
|
||||
if !IsValidSubclass(parent, subclass) {
|
||||
panic(CreateParamErr("subclass", subclass))
|
||||
}
|
||||
return Err(string(parent) + errClassSep + subclass)
|
||||
}
|
||||
|
||||
// ToError converts a value of any type to an error.
|
||||
// If the value is nil, it returns nil.
|
||||
// If the value is an error, it returns it directly.
|
||||
// If the value is a slice of errors ([]error), it returns a composed error
|
||||
// with E.Multiple and the causes attached (if the slice is not empty).
|
||||
// For any other type, it uses fmt.Errorf to create a basic error.
|
||||
func ToError(err any) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
switch e := err.(type) {
|
||||
case error:
|
||||
return e
|
||||
case []error:
|
||||
if len(e) == 0 {
|
||||
return nil
|
||||
}
|
||||
//todo change a multiError
|
||||
//return ercs.Compose(E.Multiple, ercs.WithCauses(e...))
|
||||
}
|
||||
return fmt.Errorf("%v", err)
|
||||
}
|
||||
|
||||
// ErrorToString converts an error to its string representation.
|
||||
// If the error is nil, it returns an empty string.
|
||||
// If the error is of type Err, it returns its underlying string value.
|
||||
// If the error implements fmt.Stringer, it uses its String() method.
|
||||
// Otherwise, it uses the error's Error() method.
|
||||
func ErrorToString(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch e := err.(type) {
|
||||
case Err:
|
||||
return string(e)
|
||||
case fmt.Stringer:
|
||||
return e.String()
|
||||
default:
|
||||
return err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
// IsSubclassOf checks if 'err' is a subclass of 'parent'.
|
||||
// This is checked for both Err types (using the hierarchy defined by errClassSep)
|
||||
// and standard errors (checking if the error string starts with the parent string + ".").
|
||||
// Returns false if either error is nil.
|
||||
func IsSubclassOf(err, parent error) bool {
|
||||
if err == nil || parent == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Specific check for Err types
|
||||
var e, p Err
|
||||
if errors.As(err, &e) && errors.As(parent, &p) {
|
||||
return e.IsSubclassOf(p)
|
||||
}
|
||||
|
||||
// Generic check for errors implementing Unwrap
|
||||
for e := err; e != nil; e = errors.Unwrap(e) {
|
||||
errStr := ErrorToString(e)
|
||||
parentStr := ErrorToString(parent)
|
||||
if errStr == parentStr || strings.HasPrefix(errStr, parentStr+".") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsValidErr checks if a string is a valid error name according to the rules defined by classValidator.
|
||||
func IsValidErr(value string) bool {
|
||||
return len(value) > 0 && g.classValidator.MatchString(value)
|
||||
}
|
||||
|
||||
// IsValidClass checks if a string is a valid class name according to the rules defined by classValidator.
|
||||
func IsValidClass(class string) bool {
|
||||
return len(class) > 0 && g.classValidator.MatchString(class)
|
||||
}
|
||||
|
||||
// IsValidSubclass checks if 'subclass' is a valid subclass name for the 'parent' error.
|
||||
// It verifies that both the parent and subclass are valid names and that the subclass is not identical
|
||||
// to the final name of the parent (to prevent subclasses from having the same name as their direct parent).
|
||||
func IsValidSubclass(parent Err, subclass string) bool {
|
||||
if !IsValidErr(string(parent)) {
|
||||
return false
|
||||
}
|
||||
if !IsValidClass(subclass) { // Should this be IsValidSubclass name?
|
||||
return false
|
||||
}
|
||||
|
||||
// Extract the final name of the parent class (e.g., "format" from "modulo::validation.format")
|
||||
parentName := string(parent)
|
||||
if idx := strings.LastIndex(parentName, errClassSep); idx != -1 {
|
||||
parentFinalName := parentName[idx+len(errClassSep):]
|
||||
return subclass != parentFinalName
|
||||
}
|
||||
// If no errClassSep, use the class name after errModuleSep
|
||||
if c, h := strings.CutPrefix(parentName, errModuleSep); h {
|
||||
return subclass != c
|
||||
}
|
||||
// If neither errClassSep nor errModuleSep is present, compare with the full parent name.
|
||||
return subclass != parentName
|
||||
}
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 17/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
type (
|
||||
// Causer is an interface that can be implemented by errors that have an underlying cause.
|
||||
// It is similar to Go 1.13+'s Unwrap interface, but specifically for a single cause.
|
||||
Causer interface {
|
||||
// Cause returns the error that caused this error.
|
||||
Cause() error
|
||||
}
|
||||
|
||||
// CauseFnc is a function type that implements the Causer interface.
|
||||
// It allows an anonymous function or an existing function to act as a cause.
|
||||
CauseFnc func() error
|
||||
)
|
||||
|
||||
// Cause implements the Causer interface for CauseFnc, executing the underlying function.
|
||||
func (f CauseFnc) Cause() error { return f() }
|
||||
@ -0,0 +1,45 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 17/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
type (
|
||||
// Causers is an interface that can be implemented by errors that have multiple underlying causes.
|
||||
// This is useful for errors that aggregate failures from multiple operations.
|
||||
Causers interface {
|
||||
// Causes returns a slice of errors that caused this error.
|
||||
Causes() []error
|
||||
}
|
||||
|
||||
// CausesFnc is a function type that implements the Causers interface.
|
||||
// It allows an anonymous function or an existing function to act as a provider of multiple causes.
|
||||
CausesFnc func() []error
|
||||
)
|
||||
|
||||
// Causes implements the Causers interface for CausesFnc, executing the underlying function.
|
||||
func (f CausesFnc) Causes() []error { return f() }
|
||||
@ -0,0 +1,129 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 07/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
import (
|
||||
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Err is the fundamental type for structured errors in this package.
|
||||
// It represents an error with a hierarchical class name (e.g., "module::class.subclass").
|
||||
// It implements the standard Go error interface.
|
||||
type Err string
|
||||
|
||||
// CreateErr creates a new Err instance with the provided string value.
|
||||
// It validates that the value is a valid error name.
|
||||
// Panics if the value is not valid.
|
||||
func CreateErr(value string) Err {
|
||||
if !IsValidErr(value) {
|
||||
// Panics with an error indicating an invalid Err value and the cause (the parameter error).
|
||||
panic(E.InvalidErrValue)
|
||||
}
|
||||
return Err(value)
|
||||
}
|
||||
|
||||
// Module extracts the module name from the error, if present.
|
||||
// The module is the part before the first "::".
|
||||
// Returns an empty string if no module is present.
|
||||
func (e Err) Module() string {
|
||||
// Uses strings.CutSuffix to find and remove the "::" suffix if it exists.
|
||||
if m, h := strings.CutSuffix(string(e), errModuleSep); h {
|
||||
return m
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Class extracts the class name from the error.
|
||||
// The class is the part after the first "::", or the full name if no module is present.
|
||||
func (e Err) Class() string {
|
||||
s := string(e)
|
||||
// Uses strings.CutPrefix to find and remove the "::" prefix if it exists.
|
||||
if n, h := strings.CutPrefix(s, errModuleSep); h {
|
||||
return n
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Parent returns the parent error in the subclass hierarchy, if it exists.
|
||||
// For example, for "module::class.subclass", it returns "module::class".
|
||||
// The second boolean value is true if a parent was found, false otherwise.
|
||||
func (e Err) Parent() (Err, bool) {
|
||||
s := string(e)
|
||||
// Finds the last class separator ".".
|
||||
if idx := strings.LastIndex(s, errClassSep); idx != -1 {
|
||||
// Returns the substring up to the last separator as the parent error.
|
||||
return Err(s[:idx]), true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// Error implements the standard Go error interface.
|
||||
// It returns the string representation of the error.
|
||||
func (e Err) Error() string { return string(e) }
|
||||
|
||||
// String implements the fmt.Stringer interface.
|
||||
// It returns the string representation of the error.
|
||||
func (e Err) String() string { return string(e) }
|
||||
|
||||
// IsSubclassOf checks if this Err error is a subclass of the 'parent' error.
|
||||
// It checks if the string of this error starts with the string of the parent followed by the class separator ".".
|
||||
// It also verifies that the errors are not identical and that this error is longer than the parent.
|
||||
// Returns false if the parent is not of type Err.
|
||||
func (e Err) IsSubclassOf(parent error) bool {
|
||||
var p Err
|
||||
// Attempts to convert the parent error to type Err.
|
||||
if errors.As(parent, &p) {
|
||||
s, ps := string(e), string(p)
|
||||
// Checks if the string of this error starts with the parent string + "."
|
||||
// and if the strings are different and this one is longer.
|
||||
return s != ps && len(s) > len(ps) && strings.HasPrefix(s, ps+errClassSep)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Is implements Go 1.13+'s errors.Is interface.
|
||||
// It checks if this Err error is equal to the 'target' error or if it is a subclass of 'target'.
|
||||
// The exact check (e == target) is performed first.
|
||||
func (e Err) Is(target error) bool {
|
||||
// Exact check first: if this Err error is identical to the target (if the target is also Err).
|
||||
var t Err
|
||||
if errors.As(target, &t) && e == t {
|
||||
return true
|
||||
}
|
||||
|
||||
// Hierarchy check: if this error is a subclass of the target.
|
||||
return IsSubclassOf(e, target)
|
||||
}
|
||||
|
||||
// Unwrap implements Go 1.13+'s errors.Unwrap interface.
|
||||
// For the base Err type, there is no wrapped error, so it returns nil.
|
||||
func (_ Err) Unwrap() error { return nil }
|
||||
|
||||
@ -0,0 +1,122 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 13/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
// ErrorList is a slice of errors with helper methods for managing the list.
|
||||
// It can contain nil errors.
|
||||
type ErrorList []error
|
||||
|
||||
// Any returns true if the list contains at least one non-nil error.
|
||||
func (l ErrorList) Any() bool {
|
||||
for _, e := range l {
|
||||
if e != nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Len returns the total length of the error list, including nil errors.
|
||||
func (l ErrorList) Len() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
// Count returns the number of non-nil errors in the list.
|
||||
func (l ErrorList) Count() int {
|
||||
c := 0
|
||||
for _, e := range l {
|
||||
if e != nil {
|
||||
c++
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// First returns the first non-nil error in the list.
|
||||
// If no non-nil error exists, returns nil.
|
||||
func (l ErrorList) First() error {
|
||||
for _, e := range l {
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Last returns the last non-nil error in the list.
|
||||
// If no non-nil error exists, returns nil.
|
||||
func (l ErrorList) Last() error {
|
||||
for i := len(l) - 1; i >= 0; i-- {
|
||||
if l[i] != nil {
|
||||
return l[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Append adds an error to the end of the list, regardless of whether it's nil.
|
||||
// Returns the modified error list.
|
||||
func (l ErrorList) Append(err error) ErrorList {
|
||||
return append(l, err)
|
||||
}
|
||||
|
||||
// AppendNotNil adds an error to the list only if it's not nil.
|
||||
// Returns the modified error list or the original list if the error was nil.
|
||||
func (l ErrorList) AppendNotNil(err error) ErrorList {
|
||||
if err != nil {
|
||||
return append(l, err)
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// Reset removes all errors from the list by resetting its length to zero.
|
||||
// Returns the emptied error list.
|
||||
func (l ErrorList) Reset() ErrorList {
|
||||
return l[:0]
|
||||
}
|
||||
|
||||
// Clean removes any nil errors from the list.
|
||||
// Returns a new error list containing only non-nil errors.
|
||||
func (l ErrorList) Clean() ErrorList {
|
||||
return l.filter(func(e error) bool {
|
||||
return e != nil
|
||||
})
|
||||
}
|
||||
|
||||
// filter creates a new error list containing only errors that satisfy the filter function.
|
||||
// This is an internal helper method.
|
||||
func (l ErrorList) filter(filter func(error) bool) ErrorList {
|
||||
rs := make([]error, 0, len(l))
|
||||
for _, e := range l {
|
||||
if filter(e) {
|
||||
rs = append(rs, e)
|
||||
}
|
||||
}
|
||||
return rs
|
||||
}
|
||||
@ -0,0 +1,143 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 16/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Format is the main entry point for formatting errors using the package's capabilities.
|
||||
// It is typically called by types implementing fmt.Formatter.
|
||||
// It delegates the actual formatting to the configured errorFormatter.
|
||||
func Format(err error, f fmt.State, verb rune) {
|
||||
// Delegates formatting to the global errorFormatter, passing formatting state,
|
||||
// the error, current format options, initial indentation level (0),
|
||||
// and formatting show options derived from the fmt verb and flags.
|
||||
g.errorFormatter(f, err, g.formatOptions, 0, ShowOptionsFromVerb(f, verb))
|
||||
}
|
||||
|
||||
// defaultFormatError provides a default implementation for formatting errors.
|
||||
// It recursively formats the error and its wrapped errors (causes), displaying
|
||||
// error messages, metadata, and stack traces based on the provided options and show flags.
|
||||
func defaultFormatError(w io.Writer, err error, opts *FormatOptions, level int, show FormatShow) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var el []error // Slice to collect wrapped errors (causes) for recursive formatting
|
||||
var stack *Meta // Pointer to store the stack trace metadata if found
|
||||
|
||||
// Determine which metadata to select based on show options.
|
||||
sm := MetaTypeValue
|
||||
if show.ShowStack() {
|
||||
sm |= MetaTypeStack
|
||||
}
|
||||
// If not showing hierarchy, don't select cause metadata at the current level
|
||||
// to avoid duplicating cause information in the flat metadata list.
|
||||
if !show.ShowHierarchy() {º
|
||||
sm |= MetaTypeCause
|
||||
}
|
||||
|
||||
// Calculate the indentation for the current level.
|
||||
indent := strings.Repeat(opts.Indent, level)
|
||||
|
||||
// Format the current error message. Use different formats for the root error (level 0) and causes.
|
||||
if level == 0 {
|
||||
_, _ = fmt.Fprintf(w, opts.FmtError, indent, err.Error())
|
||||
} else {
|
||||
_, _ = fmt.Fprintf(w, opts.FmtCause, indent, err.Error())
|
||||
}
|
||||
|
||||
// Iterate through the error chain using errors.Unwrap.
|
||||
for e := err; e != nil; e = errors.Unwrap(e) {
|
||||
// If showing metadata and the current error provides metadata.
|
||||
if show.ShowMetas() {
|
||||
if mp, ok := e.(MetadataProvider); ok {
|
||||
// Get metadata based on the current selection criteria.
|
||||
ml := mp.Metadata(sm)
|
||||
for _, m := range ml {
|
||||
// Handle stack trace metadata separately if selected.
|
||||
if sm.SelectStack() && m.mType == MetaTypeStack {
|
||||
stack = &m
|
||||
// Remove MetaSelectStack from selection for subsequent metadata at this level.
|
||||
sm &^= MetaTypeStack
|
||||
continue
|
||||
}
|
||||
// If showing hierarchy, skip cause metadata here to avoid duplication.
|
||||
if show.ShowHierarchy() && sm.SelectCause() && m.mType == MetaTypeCause {
|
||||
continue
|
||||
}
|
||||
// Format other metadata.
|
||||
_, _ = fmt.Fprintf(w, opts.FmtMeta, indent, m.Name, m.Value())
|
||||
}
|
||||
}
|
||||
}
|
||||
// If showing hierarchy, collect the wrapped errors (causes) for recursive formatting.
|
||||
if show.ShowHierarchy() {
|
||||
switch cs := e.(type) {
|
||||
case Causer:
|
||||
// Handle single cause errors.
|
||||
el = append(el, cs.Cause())
|
||||
case Causers:
|
||||
// Handle errors with multiple causes.
|
||||
el = append(el, cs.Causes()...)
|
||||
case interface{ Unwrap() []error }:
|
||||
// Handle errors implementing the Unwrap() []error interface (Go 1.20+).
|
||||
el = cs.Unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively format the collected wrapped errors (causes).
|
||||
if len(el) > 0 {
|
||||
// Adjust show options for deep formatting if not explicitly requested.
|
||||
if !show.ShowDeepMetas() && show.ShowMetas() {
|
||||
show &^= FormatShowMetas // Turn off showing metas in deeper levels if not deep.
|
||||
}
|
||||
if !show.ShowDeepStacks() && show.ShowStack() {
|
||||
show &^= FormatShowStack // Turn off showing stacks in deeper levels if not deep.
|
||||
}
|
||||
for _, ce := range el {
|
||||
// Recursively call defaultFormatError for each cause, increasing the indentation level.
|
||||
defaultFormatError(w, ce, opts, level+1, show)
|
||||
}
|
||||
}
|
||||
|
||||
// Format the stack trace if one was collected and formatting is enabled.
|
||||
if stack != nil && !stack.State().HasNilOrZero() {
|
||||
_, _ = fmt.Fprintf(w, opts.FmtStackH, indent) // Format stack header.
|
||||
// Format each line of the stack trace.
|
||||
for _, l := range stack.Value().([]string) {
|
||||
_, _ = fmt.Fprintf(w, opts.FmtStackL, indent, l)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,131 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 17/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
/*
|
||||
// Basic ANSI color codes (Commented out, but values used in NewFormatOptionsColor)
|
||||
const (
|
||||
ColorBlack = "\033[30m"
|
||||
ColorRed = "\033[31m"
|
||||
ColorGreen = "\033[32m"
|
||||
ColorYellow = "\033[33m"
|
||||
ColorBlue = "\033[34m"
|
||||
ColorMagenta = "\033[35m"
|
||||
ColorCyan = "\033[36m"
|
||||
ColorWhite = "\033[37m"
|
||||
|
||||
ColorGray = "\033[2m"
|
||||
|
||||
ColorBrightBlack = "\033[90m"
|
||||
ColorBrightRed = "\033[91m"
|
||||
ColorBrightGreen = "\033[92m"
|
||||
ColorBrightYellow = "\033[93m"
|
||||
ColorBrightBlue = "\033[94m"
|
||||
ColorBrightMagenta= "\033[95m"
|
||||
ColorBrightCyan = "\033[96m"
|
||||
ColorBrightWhite = "\033[97m"
|
||||
|
||||
BgBlack = "\033[40m"
|
||||
BgRed = "\033[41m"
|
||||
BgGreen = "\033[42m"
|
||||
BgYellow = "\033[43m"
|
||||
BgBlue = "\033[44m"
|
||||
BgMagenta = "\033[45m"
|
||||
BgCyan = "\033[46m"
|
||||
BgWhite = "\033[47m"
|
||||
|
||||
BgBrightBlack = "\033[100m"
|
||||
BgBrightRed = "\033[101m"
|
||||
BgBrightGreen = "\033[102m"
|
||||
BgBrightYellow = "\033[103m"
|
||||
BgBrightBlue = "\033[104m"
|
||||
BgBrightMagenta = "\033[105m"
|
||||
BgBrightCyan = "\033[106m"
|
||||
BgBrightWhite = "\033[107m"
|
||||
|
||||
TextBold = "\033[1m" // Bold text
|
||||
TextFaint = "\033[2m" // Faint text (dim)
|
||||
TextUnderline = "\033[4m" // Underlined text
|
||||
TextReverse = "\033[7m" // Swap foreground and background colors
|
||||
|
||||
ColorReset = "\033[0m" // Reset all attributes
|
||||
|
||||
)
|
||||
|
||||
*/
|
||||
|
||||
type (
|
||||
// FormatOptions defines the options for controlling how errors are formatted.
|
||||
FormatOptions struct {
|
||||
// Show specifies which parts of the error (hierarchy, metas, stack) should be displayed.
|
||||
Show FormatShow
|
||||
// EnableColor indicates whether ANSI color codes should be included in the output.
|
||||
EnableColor bool
|
||||
|
||||
// Indent is the string used for each level of indentation in the formatted output.
|
||||
Indent string
|
||||
|
||||
// FmtError is the format string used for the root error message.
|
||||
FmtError string
|
||||
// FmtMeta is the format string used for displaying metadata.
|
||||
FmtMeta string
|
||||
// FmtCause is the format string used for displaying wrapped error messages (causes).
|
||||
FmtCause string
|
||||
// FmtStackH is the format string used for the stack trace header.
|
||||
FmtStackH string
|
||||
// FmtStackL is the format string used for each line of the stack trace.
|
||||
FmtStackL string
|
||||
}
|
||||
)
|
||||
|
||||
// NewFormatOptions creates a new FormatOptions instance with default plain text formatting.
|
||||
func NewFormatOptions() *FormatOptions {
|
||||
return &FormatOptions{
|
||||
Indent: " ",
|
||||
FmtError: "%s%s\n",
|
||||
FmtMeta: "%s * %s: %v\n",
|
||||
FmtCause: "%s%s\n",
|
||||
FmtStackH: "%s * stack:\n",
|
||||
FmtStackL: "%s %s\n",
|
||||
}
|
||||
}
|
||||
|
||||
// NewFormatOptionsColor creates a new FormatOptions instance with default ANSI color formatting.
|
||||
func NewFormatOptionsColor() *FormatOptions {
|
||||
return &FormatOptions{
|
||||
Indent: " ",
|
||||
EnableColor: true,
|
||||
// Format strings include ANSI color codes for different parts of the error output.
|
||||
FmtError: "%s\033[31m%s\033[0m\n", // Red for the main error message
|
||||
FmtMeta: "%s\033[2m * %s: %v\033[0m\n", // Faint/Dim for metadata
|
||||
FmtCause: "%s\033[33m%s\033[0m\n", // Yellow for wrapped error messages (causes)
|
||||
FmtStackH: "%s\033[37m * stack:\033[0m\n", // White for stack header
|
||||
FmtStackL: "%s\033[37m %s\033[0m\n", // White for stack lines
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n// =============================================================================\n// Date Create 18/05/2025\n// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
// FormatShowHierarchy is a flag to show the error hierarchy (wrapped errors/causes).
|
||||
FormatShowHierarchy FormatShow = 1 << iota
|
||||
// FormatShowMetas is a flag to show metadata of the current error in the hierarchy.
|
||||
FormatShowMetas
|
||||
// FormatShowDeepMetas is a flag to show metadata for all errors in the hierarchy.
|
||||
FormatShowDeepMetas
|
||||
// FormatShowStack is a flag to show the stack trace of the root error.
|
||||
FormatShowStack
|
||||
// FormatShowDeepStacks is a flag to show stack traces for all errors in the hierarchy if defined.
|
||||
FormatShowDeepStacks
|
||||
|
||||
// FormatShowNone is a flag to show nothing extra (only the basic error message).
|
||||
FormatShowNone FormatShow = 0
|
||||
)
|
||||
|
||||
// FormatShow is a bitmask type used to control which parts of an error are displayed during formatting.
|
||||
type FormatShow uint8
|
||||
|
||||
// ShowMetas returns true if the FormatShow includes the FormatShowMetas flag.
|
||||
func (o FormatShow) ShowMetas() bool { return o&FormatShowMetas != 0 }
|
||||
|
||||
// ShowHierarchy returns true if the FormatShow includes the FormatShowHierarchy flag.
|
||||
func (o FormatShow) ShowHierarchy() bool { return o&FormatShowHierarchy != 0 }
|
||||
|
||||
// ShowDeepMetas returns true if the FormatShow includes the FormatShowDeepMetas flag.
|
||||
func (o FormatShow) ShowDeepMetas() bool { return o&FormatShowDeepMetas != 0 }
|
||||
|
||||
// ShowStack returns true if the FormatShow includes the FormatShowStack flag.
|
||||
func (o FormatShow) ShowStack() bool { return o&FormatShowStack != 0 }
|
||||
|
||||
// ShowDeepStacks returns true if the FormatShow includes the FormatShowDeepStacks flag.
|
||||
func (o FormatShow) ShowDeepStacks() bool { return o&FormatShowDeepStacks != 0 }
|
||||
|
||||
// ShowOptionsFromVerb derives FormatShow options based on the fmt.State and verb.
|
||||
// This function interprets standard fmt verbs and flags to determine what to display.
|
||||
func ShowOptionsFromVerb(f fmt.State, verb rune) FormatShow {
|
||||
s := FormatShowNone
|
||||
switch verb {
|
||||
case 's', 'q':
|
||||
// For %s and %q, show nothing extra.
|
||||
return s
|
||||
|
||||
case 'v':
|
||||
// For %v, check flags to determine what to show.
|
||||
if f.Flag('+') {
|
||||
// %+v -> Show hierarchy, metas, and full stack
|
||||
s |= FormatShowHierarchy |
|
||||
FormatShowMetas |
|
||||
FormatShowDeepMetas |
|
||||
FormatShowStack |
|
||||
FormatShowDeepStacks
|
||||
|
||||
} else if f.Flag('#') {
|
||||
// %#v -> Show metas and stack of the principal error
|
||||
s |= FormatShowMetas |
|
||||
FormatShowStack
|
||||
|
||||
} else {
|
||||
// %v -> Show hierarchy and principal stack (optional based on your criterion)
|
||||
s |= FormatShowHierarchy |
|
||||
FormatShowStack
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 20/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
|
||||
type (
|
||||
|
||||
Formatter interface {
|
||||
Format (err error) ([]byte,error)
|
||||
}
|
||||
|
||||
|
||||
FormatFnc func (error) ([]byte,error)
|
||||
)
|
||||
|
||||
|
||||
|
||||
func (f FormatFnc) Format (err error) ([]byte,error) { return f(err) }
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,86 @@
|
||||
// =============================================================================
|
||||
// GO·AT Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 09/06/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
import (
|
||||
"core/excs"
|
||||
"core/vals"
|
||||
)
|
||||
|
||||
|
||||
|
||||
type (
|
||||
|
||||
Meta struct {
|
||||
vals.CValue
|
||||
name string
|
||||
mType MetaType
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
func CreateMeta (name string, cval vals.CValue) Meta {
|
||||
if !IsValidMetaName(name) {
|
||||
panic(E.InvalidMetaName)
|
||||
}
|
||||
return Meta {
|
||||
CValue : cval,
|
||||
name : name,
|
||||
mType : MetaTypeValue,
|
||||
}
|
||||
}
|
||||
|
||||
func CreateMetaStack (stack excs.Stack) Meta {
|
||||
return Meta {
|
||||
name : MetaCauseName,
|
||||
CValue : vals.CreateCValueStack(stack),
|
||||
mType : MetaTypeStack,
|
||||
}
|
||||
}
|
||||
|
||||
func CreateMetaCause(cause error) Meta {
|
||||
return Meta {
|
||||
name : MetaCauseName,
|
||||
CValue : vals.CreateCValueError(cause),
|
||||
mType : MetaTypeCause,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (m Meta) Name() string { return m.name }
|
||||
|
||||
|
||||
|
||||
// IsValidMetaName checks if a string is a valid metadata name according to the rules defined by metaValidator.
|
||||
func IsValidMetaName(meta string) bool {
|
||||
return len(meta) > 0 && g.metaValidator.MatchString(meta)
|
||||
}
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 18/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
const (
|
||||
// MetaTypeValue is a flag to select general value metadata.
|
||||
MetaTypeValue MetaType = 1 << iota
|
||||
// MetaTypeCause is a flag to select cause metadata.
|
||||
MetaTypeCause
|
||||
// MetaTypeStack is a flag to select stack trace metadata.
|
||||
MetaTypeStack
|
||||
// MetaTypeAll is a flag to select all types of metadata.
|
||||
MetaTypeAll = 7 // Combination of all selection flags
|
||||
)
|
||||
|
||||
// MetaType is a bitmask type used to select which types of metadata to retrieve.
|
||||
type MetaType uint8
|
||||
|
||||
// SelectValue returns true if the MetaType includes the MetaTypeValue flag.
|
||||
func (s MetaType) SelectValue() bool { return s&MetaTypeValue != 0 }
|
||||
|
||||
// SelectCause returns true if the MetaType includes the MetaTypeCause flag.
|
||||
func (s MetaType) SelectCause() bool { return s&MetaTypeCause != 0 }
|
||||
|
||||
// SelectStack returns true if the MetaType includes the MetaTypeStack flag.
|
||||
func (s MetaType) SelectStack() bool { return s&MetaTypeStack != 0 }
|
||||
@ -0,0 +1,45 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 16/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
type (
|
||||
// MetadataProvider is an interface implemented by types that can provide metadata.
|
||||
// Composed error types typically implement this interface.
|
||||
MetadataProvider interface {
|
||||
// Metadata returns a slice of Meta objects based on the provided selector.
|
||||
Metadata(selector MetaType) []Meta }
|
||||
|
||||
// MetadataFnc is a function type that implements the MetadataProvider interface.
|
||||
// It allows an anonymous function or an existing function to act as a metadata provider.
|
||||
MetadataFnc func(selector MetaType) []Meta
|
||||
|
||||
)
|
||||
|
||||
// Metadata implements the MetadataProvider interface for MetadataFnc, executing the underlying function.
|
||||
func (f MetadataFnc) Metadata(selector MetaType) []Meta { return f(selector) }
|
||||
@ -0,0 +1,72 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 13/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
const (
|
||||
// errPanic is the error class name used to represent panics converted to errors.
|
||||
errPanic = moduleName + "panic"
|
||||
)
|
||||
|
||||
type (
|
||||
// PanicErr is an error type that wraps a recovered panic.
|
||||
// It allows treating a panic as a structured error.
|
||||
PanicErr struct {
|
||||
Err // Embeds the Err type to inherit its methods and basic structure.
|
||||
cause error // cause stores the recovered panic value, converted to an error type.
|
||||
}
|
||||
)
|
||||
|
||||
// CreatePanicErr creates a new PanicErr instance from a recovered panic value.
|
||||
// It converts the panic value to an error type using ToError.
|
||||
func CreatePanicErr(cause any) PanicErr {
|
||||
return PanicErr{
|
||||
Err: CreateErr(errPanic), // Creates a base error with the "panic" class.
|
||||
cause: ToError(cause), // Converts the panic value to an error.
|
||||
}
|
||||
}
|
||||
|
||||
// Cause implements the Causer interface for PanicErr.
|
||||
// It returns the underlying error representing the panic value.
|
||||
func (e PanicErr) Cause() error { return e.cause }
|
||||
|
||||
// Unwrap implements Go 1.13+'s errors.Unwrap interface.
|
||||
// It returns the underlying error representing the panic value, allowing
|
||||
// the PanicErr to be unwrapped to access the original cause.
|
||||
func (e PanicErr) Unwrap() error { return e.cause }
|
||||
|
||||
|
||||
|
||||
func (e PanicErr) Metadata(selector MetaType) []Meta {
|
||||
if !selector.SelectCause() {
|
||||
return nil
|
||||
}
|
||||
return []Meta{
|
||||
CreateMetaCause(e.cause),
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 12/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
import (
|
||||
"core/vals"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
errParam = moduleName + "invalid_param"
|
||||
errParamNil = errParam + errClassSep + "nil"
|
||||
errParamEmpty = errParam + errClassSep + "empty"
|
||||
errParamRange = errParam + errClassSep + "range"
|
||||
errParamRangeMin = errParamRange + errClassSep + "min"
|
||||
errParamRangeMax = errParamRange + errClassSep + "max"
|
||||
)
|
||||
|
||||
type (
|
||||
ParamErr struct {
|
||||
Err
|
||||
name string
|
||||
value any
|
||||
}
|
||||
)
|
||||
|
||||
func createParamErr(err Err, name string, value any) ParamErr {
|
||||
if name == "" {
|
||||
|
||||
panic(CreateParamEmptyErr("name"))
|
||||
}
|
||||
return ParamErr{
|
||||
Err: err,
|
||||
name: name,
|
||||
value: value,
|
||||
}
|
||||
}
|
||||
|
||||
func CreateParamErr (name string, value any) ParamErr {
|
||||
return createParamErr(Err(errParam), name, value)
|
||||
}
|
||||
|
||||
func CreateParamNilErr (name string) ParamErr {
|
||||
return createParamErr(Err(errParamNil),name, nil)
|
||||
}
|
||||
|
||||
func CreateParamEmptyErr(name string) ParamErr {
|
||||
return createParamErr(Err(errParamEmpty),name,"")
|
||||
}
|
||||
|
||||
func CreateParamRange (name string, value any) ParamErr {
|
||||
return createParamErr(Err(errParamRange),name,value)
|
||||
}
|
||||
|
||||
func CreateParamRangeMin(name string, value any) ParamErr {
|
||||
return createParamErr(Err(errParamRangeMin), name, value)
|
||||
}
|
||||
|
||||
func CreateParamRangeMax(name string, value any) ParamErr {
|
||||
return createParamErr(Err(errParamRangeMax), name, value)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func (e ParamErr) ParamName() string { return e.name }
|
||||
|
||||
func (e ParamErr) ParamValue() any { return e.value }
|
||||
|
||||
func (e ParamErr) Format(f fmt.State, v rune) { Format(e, f, v) }
|
||||
|
||||
func (e ParamErr) Metadata(selector MetaType) []Meta {
|
||||
if !selector.SelectValue() {
|
||||
return nil
|
||||
}
|
||||
return []Meta {
|
||||
CreateMeta("param_name", vals.CreateCValueString(e.name)),
|
||||
vals.CreateCField("param_value", e.value),
|
||||
}
|
||||
}
|
||||
|
||||
func (e ParamErr) Unwrap() error {
|
||||
// ParamErr es típicamente un error hoja, no envuelve nada que continúe la cadena.
|
||||
return nil
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
// =============================================================================
|
||||
// Active-GO Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 15/05/2025
|
||||
// =============================================================================
|
||||
|
||||
package errs
|
||||
|
||||
const (
|
||||
// SeverityDebug indicates a severity level for debugging information.
|
||||
SeverityDebug Severity = 1 << iota
|
||||
// SeverityInfo indicates a severity level for general information.
|
||||
SeverityInfo
|
||||
// SeverityWarn indicates a severity level for warnings.
|
||||
SeverityWarn
|
||||
// SeverityError indicates a severity level for errors affecting functionality.
|
||||
SeverityError
|
||||
// SeverityCritical indicates a severity level for critical errors requiring immediate attention.
|
||||
SeverityCritical
|
||||
// SeverityFatal indicates a severity level for errors causing application termination.
|
||||
SeverityFatal
|
||||
)
|
||||
|
||||
// Severity represents the severity level of an error.
|
||||
// It is used to classify the importance of an error.
|
||||
type Severity uint8
|
||||
|
||||
// String returns the string representation of the severity level.
|
||||
// Returns "UNKNOWN" for undefined severity values.
|
||||
func (s Severity) String() string {
|
||||
// Checks if the severity value is within the expected range.
|
||||
if s <= 0 || s > SeverityFatal {
|
||||
return "UNKNOWN"
|
||||
}
|
||||
// Uses a string slice to map the severity value to its name.
|
||||
// Note: Index 0 is not used as severity values start from 1 (1 << 0).
|
||||
return [...]string{"DEBUG", "INFO", "WARNING", "ERROR", "FATAL", "CRITICAL"}[s-1] // Corrected index
|
||||
}
|
||||
@ -0,0 +1,154 @@
|
||||
// =============================================================================
|
||||
// GO·AT Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 10/06/2025
|
||||
// =============================================================================
|
||||
|
||||
package vals
|
||||
|
||||
type (
|
||||
|
||||
CAttribute struct {
|
||||
CValue
|
||||
aType CAttributeType
|
||||
name string
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
func CreateCAttribute (name string, value any, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValue(value), attrType)
|
||||
}
|
||||
|
||||
|
||||
func CreateCAttributeBool (name string, value bool, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueBool(value), attrType) }
|
||||
|
||||
|
||||
|
||||
func CreateCAttributeInt (name string, value int, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueInt(value), attrType) }
|
||||
|
||||
func CreateCAttributeInt8 (name string, value int8, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueInt8(value), attrType) }
|
||||
|
||||
func CreateCAttributeInt16 (name string, value int16, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueInt16(value), attrType) }
|
||||
|
||||
func CreateCAttributeInt32 (name string, value int32, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueInt32(value), attrType) }
|
||||
|
||||
func CreateCAttributeInt64 (name string, value int64, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueInt64(value), attrType) }
|
||||
|
||||
|
||||
|
||||
|
||||
func CreateCAttributeUint (name string, value uint, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueUint(value), attrType) }
|
||||
|
||||
func CreateCAttributeUint8 (name string, value uint8, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueUint8(value), attrType) }
|
||||
|
||||
func CreateCAttributeUint16 (name string, value uint16, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueUint16(value), attrType) }
|
||||
|
||||
func CreateCAttributeUint32 (name string, value uint32, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueUint32(value), attrType) }
|
||||
|
||||
func CreateCAttributeUint64 (name string, value uint64, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueUint64(value), attrType) }
|
||||
|
||||
func CreateCAttributeUintptr (name string, value uintptr, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueUintptr(value),attrType) }
|
||||
|
||||
|
||||
|
||||
|
||||
func CreateCAttributeFloat32 (name string, value float32, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueFloat32(value), attrType) }
|
||||
|
||||
func CreateCAttributeFloat64 (name string, value float64, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueFloat64(value), attrType) }
|
||||
|
||||
func CreateCAttributeComplex64 (name string, value complex64, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueComplex64(value), attrType) }
|
||||
|
||||
func CreateCAttributeComplex128 (name string, value complex128, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueComplex128(value), attrType) }
|
||||
|
||||
|
||||
|
||||
func CreateCAttributeDate (name string, value Date, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueDate(value),attrType) }
|
||||
|
||||
func CreateCAttributeDuration (name string, value Duration, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueDuration(value),attrType) }
|
||||
|
||||
|
||||
|
||||
func CreateCAttributeString (name string, value string, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueString(value), attrType) }
|
||||
|
||||
func CreateCAttributeBytes (name string, value Bytes, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueBytes(value), attrType) }
|
||||
|
||||
func CreateCAttributeStack (name string, value Stack, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueStack(value), attrType | CAttributeTypeStack ) }
|
||||
|
||||
func CreateCAttributeCause (name string, value error, attrType CAttributeType) CAttribute {
|
||||
return CreateCAttributeWithCValue(name,CreateCValueError(value), attrType|CAttributeTypeCause) }
|
||||
|
||||
|
||||
|
||||
|
||||
func CreateCAttributeWithCValue (name string, cvalue CValue, attrType CAttributeType) CAttribute {
|
||||
at := CAttribute{
|
||||
CValue: cvalue,
|
||||
name : name,
|
||||
aType : attrType,
|
||||
}
|
||||
if attrType.HasAttributePII() {
|
||||
at.vState|= cValueStateSensitive
|
||||
}
|
||||
return at
|
||||
}
|
||||
|
||||
|
||||
func (a CAttribute) Name() string { return a.name }
|
||||
|
||||
func (a CAttribute) AttrType() CAttributeType { return a.aType }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,74 @@
|
||||
// =============================================================================
|
||||
// GO·AT Framework
|
||||
// Copyright (c) 2025 ActiveThing (https://activething.com)
|
||||
// Author: Juan V. Navarro juanvnl@activething.com
|
||||
// =============================================================================
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// Date Create 10/06/2025
|
||||
// =============================================================================
|
||||
|
||||
package vals
|
||||
|
||||
|
||||
const (
|
||||
|
||||
CAttributeTypeCause CAttributeType = 1 << iota
|
||||
CAttributeTypeStack
|
||||
CAttributeTypeIdentifier
|
||||
CAttributeTypeIndexed
|
||||
CAttributeTypeMeasurement
|
||||
CAttributeTypePII
|
||||
CAttributeTypeDebug
|
||||
|
||||
CAttributeTypeDefault CAttributeType = 0
|
||||
)
|
||||
|
||||
|
||||
type CAttributeType uint8
|
||||
|
||||
|
||||
|
||||
func (c CAttributeType) HasAttribute (attType CAttributeType) bool { return c&attType == c }
|
||||
|
||||
func (c CAttributeType) IsAttributeDefault () bool { return c == 0 }
|
||||
|
||||
func (c CAttributeType) HasAttributeCause () bool { return c&CAttributeTypeCause != 0 }
|
||||
func (c CAttributeType) HasAttributeStack () bool { return c&CAttributeTypeStack != 0 }
|
||||
func (c CAttributeType) HasAttributeIdentifier() bool { return c&CAttributeTypeIdentifier != 0 }
|
||||
func (c CAttributeType) HasAttributePII () bool { return c&CAttributeTypePII != 0 }
|
||||
func (c CAttributeType) HasAttributeIndexed () bool { return c&CAttributeTypeIndexed != 0 }
|
||||
func (c CAttributeType) HasAttributeMeasurement() bool{ return c&CAttributeTypeMeasurement != 0 }
|
||||
func (c CAttributeType) HasAttributeDebug () bool { return c&CAttributeTypeDebug != 0 }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in new issue