diff --git a/src/app/main.go b/src/app/main.go index 3ef374e..dd541ce 100644 --- a/src/app/main.go +++ b/src/app/main.go @@ -29,43 +29,18 @@ package main import ( - "base/cdts" + "corx/cdts" "fmt" ) func main() { - /* - var m map[string]int = map[string]int{ "ss" : 22, "ds" : 434} - - - c := vals.G.TypeInfos.CreateCValue(m) - - fmt.Printf("%v+ --> %s \n",c,c.Type().String()) - - - g := vals.G.TypeInfos.CreateCValue(func() int { return 1 } ) - fmt.Printf("%v+ --> %s \n",g,g.Type().String()) - - var f func() int - g = vals.G.TypeInfos.CreateCValue(f) - fmt.Printf("%v+ --> %s %s \n",g,g.Type().String(),g.State().String()) - - type st struct { na string } - var a *st - e := vals.G.TypeInfos.CreateCValue(a) - fmt.Printf("%v+ --> %s %s \n",e,e.Type().String(),e.State().String()) - -*/ - var an any - - type s struct { m string } - - an = []s { { m: "dfdff"}, {m: "aaaa"} } - - e := cdts.CreateCValue(an) - fmt.Printf("%v+ --> tipo : %s estado :%s \n",e,e.Type().String(),e.State().String()) - + m := map[string]int {"dd":3,"d":3,} + d := func() int { return 3} + cv := cdts.G.CTypes.CreateByReflection(m,cdts.CreateCVTypeMap(cdts.CBTypeAny,cdts.CBTypeAny)) + fmt.Printf ("CValue %v\n", cv) + cv = cdts.G.CTypes.CreateByReflection(d,cdts.CreateCVTypeLazy(cdts.CBTypeAny)) + fmt.Printf ("CValue %v\n", cv) } diff --git a/src/corx/cdts/a.go b/src/corx/cdts/a.go index 37f240b..4efc07b 100644 --- a/src/corx/cdts/a.go +++ b/src/corx/cdts/a.go @@ -71,6 +71,12 @@ type ( var ( + G = struct { + CTypes *cBTypeInfos + } { + + CTypes: newCBTypeInfos(), + } g = struct { bigZero *BigInt @@ -91,9 +97,10 @@ var ( } E = struct { - - InvalidReflectValue string + UnexpectedTypeReflected, + InvalidReflectValue string }{ - InvalidReflectValue: "::invalid_reflect_value", + UnexpectedTypeReflected : "::unexpected_type_reflected", + InvalidReflectValue : "::invalid_reflect_value", } ) \ No newline at end of file diff --git a/src/corx/cdts/cbtype.go b/src/corx/cdts/cbtype.go index 18a44d9..c737184 100644 --- a/src/corx/cdts/cbtype.go +++ b/src/corx/cdts/cbtype.go @@ -68,6 +68,7 @@ const ( CBTypeDate CBTypeCValue CBTypeReflect + CBTypeObject CBTypeListPackable diff --git a/src/corx/cdts/cbtype_infos.go b/src/corx/cdts/cbtype_infos.go index 04cbe9c..71f515e 100644 --- a/src/corx/cdts/cbtype_infos.go +++ b/src/corx/cdts/cbtype_infos.go @@ -45,31 +45,34 @@ type ( func newCBTypeInfos() *cBTypeInfos { - vi := &cBTypeInfos{} + vi := &cBTypeInfos{ + cache : make(map[reflect.Type]func(reflect.Value) CValue), + } vi.types = []*cBTypeInfo{ - /* 01 */ newCVTypeInfo(CBTypeInvalid ,"invalid" , optInvalidCreators()), - /* 02 */ newCVTypeInfo(CBTypeAny ,"any" , optAnyCreators [any ](nil)), - /* 03 */ newCVTypeInfo(CBTypeBool ,"bool" , optNormalCreators [bool ](CreateCBool)), - /* 04 */ newCVTypeInfo(CBTypeInt ,"int" , optNormalCreators [int ](CreateCInt)), - /* 05 */ newCVTypeInfo(CBTypeInt8 ,"int8" , optNormalCreators [int8 ](CreateCInt8)), - /* 06 */ newCVTypeInfo(CBTypeInt16 ,"int16" , optNormalCreators [int16 ](CreateCInt16)), - /* 07 */ newCVTypeInfo(CBTypeInt64 ,"int64" , optNormalCreators [int64 ](CreateCInt64)), - /* 08 */ newCVTypeInfo(CBTypeUint ,"uint" , optNormalCreators [uint ](CreateCUint)), + /* 00 */ newCVTypeInfo(CBTypeInvalid ,"invalid" , optInvalidCreators()), + /* 01 */ newCVTypeInfo(CBTypeAny ,"any" , optAnyCreators [any ](nil)), + /* 02 */ newCVTypeInfo(CBTypeBool ,"bool" , optNormalCreators [bool ](CreateCBool)), + /* 03 */ newCVTypeInfo(CBTypeInt ,"int" , optNormalCreators [int ](CreateCInt)), + /* 04 */ newCVTypeInfo(CBTypeInt8 ,"int8" , optNormalCreators [int8 ](CreateCInt8)), + /* 05 */ newCVTypeInfo(CBTypeInt16 ,"int16" , optNormalCreators [int16 ](CreateCInt16)), + /* 06 */ newCVTypeInfo(CBTypeInt32 ,"int32" , optNormalCreators [int32 ](CreateCInt32)), + /* 07 */ newCVTypeInfo(CBTypeInt64 ,"int64" , optNormalCreators [int64 ](CreateCInt64)), + /* 08 */ newCVTypeInfo(CBTypeUint ,"uint" , optNormalCreators [uint ](CreateCUint)), /* 09 */ newCVTypeInfo(CBTypeUint8 ,"uint8" , optNormalCreators[uint8](CreateCUint8), // el creador de []uint8 debe de reportar el tipo Bytes y debe de llamar a su creador CreateCBytes func(i *cBTypeInfo) { i.cByList = func(v any) CValue { return CreateCBytes(v.(Bytes)) } }), - /* 10 */ newCVTypeInfo(CBTypeUint16 ,"uint16" , optNormalCreators[uint16 ](CreateCUint16)), - /* 11 */ newCVTypeInfo(CBTypeUint32 ,"uint32" , optNormalCreators[uint32 ](CreateCUint32)), - /* 12 */ newCVTypeInfo(CBTypeUint64 ,"uint64" , optNormalCreators[uint64 ](CreateCUint64)), - /* 13 */ newCVTypeInfo(CBTypeUintptr ,"uintptr" , optNormalCreators[uintptr ](CreateCUintptr)), - /* 14 */ newCVTypeInfo(CBTypeDuration ,"duration" , optNormalCreators[Duration ](CreateCDuration)), + /* 10 */ newCVTypeInfo(CBTypeUint16 ,"uint16" , optNormalCreators [uint16 ](CreateCUint16)), + /* 11 */ newCVTypeInfo(CBTypeUint32 ,"uint32" , optNormalCreators [uint32 ](CreateCUint32)), + /* 12 */ newCVTypeInfo(CBTypeUint64 ,"uint64" , optNormalCreators [uint64 ](CreateCUint64)), + /* 13 */ newCVTypeInfo(CBTypeUintptr ,"uintptr" , optNormalCreators [uintptr ](CreateCUintptr)), + /* 14 */ newCVTypeInfo(CBTypeDuration ,"duration" , optNormalCreators [Duration ](CreateCDuration)), - /* 15 */ newCVTypeInfo(CBTypeFloat32 ,"float32" , optNormalCreators[float32 ](CreateCFloat32)), - /* 16 */ newCVTypeInfo(CBTypeFloat64 ,"float64" , optNormalCreators[float64 ](CreateCFloat64)), + /* 15 */ newCVTypeInfo(CBTypeFloat32 ,"float32" , optNormalCreators [float32 ](CreateCFloat32)), + /* 16 */ newCVTypeInfo(CBTypeFloat64 ,"float64" , optNormalCreators [float64 ](CreateCFloat64)), - /* 17 */ newCVTypeInfo(CBTypeComplex64 ,"complex64" , optNormalCreators[complex64 ](CreateCComplex64 )), - /* 18 */ newCVTypeInfo(CBTypeComplex128 ,"complex128" , optNormalCreators[complex128 ](CreateCComplex128)), + /* 17 */ newCVTypeInfo(CBTypeComplex64 ,"complex64" , optNormalCreators [complex64 ](CreateCComplex64 )), + /* 18 */ newCVTypeInfo(CBTypeComplex128 ,"complex128" , optNormalCreators [complex128 ](CreateCComplex128)), // Big Int tiene una forma canonica de *big.Int, lo cual hace cambiar los constructores de Ptr ya que no lo // debe des referenciar, en caso de que se pase por valor, debemos de convertirlo a un *BigInt, copiar su @@ -83,30 +86,31 @@ func newCBTypeInfos() *cBTypeInfos { i.cByLazy= buildCreatorPByLazy[BigInt](CBTypeBigInt) i.cByList= buildCreatorPByList[BigInt](CBTypeBigInt) }), - /* 20 */ newCVTypeInfo(CBTypeHashAlg ,"hashalg" , optNormalCreators[HashAlg ](CreateCHashAlg)), + /* 20 */ newCVTypeInfo(CBTypeHashAlg ,"hashalg" , optNormalCreators [HashAlg ](CreateCHashAlg)), - /* 21 */ newCVTypeInfo(CBTypeString ,"string" , optNormalCreators[string ](CreateCString)), - /* 22 */ newCVTypeInfo(CBTypeUUID ,"uuid" , optNormalCreators[UUID ](CreateCUUID)), - /* 23 */ newCVTypeInfo(CBTypeBytes ,"bytes" , optNormalCreators[Bytes ](CreateCBytes)), - /* 24 */ newCVTypeInfo(CBTypeStack ,"stack" , optNormalCreators[Stack ](CreateCStack)), + /* 21 */ newCVTypeInfo(CBTypeString ,"string" , optNormalCreators [string ](CreateCString)), + /* 22 */ newCVTypeInfo(CBTypeUUID ,"uuid" , optNormalCreators [UUID ](CreateCUUID)), + /* 23 */ newCVTypeInfo(CBTypeBytes ,"bytes" , optNormalCreators [Bytes ](CreateCBytes)), + /* 24 */ newCVTypeInfo(CBTypeStack ,"stack" , optNormalCreators [Stack ](CreateCStack)), - /* 25 */ newCVTypeInfo(CBTypeDate ,"date" , optNormalCreators[Date ](CreateCDate)), - /* 26 */ newCVTypeInfo(CBTypeCValue ,"cvalue" , optNormalCreators[CValue ](CreateCCValue)), - /* 27 */ newCVTypeInfo(CBTypeReflect ,"cvalue" , optNormalCreators[Reflect ](CreateCReflect)), + /* 25 */ newCVTypeInfo(CBTypeDate ,"date" , optNormalCreators [Date ](CreateCDate)), + /* 26 */ newCVTypeInfo(CBTypeCValue ,"cvalue" , optNormalCreators [CValue ](CreateCCValue)), + /* 27 */ newCVTypeInfo(CBTypeReflect ,"cvalue" , optNormalCreators [Reflect ](CreateCReflect)), + /* 28 */ newCVTypeInfo(CBTypeObject ,"object" , optAnyCreators [any ](CreateCAny)), // Los interfaces solo se evaluate en su forma canonical - /* 28 */ newCVTypeInfo(CBTypeMapPackable,"mappackable", optAnyCreators [MapPackable](CreateCMapPackable)), /* 29 */ newCVTypeInfo(CBTypeMapPackable,"mappackable", optAnyCreators [MapPackable](CreateCMapPackable)), - /* 30 */ newCVTypeInfo(CBTypeObjPackable,"objpackable", optAnyCreators [ObjPackable](CreateCObjectPackable)), - /* 31 */ newCVTypeInfo(CBTypePackable ,"packable" , optAnyCreators [Packable ](CreateCPackable)), + /* 30 */ newCVTypeInfo(CBTypeMapPackable,"mappackable", optAnyCreators [MapPackable](CreateCMapPackable)), + /* 31 */ newCVTypeInfo(CBTypeObjPackable,"objpackable", optAnyCreators [ObjPackable](CreateCObjectPackable)), + /* 32 */ newCVTypeInfo(CBTypePackable ,"packable" , optAnyCreators [Packable ](CreateCPackable)), - /* 32 */ newCVTypeInfo(CBTypeContext ,"context" , optAnyCreators [Context ](CreateCContext)), - /* 33 */ newCVTypeInfo(CBTypeError ,"error" , optNormalCreators [error ](CreateCError)), - /* 34 */ newCVTypeInfo(CBTypeStringer ,"stringer" , optNormalCreators [Stringer ](CreateCStringer)) , + /* 33 */ newCVTypeInfo(CBTypeContext ,"context" , optAnyCreators [Context ](CreateCContext)), + /* 34 */ newCVTypeInfo(CBTypeError ,"error" , optNormalCreators [error ](CreateCError)), + /* 35 */ newCVTypeInfo(CBTypeStringer ,"stringer" , optNormalCreators [Stringer ](CreateCStringer)) , - /* 35 */ newCVTypeInfo(CBTypeNil , "nil" , optSameCreators (CreateCNil)), + /* 36 */ newCVTypeInfo(CBTypeNil , "nil" , optSameCreators (CreateCNil)), } @@ -115,7 +119,10 @@ func newCBTypeInfos() *cBTypeInfos { -func (i *cBTypeInfos) createByReflection (value any) CValue { + + + +func (i *cBTypeInfos) CreateByReflection(value any, vtype CVType) CValue { rv := reflect.ValueOf(value) if !rv.IsValid() { return createCInvalidError(rv,CStateReflected,E.InvalidReflectValue) @@ -129,13 +136,182 @@ func (i *cBTypeInfos) createByReflection (value any) CValue { return rf(rv) } - tn := rt.String() + switch rt.Kind() { + // Los tipos soportados deben de haber sido capturados + // por el switch de tipos + case reflect.Struct : // createCValueAny + if /*vtype.c.IsComposite() ||*/ vtype.v != CBTypeObject { + return createCInvalidError(rv, CStateReflected,E.UnexpectedTypeReflected) + } + rf = createCValueRObj(rt.String()) + + case reflect.Func : + if /*!vtype.v.IsValid() ||*/ vtype.c != CCTypeLazy { + return createCInvalidError(rv, CStateReflected,E.UnexpectedTypeReflected) + } + if rt.NumIn() == 0 && rt.NumOut() == 1 { + // Si fuera el tipo del valor devuelto conocido ya lo habria + // interceptado el switch de tipos, devolvemos un lazy|any + // + et:= reflectKindToCType(rt.Out(0).Kind()) + rf = createCValueRLazy(CVType { v : et.v, c : CCTypeLazy},rt.String()) + } + + case reflect.Slice, + reflect.Array : + if /*!vtype.v.IsValid() ||*/ vtype.c != CCTypeList { + return createCInvalidError(rv,CStateReflected,E.UnexpectedTypeReflected) + } + kv := reflectKindToCType(rt.Elem().Kind()) + if kv.v != CBTypeInvalid { + rf = createCValueRList(kv,rt.String()) + } + + case reflect.Map : + if /*!vtype.v.IsValid() ||*/ vtype.c != CCTypeMap { + return createCInvalidError(rv,CStateReflected,E.UnexpectedTypeReflected) + } + if kt := reflectKindToCType(rt.Key().Kind()); kt.v.IsValid() { + if et := reflectKindToCType(rt.Elem().Kind()); et.v.IsValid() { + et.c = CCTypeMap + et.k = kt.k + rf = createCValueRMap(et,rt.String()) + } + } + + } + + if rf == nil { + rf = createCValueRAny(rt.String()) + } + i.mux.Lock() i.cache[rt]=rf - i.mux.RUnlock() + i.mux.Unlock() return rf(rv) } + + + +func createCValueRList (vtype CVType, tname string) func(reflect.Value) CValue { + return func(rv reflect.Value) CValue { + vs := CStateReflected + // Código podría ser redundante + if !rv.IsValid() { + return createCInvalidError(rv,vs,E.InvalidReflectValue) + } + vt := vtype + tn := tname + ln := rv.Len() + if ln == 0 { + if rv.IsNil() { + vs |= CStateNil + } else { + vs |= CStateZero + } + } + return CValue{CVType: vt, CState: vs, anyVal: rv, strVal: tn, intVal: int64(ln)} + } +} + + +func createCValueRMap (vtype CVType, tname string) func (value reflect.Value) CValue { + return func(rv reflect.Value) CValue { + vs := CStateReflected + // Código podría ser redundante + if !rv.IsValid() { + return createCInvalidError(rv,vs,E.InvalidReflectValue) + } + vt := vtype + tn := tname + ln := rv.Len() + if ln == 0 { + if rv.IsNil() { + vs |= CStateNil + } else { + vs |= CStateZero + } + } + return CValue{CVType: vt, CState: vs, anyVal: rv, strVal: tn, intVal: int64(ln)} + } +} + + +func createCValueRLazy (vtype CVType, tname string) func (value reflect.Value) CValue { + return func(rv reflect.Value) CValue { + vs := CStateReflected + // Código podría ser redundante + if !rv.IsValid() { + return createCInvalidError(rv,vs,E.InvalidReflectValue) + } + vt := vtype + tn := tname + if rv.IsNil() { + vs |= CStateNil + } + return CValue {CVType: vt, CState: vs, strVal: tn, anyVal: rv} + } +} + + +func createCValueRObj (tname string) func(reflect.Value) CValue { + return func(rv reflect.Value) CValue { + vs := CStateReflected + // Código podría ser redundante + if !rv.IsValid() { + return createCInvalidError(rv,vs,E.InvalidReflectValue) + } + tn := tname + return CValue{CVType: CVType { v: CBTypeObject }, CState: vs, strVal: tn, anyVal: rv} + } +} + + +func createCValueRAny (tname string) func(reflect.Value) CValue { + return func(rv reflect.Value) CValue { + // Código podría ser redundante + if !rv.IsValid() { + return createCInvalidError(rv,CStateReflected,E.InvalidReflectValue) + } + tn := tname + return CValue{CVType: CVType { v: CBTypeAny }, CState: CStateReflected, strVal: tn, anyVal: rv} + } +} + + + +func reflectKindToCType (kind reflect.Kind) CVType { + switch kind { + case reflect.Invalid: return CVType{ v: CBTypeInvalid} + case reflect.Bool : return CVType{ v: CBTypeBool } + case reflect.Int : return CVType{ v: CBTypeInt } + case reflect.Int8 : return CVType{ v: CBTypeInt8 } + case reflect.Int16 : return CVType{ v: CBTypeInt16 } + case reflect.Int32 : return CVType{ v: CBTypeInt32 } + case reflect.Int64 : return CVType{ v: CBTypeInt64 } + case reflect.Uint : return CVType{ v: CBTypeUint } + case reflect.Uint8 : return CVType{ v: CBTypeUint8 } + case reflect.Uint16 : return CVType{ v: CBTypeUint16 } + case reflect.Uint32 : return CVType{ v: CBTypeUint32 } + case reflect.Uint64 : return CVType{ v: CBTypeUint64 } + case reflect.Uintptr: return CVType{ v: CBTypeUintptr} + case reflect.Float32: return CVType{ v: CBTypeFloat32} + case reflect.Float64: return CVType{ v: CBTypeFloat64} + case reflect.Complex64 : return CVType{ v: CBTypeComplex64 } + case reflect.Complex128 :return CVType{ v: CBTypeComplex128} + case reflect.String : return CVType{ v: CBTypeString } + case reflect.Struct : return CVType{ v: CBTypeObject } + + case reflect.Array, + reflect.Slice : return CVType{ v: CBTypeAny, c: CCTypeList } + case reflect.Map : return CVType{ v: CBTypeAny, c: CCTypeMap } + case reflect.Func : return CVType{ v: CBTypeAny, c: CCTypeLazy } + } + + return CVType{ v: CBTypeAny } +} + diff --git a/src/corx/cdts/cctype.go b/src/corx/cdts/cctype.go index ef8451a..bb29c1e 100644 --- a/src/corx/cdts/cctype.go +++ b/src/corx/cdts/cctype.go @@ -43,5 +43,5 @@ const ( type CCType uint8 -func (c CCType) IsValid () bool { return c > CCTypeNone && c < g.maxCCType } +func (c CCType) IsComposite() bool { return c > CCTypeNone && c < g.maxCCType } diff --git a/src/corx/cdts/cstate.go b/src/corx/cdts/cstate.go index 381dcd3..945ce6b 100644 --- a/src/corx/cdts/cstate.go +++ b/src/corx/cdts/cstate.go @@ -28,34 +28,54 @@ package cdts - +// CState representa una serie de banderas de estado compactas para un valor. +// Cada bandera se representa como un bit individual usando iota y operadores bitwise. const ( + CStateInvalid CState = 1 << iota // Valor no válido o corrupto (inconsistencia grave) + CStateError // Hubo un error al construir el valor; el detalle está en strValue (StateError) + CStateNil // Valor explícitamente nulo + CStateZero // Valor es cero (valor por defecto) + CStateVersion // Contiene metadatos de versión + CStateReflected // El valor fue obtenido por reflexión + CStateSensitive // Valor sensible (requiere tratamiento especial) + CStateEncoded // El Valor esta codificado - CStateInvalid CState = 1 << iota - CStateError - CStateNil - CStateZero - CStateVersion - CStateReflected - CStateSensitive - CStateEncoded + CStateNone CState = 0 // Estado sin banderas activas - CStateNone CState = 0 + cStateOps = CStateSensitive | CStateEncoded // Conjunto de estados operativos especiales - cStateOps= CStateSensitive | CStateEncoded ) +// CState define un conjunto de banderas compactas de tipo uint8. type CState uint8 -func (s CState) IsStateInvalid () bool { return s&CStateInvalid != 0 } -func (s CState) IsStateError () bool { return s&CStateError != 0 } -func (s CState) IsStateNil () bool { return s&CStateNil != 0 } -func (s CState) IsStateZero () bool { return s&CStateZero != 0 } -func (s CState) IsStateNilOrZero() bool { return s&(CStateZero |CStateNil) != 0 } -func (s CState) IsStateVersion () bool { return s&CStateVersion != 0 } -func (s CState) IsStateReflected() bool { return s&CStateReflected != 0 } -func (s CState) IsStateSensitive() bool { return s&CStateSensitive != 0 } -func (s CState) IsStateEncoded () bool { return s&CStateEncoded != 0 } +// IsStateInvalid indica si el estado representa un valor inválido. +func (s CState) IsStateInvalid() bool { return s&CStateInvalid != 0 } + +// IsStateError indica que hubo un error al construir el valor. +// El mensaje o código de error se encuentra en strValue y se accede con StateError() +// de CValue. +func (s CState) IsStateError() bool { return s&CStateError != 0 } + +// IsStateNil indica si el valor es nulo. +func (s CState) IsStateNil() bool { return s&CStateNil != 0 } + +// IsStateZero indica si el valor es el valor por defecto (cero). +func (s CState) IsStateZero() bool { return s&CStateZero != 0 } + +// IsStateNilOrZero indica si el valor es nulo o cero. +func (s CState) IsStateNilOrZero() bool { return s&(CStateNil|CStateZero) != 0 } + +// IsStateVersion indica si el valor contiene información de versión. +func (s CState) IsStateVersion() bool { return s&CStateVersion != 0 } + +// IsStateReflected indica si el valor proviene de reflexión. +func (s CState) IsStateReflected() bool { return s&CStateReflected != 0 } + +// IsStateSensitive indica si el valor es sensible (por ejemplo, contraseñas). +func (s CState) IsStateSensitive() bool { return s&CStateSensitive != 0 } +// IsStateEncoded indica si el valorha sido codificado. +func (s CState) IsStateEncoded() bool { return s&CStateEncoded != 0 } \ No newline at end of file diff --git a/src/corx/cdts/cvalue.go b/src/corx/cdts/cvalue.go index 8e46662..4830c39 100644 --- a/src/corx/cdts/cvalue.go +++ b/src/corx/cdts/cvalue.go @@ -200,7 +200,7 @@ func createCUints[T uints] (v T, t CBType) CValue { if v == 0 { return CValue{ CVType: CVType{ v: t }, CState : CStateZero } } - if t == CBTypeUint64 || t == CBTypeUintptr && v > math.MaxInt64 { + if t == CBTypeUint64 || t == CBTypeUintptr && uint64(v) > math.MaxInt64 { return CValue{ CVType: CVType{ v: t }, CState : CStateVersion, anyVal: v } } return CValue{ CVType: CVType{ v: t }, intVal: int64(v) } @@ -225,9 +225,12 @@ func createCList [T lists] (v T, t CBType) CValue { } func createCIfcs[T any] (v T, t CBType) CValue { + /* if v == nil { return CValue{ CVType: CVType{ v: t }, CState : CStateNil } } + + */ return CValue{ CVType: CVType{ v: t }, anyVal: v } } diff --git a/src/corx/cdts/cvtype.go b/src/corx/cdts/cvtype.go index 323544a..d0b5188 100644 --- a/src/corx/cdts/cvtype.go +++ b/src/corx/cdts/cvtype.go @@ -69,3 +69,6 @@ func (i CVType) KType () CBType { func (i CVType) CType () CCType { return i.c } +func (i CVType) IsComposite () bool { + return i.c.IsComposite() +} \ No newline at end of file diff --git a/src/corx/cvls/a.go b/src/corx/cvls/a.go new file mode 100644 index 0000000..920f8a2 --- /dev/null +++ b/src/corx/cvls/a.go @@ -0,0 +1,109 @@ +// ============================================================================= +// 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 AType 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 14/06/2025 +// ============================================================================= + +package cvls + +import ( + "context" + "crypto" + "fmt" + "math" + "math/big" + "reflect" + "time" +) + + +type ( + + Bytes = []uint8 + Stack = []struct{ Line string } + UUID = [16]byte + + Reflect = reflect.Value + Date = time.Time + Duration= time.Duration + + Stringer= fmt.Stringer + + BigInt = big.Int + HashAlg = crypto.Hash + + Packable= interface { P () } + MapPackable = interface { Map () } + ListPackable = interface { List () } + ObjPackable = interface { Object () } + + Context = context.Context +) + +type ( + + ints interface { int | int8 | int16 | int32 | int64 } + uints interface { uint | uint8 | uint16 | uint32 | uint64 | uintptr | Duration | HashAlg } + cmplx interface { complex64 | complex128 } + lists interface { Bytes | Stack } +) + +var ( + + G = struct { + cTypes *cTypeInfos + } { + + cTypes : newCTypeInfos(), + } + + + g = struct { + bigZero *BigInt + uuidZero UUID + maxBType BType + maxCType AType + + minTime, + maxTime time.Time + }{ + uuidZero : UUID{}, + bigZero : big.NewInt(0), + maxCType : aMaxType, + maxBType : bMaxType, + + minTime: time.Unix(0, math.MinInt64), + maxTime: time.Unix(0, math.MaxInt64), + } + + E = struct { + UnexpectedTypeReflected, + InvalidReflectValue string + }{ + UnexpectedTypeReflected : "::unexpected_type_reflected", + InvalidReflectValue : "::invalid_reflect_value", + } +) + diff --git a/src/corx/cvls/atype.go b/src/corx/cvls/atype.go new file mode 100644 index 0000000..fbf12ba --- /dev/null +++ b/src/corx/cvls/atype.go @@ -0,0 +1,52 @@ +// ============================================================================= +// 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 AType 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 14/06/2025 +// ============================================================================= + +package cvls + + +const ( + + ATypeNone AType = iota // No representa ningún tipo de agregado + ATypeLazy // Agregado evaluado de forma perezosa (lazy evaluation) + ATypeList // Agregado representado como una lista + ATypeMap // Agregado representado como un mapa (clave-valor) + + aMaxType // Límite superior del enumerado AType (debe ser el último) +) + +// AType representa el tipo de agregado (Aggregate Type). +// Define la naturaleza del agregado: si es una lista, un mapa o un valor evaluado perezosamente. +// Es útil para indicar cómo deben interpretarse y procesarse los datos agregados. +type AType uint8 + + + +// IsValid devuelve true si el valor de AType es válido (dentro del rango definido por aMaxType). +func (c AType) IsValid() bool { + return c < aMaxType +} \ No newline at end of file diff --git a/src/corx/cvls/btype.go b/src/corx/cvls/btype.go new file mode 100644 index 0000000..ae108e7 --- /dev/null +++ b/src/corx/cvls/btype.go @@ -0,0 +1,112 @@ +// ============================================================================= +// 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 AType 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 14/06/2025 +// ============================================================================= + +package cvls + + + +const ( + BTypeInvalid BType = iota // Tipo inválido o no inicializado + + // Tipos básicos + BTypeAny // Tipo genérico que puede contener cualquier valor + BTypeBool // Booleano (true/false) + + // Tipos enteros con signo + BTypeInt // Entero con signo (tamaño por defecto de la arquitectura) + BTypeInt8 + BTypeInt16 + BTypeInt32 + BTypeInt64 + + // Tipos enteros sin signo + BTypeUint + BTypeUint8 + BTypeUint16 + BTypeUint32 + BTypeUint64 + BTypeUintptr // Representación sin signo de un puntero + BTypeDuration // Duración de tiempo (generalmente basada en int64) + + // Tipos de punto flotante y complejos + BTypeFloat32 + BTypeFloat64 + BTypeComplex64 + BTypeComplex128 + + // Tipos numéricos extendidos + BTypeBigInt // Números enteros de precisión arbitraria (math/big.Int) + BTypeHashAlg // Representación de un algoritmo de hash (enum o identificador) + + // Tipos de datos compuestos y especiales + BTypeString + BTypeUUID // Identificador único universal (UUID) + BTypeBytes // Arreglo de bytes + BTypeStack // Pila (estructura de datos LIFO) + + BTypeDate // Fecha y hora + BTypeCValue // Valor de tipo C (posiblemente interoperabilidad) + BTypeReflect // Valor reflejado (reflect.Value) + BTypeObject // Objeto genérico (interfaz, struct, etc.) + + // Tipos que admiten empaquetado (serialización optimizada) + BTypeListPackable + BTypeMapPackable + BTypeObjPackable + BTypePackable // Tipo que puede ser empaquetado de forma genérica + + // Tipos especiales + BTypeContext // Contexto (context.Context) + BTypeError // Error (error) + BTypeStringer // Interfaz fmt.Stringer + + BTypeNil // Valor nulo + + bMaxType // Límite superior (no usar directamente) +) + +// BType representa un tipo base (Base Type) utilizado para describir el tipo primitivo +// de un valor en el sistema de tipos. Puede ser combinado con AType para formar un CType. +type BType uint8 + +// Check devuelve BTypeInvalid si el valor no es válido; de lo contrario, devuelve el valor original. +func (c BType) Check() BType { + if c >= bMaxType { + return BTypeInvalid + } + return c +} + +// IsValid devuelve true si el valor de BType es válido (dentro del rango permitido, excluyendo BTypeInvalid). +func (c BType) IsValid() bool { + return c > BTypeInvalid && c < bMaxType +} + + + + diff --git a/src/corx/cvls/cstate.go b/src/corx/cvls/cstate.go new file mode 100644 index 0000000..f0b4d23 --- /dev/null +++ b/src/corx/cvls/cstate.go @@ -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 AType 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/06/2025 +// ============================================================================= + +package cvls + + +const ( + CStateInvalid CState = 1 << iota // Valor inválido o corrupto (inconsistente) + CStateError // Hubo un error al construir el valor + CStateNil // Valor explícitamente nulo + CStateZero // Valor es cero (valor por defecto) + CStateVersion // Contiene metadatos de versión + CStateReflected // Valor obtenido mediante reflexión + CStateSensitive // Valor sensible (requiere tratamiento especial) + CStateEncoded // Valor fue codificado (ej. serializado) + + CStateNone CState = 0 // Sin banderas activas + cStateOps = CStateSensitive | CStateEncoded // Banderas operativas especiales +) + +// CState define un conjunto de banderas para el tipo CValue (compact value) indicando el +// estado del mismo +type CState uint8 + + + + +// HasInvalid indica que el estado es inválido o inconsistente. +func (s CState) HasInvalid() bool { return s&CStateInvalid != 0 } + +// HasError indica que hubo un error al construir el valor. +func (s CState) HasError() bool { return s&CStateError != 0 } + +// HasNil indica que el valor es nulo explícitamente. +func (s CState) HasNil() bool { return s&CStateNil != 0 } + +// HasZero indica que el valor es igual AType cero (valor por defecto). +func (s CState) HasZero() bool { return s&CStateZero != 0 } + +// HasNilOrZero indica si el valor es nulo o cero. +func (s CState) HasNilOrZero() bool { return s&(CStateZero|CStateNil) != 0 } + +// HasVersion indica que el valor contiene metainformación de versión. +func (s CState) HasVersion() bool { return s&CStateVersion != 0 } + +// HasReflected indica que el valor fue obtenido mediante reflexión. +func (s CState) HasReflected() bool { return s&CStateReflected != 0 } + +// HasSensitive indica que el valor contiene información sensible. +func (s CState) HasSensitive() bool { return s&CStateSensitive != 0 } + +// HasEncoded indica que el valor ha sido codificado. +func (s CState) HasEncoded() bool { return s&CStateEncoded != 0 } + +// HasAny verifica si alguna de las banderas especificadas está activa. +func (s CState) HasAny(flags CState) bool { return s&flags != 0 } diff --git a/src/corx/cvls/ctype.go b/src/corx/cvls/ctype.go new file mode 100644 index 0000000..e8996fd --- /dev/null +++ b/src/corx/cvls/ctype.go @@ -0,0 +1,71 @@ +// ============================================================================= +// 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 AType 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 14/06/2025 +// ============================================================================= + +package cvls + + +// CType representa un tipo compuesto (Compact Type) que combina: +// - un tipo base de valor (VType) +// - un tipo base de clave (KType), usado en estructuras de tipo mapa +// - un tipo de agregado (AType), que describe la naturaleza estructural (list, map, lazy, etc.) +type CType struct { + VType BType // Tipo del valor contenido + KType BType // Tipo de la clave, solo aplicable si es un mapa + AType AType // Tipo de agregado (list, map, lazy, etc.) +} + + + +// CreateCTypeBase crea un CType simple, sin agregado, solo con tipo base de valor. +func CreateCTypeBase(btype BType) CType { return CType{VType: btype} } + +// CreateCTypeList crea un CType que representa una lista de valores del tipo especificado. +func CreateCTypeList(btype BType) CType { return CType{VType: btype, AType: ATypeList} } + +// CreateCTypeLazy crea un CType que representa un valor evaluado de forma perezosa. +func CreateCTypeLazy(btype BType) CType { return CType{VType: btype, AType: ATypeLazy} } + +// CreateCTypeMap crea un CType que representa un mapa con tipo de valor y tipo de clave especificados. +func CreateCTypeMap(vType, kType BType) CType { return CType{VType: vType, KType: kType, AType: ATypeMap} } + + + + +// IsValid verifica si el CType es válido. +// - El tipo de valor debe ser válido. +// - El tipo de agregado debe ser válido. +// - Si el tipo es un mapa, también debe ser válido el tipo de clave. +func (c CType) IsValid() bool { + if !c.VType.IsValid() || !c.AType.IsValid() { + return false + } + if c.AType == ATypeMap && !c.KType.IsValid() { + return false + } + return true +} diff --git a/src/corx/cvls/ctype_info.go b/src/corx/cvls/ctype_info.go new file mode 100644 index 0000000..363d35a --- /dev/null +++ b/src/corx/cvls/ctype_info.go @@ -0,0 +1,331 @@ +// ============================================================================= +// 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 15/06/2025 +// ============================================================================= + +package cvls + +// cTypeInfo contiene metadatos y funciones creadoras de CValue para un tipo base específico (BType). +// Actúa como una tabla de despacho, proporcionando diferentes constructores según cómo se presente +// el valor de entrada (por valor, por puntero, como una función lazy o como una lista/slice). +type ( + cTypeInfo struct { + valType BType // El tipo base (e.g., CBTypeInt, CBTypeString) al que se refiere este bloque de información. + name string // Un nombre legible para el BType. + cByVal func(any) CValue // Función creadora para valores pasados directamente por valor (e.g., int, string). + cByPtr func(any) CValue // Función creadora para valores pasados como punteros (e.g., *int, *string). + cByLazy func(any) CValue // Función creadora para valores encapsulados en una función de evaluación lazy (e.g., func() T). + cByList func(any) CValue // Función creadora para valores como un slice/lista (e.g., []T o []*T). + } +) + +// newCTypeInfo crea una nueva instancia de cTypeInfo para un tipo base dado y su nombre. +// Utiliza el patrón de opciones funcionales para configurar las diversas funciones creadoras de CValue (cByVal, cByPtr, etc.). +// +// BType: El tipo base (e.g., CBTypeInt) para el cual se crea esta información. +// name: Un nombre descriptivo para el BType. +// opts: Funciones opcionales que modifican la cTypeInfo, típicamente utilizadas para establecer las funciones creadoras. +func newCTypeInfo(BType BType, name string, opts ...func(info *cTypeInfo)) *cTypeInfo { + // Inicializa la estructura cTypeInfo con los valores base. + vi := &cTypeInfo{ + valType: BType, + name : name, + } + // Aplica todas las opciones funcionales proporcionadas para configurar la cTypeInfo, + // estableciendo los métodos de creación de CValue. + for _, opt := range opts { + opt(vi) + } + return vi +} + +// optInvalidCreators es una opción funcional que establece todas las funciones creadoras de CValue +// dentro de una cTypeInfo a 'createCInvalid'. +// Esto se usa típicamente para BTypes que no deberían ser instanciados directamente a través de estos +// métodos de despacho, o para señalar un método de creación no soportado. +func optInvalidCreators() func(*cTypeInfo) { + return func (i *cTypeInfo) { + i.cByVal = createCInvalid // Asigna 'createCInvalid' al creador de valores directos. + i.cByPtr = createCInvalid // Asigna 'createCInvalid' al creador de punteros. + i.cByLazy = createCInvalid // Asigna 'createCInvalid' al creador de valores lazy. + i.cByList = createCInvalid // Asigna 'createCInvalid' al creador de listas. + } +} + +// optSameCreators es una opción funcional que asigna una única función creadora de CValue +// a todos los métodos de despacho (por valor, por puntero, lazy, por lista) dentro de una cTypeInfo. +// Esto es útil cuando la lógica de creación de CValue es idéntica independientemente de cómo se presente el valor. +// +// cf: La función creadora de CValue a utilizar para todos los tipos de despacho. +func optSameCreators (cf func(any) CValue) func(info *cTypeInfo) { + return func(i *cTypeInfo) { + i.cByVal = cf // Asigna 'cf' al creador de valores directos. + i.cByPtr = cf // Asigna 'cf' al creador de punteros. + i.cByLazy = cf // Asigna 'cf' al creador de valores lazy. + i.cByList = cf // Asigna 'cf' al creador de listas. + } +} + +// optWithCreators es una opción funcional que permite especificar una función creadora de CValue distinta +// para cada método de despacho (por valor, por puntero, lazy, por lista) dentro de una cTypeInfo. +// Proporciona la máxima flexibilidad para la configuración. +// +// cvalue: Función creadora para valores directos. +// cptr: Función creadora para punteros. +// clazy: Función creadora para valores lazy (funciones). +// clist: Función creadora para valores de lista (slices). +func optWithCreators(cvalue, cptr, clazy, clist func(any) CValue) func (*cTypeInfo) { + return func ( i *cTypeInfo) { + i.cByVal = cvalue // Establece el creador para valores directos. + i.cByPtr = cptr // Establece el creador para punteros. + i.cByLazy = clazy // Establece el creador para valores lazy. + i.cByList = clist // Establece el creador para listas. + } +} + +// optAnyCreators es una opción funcional genérica que configura las funciones creadoras +// para usar principalmente 'CreateCAny' para la mayoría de los métodos de despacho. +// +// Si se proporciona una 'byValueFn' específica, se utilizará para 'cByVal' (manejando la conversión de tipo desde 'any'). +// De lo contrario, 'CreateCAny' también se utilizará para 'cByVal'. +// +// T: El tipo concreto que espera 'byValueFn'. +// byValueFn: Una función creadora opcional para valores directos de tipo T. +// Si es nil, CreateCAny se usará para cByVal. +func optAnyCreators [T any](byValueFn func(v T) CValue) func (*cTypeInfo) { + var cf func(any) CValue + if byValueFn != nil { + // Si se proporciona un creador de valor específico, lo envuelve para manejar la entrada 'any'. + cf = func(v any) CValue { + return byValueFn(v.(T)) // Asume que 'v' puede ser asertado al tipo T. + } + } else { + // Si no hay un creador de valor específico, por defecto usa el genérico CreateCAny. + cf = CreateCAny + } + return func (i *cTypeInfo) { + i.cByVal = cf // Establece el creador para valores directos (específico o genérico). + i.cByPtr = CreateCAny // Establece el creador para punteros al manejador genérico. + i.cByLazy = CreateCAny // Establece el creador para valores lazy al manejador genérico. + i.cByList = CreateCAny // Establece el creador para listas al manejador genérico. + } +} + +// optAnyPCreators es una opción funcional genérica que configura las funciones creadoras +// específicamente para tipos de puntero (e.g., *T), listas de punteros ([]*T), y +// funciones lazy que devuelven punteros (func()*T). +// +// byPtrFnc: La función creadora específica para valores pasados como punteros de tipo *T. +// T: El tipo base concreto para el cual se configuran los creadores de puntero, lista de punteros y lazy de punteros. +func optAnyPCreators [T any](byPtrFnc func(v *T) CValue) func (*cTypeInfo) { + return func(i *cTypeInfo) { + // Envuelve el creador de puntero proporcionado para manejar la entrada 'any' + // asertándola a *T. + cf := func(v any) CValue { return byPtrFnc(v.(*T)) } + i.cByPtr = cf // Establece el creador para punteros. + + // Construye y asigna creadores específicos para listas de punteros y + // funciones lazy que devuelven punteros. + i.cByList = buildCreatorPByList[T](i.valType) // Maneja []T, específicamente []*T. + i.cByLazy = buildCreatorPByLazy[T](i.valType) // Maneja func()T, específicamente func()*T. + } +} + +// optNormalCreators es una opción funcional genérica que configura todas las funciones creadoras de CValue +// (por valor, por puntero, por lista, por lazy) basándose en un creador base proporcionado para valores directos. +// Es adecuada para la mayoría de los tipos "normales" donde las formas de puntero, lista y lazy +// pueden derivarse de la forma de valor. +// +// T: El tipo concreto para el cual se están construyendo los creadores. +// byValueFn: La función creadora base para valores directos de tipo T. +func optNormalCreators [T any](byValueFn func(v T) CValue) func(*cTypeInfo) { + return func(i *cTypeInfo) { + // Envuelve el creador de valor proporcionado para manejar la entrada 'any' asertándola a T. + vf := func(v any) CValue { return byValueFn(v.(T))} + i.cByVal = vf // Establece el creador para valores directos. + + // Construye y asigna creadores específicos para punteros, listas y funciones lazy. + // Estos creadores construidos usarán internamente la 'byValueFn' para convertir + // el valor desreferenciado o evaluado. + i.cByPtr = buildCreatorByPtr [T](i.valType,byValueFn) // Maneja *T (desreferencia a T). + i.cByList = buildCreatorByList[T](i.valType) // Maneja []T. + i.cByLazy = buildCreatorByLazy[T](i.valType) // Maneja func()T. + } +} + +// buildCreatorByPtr construye una función creadora de CValue para tipos de puntero (*T). +// Toma una entrada 'any', la aserta a *T, maneja punteros nil, y luego +// desreferencia el puntero para pasar el valor a la 'byValueFn' proporcionada. +// +// T: El tipo base (no puntero) que maneja 'byValueFn'. +// BType: El CBType correspondiente al tipo base T. Usado para CTypeBase cuando es nil. +// byValueFn: La función creadora de CValue para valores directos de tipo T. +func buildCreatorByPtr [T any](BType BType, byValueFn func(v T) CValue) func(any) CValue { + return func(v any) CValue { + // Intenta asertar la entrada 'any' a un puntero de tipo *T. + vl, ok := v.(*T) + if !ok { + // Si la aserción de tipo falla, significa que la entrada no es *T. + // Devuelve un CValue inválido, con un error indicando una discordancia de tipo. + return createCInvalidError(v, CStateReflected, E.UnexpectedTypeReflected) + } + + // Si el puntero en sí es nil, devuelve un CValue indicando un estado nil. + // El CType reflejará el tipo base T, pero el valor es nil. + if vl == nil { + return CValue{ctype: CreateCTypeBase(BType), state: CStateNil} + } + + // Si el puntero no es nil, desreferéncialo (*vl) y + // usa la 'byValueFn' proporcionada para crear el CValue a partir del valor subyacente. + return byValueFn(*vl) + } +} + +// buildCreatorByList construye una función creadora de CValue para tipos de lista (slices) ([]T). +// Toma una entrada 'any', la aserta a []T, maneja slices nil, slices vacíos, +// y almacena la lista en 'anyVal' junto con su longitud en 'intVal'. +// +// T: El tipo de elemento del slice. +// btype: El CBType correspondiente al tipo de elemento T. Usado para CTypeList. +func buildCreatorByList[T any](btype BType) func(any) CValue { + return func(v any) CValue { + // Intenta asertar la entrada 'any' a un slice de tipo []T. + vl, ok := v.([]T) + if !ok { + // Si la aserción de tipo falla, Devuelve un CValue inválido, con un error + // indicando una discordancia de tipo. + return createCInvalidError(v, CStateReflected, E.UnexpectedTypeReflected) + } + + ln := len(vl) // Obtiene la longitud del slice. + var vs CState // Variable para almacenar el estado de CValue. + + // Determina el estado del slice. + if vl == nil { + // Si el slice en sí es nil, establece CStateNil. + vs = CStateNil + return CValue{ ctype: CreateCTypeList(btype) , state: vs } // Devuelve inmediatamente para un slice nil. + } + // Si el slice no es nil pero su longitud es 0, establece CStateZero. + // De lo contrario, no se establece ningún flag de estado específico (implica CStateNone). + if ln == 0 { + vs = CStateZero + } else { + vs = CStateNone // Establece explícitamente a None si no es nil y no es de longitud cero. + } + + // Devuelve el CValue con el estado determinado, el slice en anyVal y su longitud en intVal. + return CValue{ ctype : CreateCTypeList(btype) , state: vs, anyVal: vl, intVal: int64(ln) } + } +} + +// buildCreatorPByList construye una función creadora de CValue para listas de tipos de puntero ([]*T). +// Toma una entrada 'any', la aserta a []*T, maneja slices nil, slices vacíos, +// y almacena la lista en 'anyVal' junto con su longitud en 'intVal'. +// +// T: El tipo de elemento base del slice de punteros (e.g., si el slice es []*int, T es int). +// btype: El CBType correspondiente al tipo de elemento base T. Usado para CTypeList. +func buildCreatorPByList[T any](btype BType) func(any) CValue { + return func(v any) CValue { + // Intenta asertar la entrada 'any' a un slice de punteros de tipo []*T. + vl, ok := v.([]*T) + if !ok { + // Si la aserción de tipo falla, devuelve un CValue inválido. + return createCInvalidError(v, CStateReflected, E.UnexpectedTypeReflected) + } + + ln := len(vl) // Obtiene la longitud del slice. + var vs CState // Variable para almacenar el estado de CValue. + + // Determina el estado del slice. + if vl == nil { + // Si el slice en sí es nil, establece CStateNil. + vs = CStateNil + return CValue{ ctype : CreateCTypeList(btype), state: vs } // Devuelve inmediatamente para un slice nil. + } + // Si el slice no es nil pero su longitud es 0, establece CStateZero. + // De lo contrario, no se establece ningún flag de estado específico (implica CStateNone). + if ln == 0 { + vs = CStateZero + } else { + vs = CStateNone // Establece explícitamente a None si no es nil y no es de longitud cero. + } + + // Devuelve el CValue con el estado determinado, el slice en anyVal y su longitud en intVal. + return CValue{ ctype : CreateCTypeList(btype) , state: vs, anyVal: vl, intVal: int64(ln) } + } +} + +// buildCreatorByLazy construye una función creadora de CValue para tipos de evaluación lazy (func()T). +// Toma una entrada 'any', la aserta a func()T, maneja funciones nil, +// y almacena la función en 'anyVal'. +// +// T: El tipo de retorno de la función lazy. +// btype: El CBType correspondiente al tipo de retorno T. Usado para CTypeLazy. +func buildCreatorByLazy[T any](btype BType) func(any) CValue { + return func(v any) CValue { + // Intenta asertar la entrada 'any' a una función que devuelve el tipo T. + vl, ok := v.(func()T) + if !ok { + // Si la aserción de tipo falla, devuelve un CValue inválido. + return createCInvalidError(v, CStateReflected, E.UnexpectedTypeReflected) + } + + // Si la función en sí es nil, devuelve un CValue indicando un estado nil. + if vl == nil { + return CValue{ ctype: CreateCTypeLazy(btype), state: CStateNil } + } + + // De lo contrario, devuelve un CValue con la función lazy almacenada en anyVal. + return CValue{ ctype: CreateCTypeLazy(btype), anyVal: vl } + } +} + +// buildCreatorPByLazy construye una función creadora de CValue para tipos de evaluación lazy +// que devuelven punteros (func()*T). +// Toma una entrada 'any', la aserta a func()*T, maneja funciones nil, +// y almacena la función en 'anyVal'. +// +// T: El tipo base del puntero devuelto por la función lazy (e.g., si func() *int, T es int). +// btype: El CBType correspondiente al tipo de retorno base T. Usado para CTypeLazy. +func buildCreatorPByLazy[T any](btype BType) func(any) CValue { + return func(v any) CValue { + // Intenta asertar la entrada 'any' a una función que devuelve un puntero de tipo *T. + vl, ok := v.(func()*T) + if !ok { + // Si la aserción de tipo falla, devuelve un CValue inválido. + return createCInvalidError(v, CStateReflected, E.UnexpectedTypeReflected) + } + // Si la función en sí es nil, devuelve un CValue indicando un estado nil. + if vl == nil { + return CValue{ ctype: CreateCTypeLazy(btype), state: CStateNil } + } + + // De lo contrario, devuelve un CValue con la función lazy almacenada en anyVal. + return CValue{ ctype: CreateCTypeLazy(btype), anyVal: vl } + } +} \ No newline at end of file diff --git a/src/corx/cvls/ctype_infos.go b/src/corx/cvls/ctype_infos.go new file mode 100644 index 0000000..cce07b9 --- /dev/null +++ b/src/corx/cvls/ctype_infos.go @@ -0,0 +1,457 @@ +// ============================================================================= +// 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 16/06/2025 +// ============================================================================= + +package cvls + +import ( + "reflect" + "sync" +) + +type ( + + cTypeInfos struct { + types []*cTypeInfo + mux sync.RWMutex + cache map[reflect.Type]func(reflect.Value) CValue + } +) + + + +func newCTypeInfos() *cTypeInfos { + vi := &cTypeInfos{ + cache : make(map[reflect.Type]func(reflect.Value) CValue), + } + vi.types = []*cTypeInfo{ + /* 00 */ newCTypeInfo(BTypeInvalid ,"invalid" , optInvalidCreators()), + /* 01 */ newCTypeInfo(BTypeAny ,"any" , optAnyCreators [any ](nil)), + /* 02 */ newCTypeInfo(BTypeBool ,"bool" , optNormalCreators [bool ](CreateCBool)), + /* 03 */ newCTypeInfo(BTypeInt ,"int" , optNormalCreators [int ](CreateCInt)), + /* 04 */ newCTypeInfo(BTypeInt8 ,"int8" , optNormalCreators [int8 ](CreateCInt8)), + /* 05 */ newCTypeInfo(BTypeInt16 ,"int16" , optNormalCreators [int16 ](CreateCInt16)), + /* 06 */ newCTypeInfo(BTypeInt32 ,"int32" , optNormalCreators [int32 ](CreateCInt32)), + /* 07 */ newCTypeInfo(BTypeInt64 ,"int64" , optNormalCreators [int64 ](CreateCInt64)), + /* 08 */ newCTypeInfo(BTypeUint ,"uint" , optNormalCreators [uint ](CreateCUint)), + /* 09 */ newCTypeInfo(BTypeUint8 ,"uint8" , + optNormalCreators[uint8](CreateCUint8), + // el creador de []uint8 debe de reportar el tipo Bytes y debe de llamar a su creador CreateCBytes + func(i *cTypeInfo) { i.cByList = func(v any) CValue { return CreateCBytes(v.(Bytes)) } }), + /* 10 */ newCTypeInfo(BTypeUint16 ,"uint16" , optNormalCreators [uint16 ](CreateCUint16)), + /* 11 */ newCTypeInfo(BTypeUint32 ,"uint32" , optNormalCreators [uint32 ](CreateCUint32)), + /* 12 */ newCTypeInfo(BTypeUint64 ,"uint64" , optNormalCreators [uint64 ](CreateCUint64)), + /* 13 */ newCTypeInfo(BTypeUintptr ,"uintptr" , optNormalCreators [uintptr ](CreateCUintptr)), + /* 14 */ newCTypeInfo(BTypeDuration ,"duration" , optNormalCreators [Duration ](CreateCDuration)), + + /* 15 */ newCTypeInfo(BTypeFloat32 ,"float32" , optNormalCreators [float32 ](CreateCFloat32)), + /* 16 */ newCTypeInfo(BTypeFloat64 ,"float64" , optNormalCreators [float64 ](CreateCFloat64)), + + /* 17 */ newCTypeInfo(BTypeComplex64 ,"complex64" , optNormalCreators [complex64 ](CreateCComplex64 )), + /* 18 */ newCTypeInfo(BTypeComplex128 ,"complex128" , optNormalCreators [complex128 ](CreateCComplex128)), + + // Big Int tiene una forma canonica de *big.Int, lo cual hace cambiar los constructores de Ptr ya que no lo + // debe des referenciar, en caso de que se pase por valor, debemos de convertirlo a un *BigInt, copiar su + // valor y una vez pasado llamar a la funcion de creacion CreateCBigInt + /* 19 */ newCTypeInfo(BTypeBigInt ,"bigint" , func(i *cTypeInfo) { + i.cByVal = func (v any) CValue { + bv := v.(BigInt) + return CreateCBigInt(new(BigInt).Set(&bv)) + } + i.cByPtr = func (v any) CValue { return CreateCBigInt(v.(*BigInt)) } + i.cByLazy= buildCreatorPByLazy[BigInt](BTypeBigInt) + i.cByList= buildCreatorPByList[BigInt](BTypeBigInt) + }), + /* 20 */ newCTypeInfo(BTypeHashAlg ,"hashalg" , optNormalCreators [HashAlg ](CreateCHashAlg)), + + + /* 21 */ newCTypeInfo(BTypeString ,"string" , optNormalCreators [string ](CreateCString)), + /* 22 */ newCTypeInfo(BTypeUUID ,"uuid" , optNormalCreators [UUID ](CreateCUUID)), + /* 23 */ newCTypeInfo(BTypeBytes ,"bytes" , optNormalCreators [Bytes ](CreateCBytes)), + /* 24 */ newCTypeInfo(BTypeStack ,"stack" , optNormalCreators [Stack ](CreateCStack)), + + /* 25 */ newCTypeInfo(BTypeDate ,"date" , optNormalCreators [Date ](CreateCDate)), + /* 26 */ newCTypeInfo(BTypeCValue ,"cvalue" , optNormalCreators [CValue ](CreateCCValue)), + /* 27 */ newCTypeInfo(BTypeReflect ,"reflect" , optNormalCreators [Reflect ](CreateCReflect)), + /* 28 */ newCTypeInfo(BTypeObject ,"object" , optAnyCreators [any ](CreateCAny)), + + // Los interfaces solo se evaluate en su forma canonical + + /* 29 */ newCTypeInfo(BTypeListPackable ,"listpackable",optAnyCreators [ListPackable](CreateCListPackable)), + /* 30 */ newCTypeInfo(BTypeMapPackable ,"mappackable", optAnyCreators [MapPackable](CreateCMapPackable)), + /* 31 */ newCTypeInfo(BTypeObjPackable ,"objpackable", optAnyCreators [ObjPackable](CreateCObjectPackable)), + /* 32 */ newCTypeInfo(BTypePackable ,"packable" , optAnyCreators [Packable ](CreateCPackable)), + + /* 33 */ newCTypeInfo(BTypeContext ,"context" , optAnyCreators [Context ](CreateCContext)), + /* 34 */ newCTypeInfo(BTypeError ,"error" , optNormalCreators [error ](CreateCError)), + /* 35 */ newCTypeInfo(BTypeStringer ,"stringer" , optNormalCreators [Stringer ](CreateCStringer)) , + + /* 36 */ newCTypeInfo(BTypeNil , "nil" , optSameCreators (CreateCNil)), + + } + + return vi +} + + +func (i *cTypeInfos) createCValue (value any) CValue { + if value == nil { + return CValue{ ctype: CreateCTypeBase(BTypeAny), state: CStateNil } + } + + var f func(any) CValue = nil + + switch value.(type) { + /* Valores simples */ + //case any : f = i.types[BTypeAny ].cByVal + case bool : f = i.types[BTypeBool ].cByVal + case int : f = i.types[BTypeInt ].cByVal + case int8 : f = i.types[BTypeInt8 ].cByVal + case int16 : f = i.types[BTypeInt16 ].cByVal + case int32 : f = i.types[BTypeInt32 ].cByVal + case int64 : f = i.types[BTypeInt64 ].cByVal + case uint : f = i.types[BTypeUint ].cByVal + case uint8 : f = i.types[BTypeUint8 ].cByVal + case uint16 : f = i.types[BTypeUint16 ].cByVal + case uint32 : f = i.types[BTypeUint32 ].cByVal + case uint64 : f = i.types[BTypeUint64 ].cByVal + case uintptr : f = i.types[BTypeUintptr ].cByVal + case float32 : f = i.types[BTypeFloat32 ].cByVal + case float64 : f = i.types[BTypeFloat64 ].cByVal + case complex64 : f = i.types[BTypeComplex64 ].cByVal + case complex128 : f = i.types[BTypeComplex128 ].cByVal + case Date : f = i.types[BTypeDate ].cByVal + case Duration : f = i.types[BTypeDuration ].cByVal + case string : f = i.types[BTypeString ].cByVal + case Bytes : f = i.types[BTypeBytes ].cByVal + case Stack : f = i.types[BTypeStack ].cByVal + case CValue : f = i.types[BTypeCValue ].cByVal + case Context : f = i.types[BTypeContext ].cByVal + case error : f = i.types[BTypeError ].cByVal + + case Reflect : f = i.types[BTypeReflect ].cByVal + case UUID : f = i.types[BTypeUUID ].cByVal + case HashAlg : f = i.types[BTypeHashAlg ].cByVal + case Stringer : f = i.types[BTypeStringer ].cByVal + case BigInt : f = i.types[BTypeBigInt ].cByVal + case MapPackable : f = i.types[BTypeMapPackable ].cByVal + case ListPackable : f = i.types[BTypeListPackable ].cByVal + case ObjPackable : f = i.types[BTypeObjPackable ].cByVal + case Packable : f = i.types[BTypePackable ].cByVal + + + + + /* Valores Listas */ + case []any : f = i.types[BTypeAny ].cByList + case []bool : f = i.types[BTypeBool ].cByList + case []int : f = i.types[BTypeInt ].cByList + case []int8 : f = i.types[BTypeInt8 ].cByList + case []int16 : f = i.types[BTypeInt16 ].cByList + case []int32 : f = i.types[BTypeInt32 ].cByList + case []int64 : f = i.types[BTypeInt64 ].cByList + case []uint : f = i.types[BTypeUint ].cByList + // ya establecido como tipo base Bytes + //case []uint8 : + // + case []uint16 : f = i.types[BTypeUint16 ].cByList + case []uint32 : f = i.types[BTypeUint32 ].cByList + case []uint64 : f = i.types[BTypeUint64 ].cByList + case []uintptr : f = i.types[BTypeUintptr ].cByList + case []float32 : f = i.types[BTypeFloat32 ].cByList + case []float64 : f = i.types[BTypeFloat64 ].cByList + case []complex64 : f = i.types[BTypeComplex64 ].cByList + case []complex128 :f = i.types[BTypeComplex128 ].cByList + case []Duration : f = i.types[BTypeDuration ].cByList + case []Date : f = i.types[BTypeDate ].cByList + case []string : f = i.types[BTypeString ].cByList + case []Bytes : f = i.types[BTypeBytes ].cByList + //case []Stack : f = i.types[BTypeStack ].cByList + case []CValue : f = i.types[BTypeCValue ].cByList + //case []Context : f = i.types[BTypeContext ].cByList + case []error : f = i.types[BTypeError ].cByList + + case []UUID : f = i.types[BTypeUUID ].cByList + //case []HashAlg : f = i.types[BTypeHashAlg ].cByList + //case []Reflect : f = i.types[BTypeReflect ].cByList + //case []Stringer : f = i.types[BTypeStringer ].cByList + //case []*BigInt : f = i.types[BTypeBigInt ].cByList + //case []MapPackable : f = i.types[BTypeMapPackable ].cByList + //case []ListPackable : f = i.types[BTypeListPackable ].cByList + //case []ObjPackable : f = i.types[BTypeObjPackable ].cByList + //case []Packable : f = i.types[BTypePackable ].cByList + + + + + /* Valores pasados por punteros */ + //case *any : f = i.types[ 1/* Any */].cByPtr + case *bool : f = i.types[BTypeBool ].cByPtr + case *int : f = i.types[BTypeInt ].cByPtr + case *int8 : f = i.types[BTypeInt8 ].cByPtr + case *int16 : f = i.types[BTypeInt16 ].cByPtr + case *int32 : f = i.types[BTypeInt32 ].cByPtr + case *int64 : f = i.types[BTypeInt64 ].cByPtr + case *uint : f = i.types[BTypeUint ].cByPtr + case *uint8 : f = i.types[BTypeUint8 ].cByPtr + case *uint16 : f = i.types[BTypeUint16 ].cByPtr + case *uint32 : f = i.types[BTypeUint32 ].cByPtr + case *uint64 : f = i.types[BTypeUint64 ].cByPtr + case *uintptr : f = i.types[BTypeUintptr ].cByPtr + case *float32 : f = i.types[BTypeFloat32 ].cByPtr + case *float64 : f = i.types[BTypeFloat64 ].cByPtr + case *complex64 : f = i.types[BTypeComplex64 ].cByPtr + case *complex128 : f = i.types[BTypeComplex128 ].cByPtr + case *Duration : f = i.types[BTypeDuration ].cByPtr + case *Date : f = i.types[BTypeDate ].cByPtr + case *string : f = i.types[BTypeString ].cByPtr + case *Bytes : f = i.types[BTypeBytes ].cByPtr + case *Stack : f = i.types[BTypeStack ].cByPtr + case *CValue : f = i.types[BTypeCValue ].cByPtr + + //case *Context : f = i.types[BTypeContext ].cByPtr + //case *error : f = i.types[BTypeError ].cByPtr + + //case *UUID : f = i.types[BTypeUUID ].cByPtr + //case *HashAlg : f = i.types[BTypeHashAlg ].cByPtr + //case *Reflect : f = i.types[BTypeReflect ].cByPtr + //case *Stringer : f = i.types[BTypeStringer ].cByPtr + //case *BigInt : f = i.types[BTypeBigInt ].cByPtr + //case *MapPackable : f = i.types[BTypeMapPackable ].cByPtr + //case *ListPackable : f = i.types[BTypeListPackable ].cByPtr + //case *ObjPackable : f = i.types[BTypeObjPackable ].cByPtr + //case *Packable : f = i.types[BTypePackable ].cByPtr + + + + /* Valores pasados por functions Lazys */ + case func()any : f = i.types[BTypeAny ].cByLazy + case func()bool : f = i.types[BTypeBool ].cByLazy + case func()int : f = i.types[BTypeInt ].cByLazy + case func()int8 : f = i.types[BTypeInt8 ].cByLazy + case func()int16 : f = i.types[BTypeInt16 ].cByLazy + case func()int32 : f = i.types[BTypeInt32 ].cByLazy + case func()int64 : f = i.types[BTypeInt64 ].cByLazy + case func()uint : f = i.types[BTypeUint ].cByLazy + case func()uint8 : f = i.types[BTypeUint8 ].cByLazy + case func()uint16 : f = i.types[BTypeUint16 ].cByLazy + case func()uint32 : f = i.types[BTypeUint32 ].cByLazy + case func()uint64 : f = i.types[BTypeUint64 ].cByLazy + case func()uintptr : f = i.types[BTypeUintptr ].cByLazy + case func()float32 : f = i.types[BTypeFloat32 ].cByLazy + case func()float64 : f = i.types[BTypeFloat64 ].cByLazy + case func()complex64 : f = i.types[BTypeComplex64 ].cByLazy + case func()complex128 :f = i.types[BTypeComplex128 ].cByLazy + case func()Duration : f = i.types[BTypeDuration ].cByLazy + case func()Date : f = i.types[BTypeDate ].cByLazy + case func()string : f = i.types[BTypeString ].cByLazy + case func()Bytes : f = i.types[BTypeBytes ].cByLazy + case func()Stack : f = i.types[BTypeStack ].cByLazy + case func()CValue : f = i.types[BTypeCValue ].cByLazy + case func()Context : f = i.types[BTypeContext ].cByLazy + case func()error : f = i.types[BTypeError ].cByLazy + + case func()UUID : f = i.types[BTypeUUID ].cByLazy + case func()HashAlg : f = i.types[BTypeHashAlg ].cByLazy + case func()Reflect : f = i.types[BTypeReflect ].cByLazy + case func()Stringer : f = i.types[BTypeStringer ].cByLazy + case func()*BigInt : f = i.types[BTypeBigInt ].cByLazy + case func()MapPackable : f = i.types[BTypeMapPackable ].cByLazy + case func()ListPackable : f = i.types[BTypeListPackable ].cByLazy + case func()ObjPackable : f = i.types[BTypeObjPackable ].cByLazy + case func()Packable : f = i.types[BTypePackable ].cByLazy + } + + if f != nil { + return f(value) + } + + return i.CreateByReflection(value) + +} + + + + +func (i *cTypeInfos) CreateByReflection(value any) CValue { + rv := reflect.ValueOf(value) + if !rv.IsValid() { + return createCInvalidError(rv,CStateReflected,E.InvalidReflectValue) + } + rt := rv.Type() + + i.mux.RLock() + rf,ok := i.cache[rt] + i.mux.RUnlock() + if ok { + return rf(rv) + } + + switch rt.Kind() { + // Los tipos soportados deben de haber sido capturados + // por el switch de tipos + case reflect.Struct : // createCValueAny + rf = createCValueRObj(rt.String()) + + case reflect.Func : + if rt.NumIn() == 0 && rt.NumOut() == 1 { + // Si fuera el tipo del valor devuelto conocido ya lo habria + // interceptado el switch de tipos, devolvemos un lazy|any + // + et:= reflectKindToCType(rt.Out(0).Kind()) + rf = createCValueRLazy(CreateCTypeLazy(et.VType),rt.String()) + } + + case reflect.Slice, + reflect.Array : + vt := reflectKindToCType(rt.Elem().Kind()) + if vt.VType != BTypeInvalid { + rf = createCValueRList(CreateCTypeList(vt.VType),rt.String()) + } + + case reflect.Map : + if kt := reflectKindToCType(rt.Key().Kind()); kt.VType.IsValid() { + if et := reflectKindToCType(rt.Elem().Kind()); et.VType.IsValid() { + rf = createCValueRMap(CreateCTypeMap(et.VType,kt.VType),rt.String()) + } + } + } + + if rf == nil { + rf = createCValueRAny(rt.String()) + } + + + i.mux.Lock() + i.cache[rt]=rf + i.mux.Unlock() + + return rf(rv) +} + + + + + +func createCValueRList (vtype CType, tname string) func(reflect.Value) CValue { + return func(rv reflect.Value) CValue { + vt := vtype + tn := tname + vs := CStateReflected + ln := rv.Len() + if ln == 0 { + if rv.IsNil() { + vs |= CStateNil + } else { + vs |= CStateZero + } + } + return CValue{ctype: vt, state: vs, anyVal: rv, strVal: tn, intVal: int64(ln)} + } +} + + +func createCValueRMap (vtype CType, tname string) func (value reflect.Value) CValue { + return func(rv reflect.Value) CValue { + vt := vtype + tn := tname + vs := CStateReflected + ln := rv.Len() + if ln == 0 { + if rv.IsNil() { + vs |= CStateNil + } else { + vs |= CStateZero + } + } + return CValue{ctype: vt , state: vs, anyVal: rv, strVal: tn, intVal: int64(ln)} + } +} + + +func createCValueRLazy (vtype CType, tname string) func (value reflect.Value) CValue { + return func(rv reflect.Value) CValue { + vt := vtype + tn := tname + vs := CStateReflected + if rv.IsNil() { + vs |= CStateNil + } + return CValue {ctype: vt, state: vs, strVal: tn, anyVal: rv} + } +} + + +func createCValueRObj (tname string) func(reflect.Value) CValue { + return func(rv reflect.Value) CValue { + tn := tname + return CValue{ctype: CreateCTypeBase (BTypeObject), state: CStateReflected, strVal: tn, anyVal: rv} + } +} + + +func createCValueRAny (tname string) func(reflect.Value) CValue { + return func(rv reflect.Value) CValue { + tn := tname + return CValue{ ctype: CreateCTypeBase (BTypeAny), state: CStateReflected, strVal: tn, anyVal: rv} + } +} + + + +func reflectKindToCType (kind reflect.Kind) CType { + switch kind { + case reflect.Invalid: return CType{ VType: BTypeInvalid } + case reflect.String : return CType{ VType: BTypeString } + case reflect.Int : return CType{ VType: BTypeInt } + case reflect.Uint : return CType{ VType: BTypeUint } + case reflect.Bool : return CType{ VType: BTypeBool } + case reflect.Int8 : return CType{ VType: BTypeInt8 } + case reflect.Int16 : return CType{ VType: BTypeInt16 } + case reflect.Int32 : return CType{ VType: BTypeInt32 } + case reflect.Int64 : return CType{ VType: BTypeInt64 } + case reflect.Uint8 : return CType{ VType: BTypeUint8 } + case reflect.Uint16 : return CType{ VType: BTypeUint16 } + case reflect.Uint32 : return CType{ VType: BTypeUint32 } + case reflect.Uint64 : return CType{ VType: BTypeUint64 } + case reflect.Uintptr: return CType{ VType: BTypeUintptr } + case reflect.Float32: return CType{ VType: BTypeFloat32 } + case reflect.Float64: return CType{ VType: BTypeFloat64 } + case reflect.Struct : return CType{ VType: BTypeObject } + + case reflect.Array, + reflect.Slice : return CType{ VType: BTypeAny, AType: ATypeList } + case reflect.Map : return CType{ VType: BTypeAny, AType: ATypeMap } + case reflect.Func : return CType{ VType: BTypeAny, AType: ATypeLazy } + + case reflect.Complex64 : return CType{ VType: BTypeComplex64 } + case reflect.Complex128: return CType{ VType: BTypeComplex128} + } + + return CType{ VType: BTypeAny } +} + diff --git a/src/corx/cvls/cvalue.go b/src/corx/cvls/cvalue.go new file mode 100644 index 0000000..56cde15 --- /dev/null +++ b/src/corx/cvls/cvalue.go @@ -0,0 +1,270 @@ +// ============================================================================= +// 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 15/06/2025 +// ============================================================================= + +package cvls + +import ( + "math" + "reflect" +) + +// CValue representa un valor de tipo dinámico con su tipo base (ctype), estado (state) y valores posibles. +type ( + CValue struct { + _ [0]func() // Padding para prevenir comparaciones automáticas (zero-size field) + ctype CType // Tipo base del valor + state CState // Estado del valor (Zero, Nil, Error, etc.) + intVal int64 // Representación numérica si aplica + strVal string // Representación de string si aplica + anyVal any // Valor genérico (interface{}) + } +) + +// Cualquier valor genérico +func CreateCAny(v any) CValue { + if v == nil { + return CValue{ctype: CreateCTypeBase(BTypeAny), state: CStateNil} + } + return CValue{ctype: CreateCTypeBase(BTypeAny), anyVal: v} +} + +// Booleano +func CreateCBool(v bool) CValue { + if !v { + return CValue{ctype: CreateCTypeBase(BTypeBool), state: CStateZero} + } + return CValue{ctype: CreateCTypeBase(BTypeBool), intVal: 1} +} + +// Tipos enteros con funciones genéricas +func CreateCInt (v int ) CValue { return createCInts[int ](v, BTypeInt) } +func CreateCInt8 (v int8 ) CValue { return createCInts[int8 ](v, BTypeInt8) } +func CreateCInt16 (v int16 ) CValue { return createCInts[int16 ](v, BTypeInt16) } +func CreateCInt32 (v int32 ) CValue { return createCInts[int32 ](v, BTypeInt32) } +func CreateCInt64 (v int64 ) CValue { return createCInts[int64 ](v, BTypeInt64) } + +// Tipos unsigned +func CreateCUint (v uint ) CValue { return createCUints[uint ](v, BTypeUint) } +func CreateCUint8 (v uint8 ) CValue { return createCUints[uint8 ](v, BTypeUint8) } +func CreateCUint16 (v uint16 ) CValue { return createCUints[uint16 ](v, BTypeUint16) } +func CreateCUint32 (v uint32 ) CValue { return createCUints[uint32 ](v, BTypeUint32) } +func CreateCUint64 (v uint64 ) CValue { return createCUints[uint64 ](v, BTypeUint64) } +func CreateCUintptr (v uintptr ) CValue { return createCUints[uintptr ](v, BTypeUintptr) } +func CreateCDuration(v Duration ) CValue { return createCUints[Duration ](v, BTypeDuration) } +func CreateCHashAlg (v HashAlg ) CValue { return createCUints[HashAlg ](v, BTypeHashAlg) } + +// Tipos float +func CreateCFloat32(v float32) CValue { + if v == 0 { + return CValue{ctype: CreateCTypeBase(BTypeFloat32), state: CStateZero} + } + return CValue{ctype: CreateCTypeBase(BTypeFloat32), intVal: int64(math.Float32bits(v))} +} + +func CreateCFloat64(v float64) CValue { + if v == 0 { + return CValue{ctype: CreateCTypeBase(BTypeFloat64), state: CStateZero} + } + b := math.Float64bits(v) + if b > math.MaxInt64 { + return CValue{ctype: CreateCTypeBase(BTypeFloat64), state: CStateVersion, anyVal: v} + } + return CValue{ctype: CreateCTypeBase(BTypeFloat64), intVal: int64(b)} +} + +// Complejos +func CreateCComplex64 (v complex64 ) CValue { return createCCmplx[complex64 ](v, BTypeComplex64) } +func CreateCComplex128(v complex128) CValue { return createCCmplx[complex128 ](v, BTypeComplex128) } + +// BigInt +func CreateCBigInt(v *BigInt) CValue { + if v.Cmp(g.bigZero) == 0 { + return CValue{ctype: CreateCTypeBase(BTypeBigInt), state: CStateZero} + } + return CValue{ctype: CreateCTypeBase(BTypeBigInt), anyVal: v} +} + +// String +func CreateCString(v string) CValue { + if v == "" { + return CValue{ctype: CreateCTypeBase(BTypeString), state: CStateZero} + } + return CValue{ctype: CreateCTypeBase(BTypeString), strVal: v} +} + +// Listas y estructuras similares +func CreateCBytes(v Bytes) CValue { return createCList[Bytes](v, BTypeBytes) } +func CreateCStack(v Stack) CValue { return createCList[Stack](v, BTypeStack) } + +// UUID +func CreateCUUID(v UUID) CValue { + if v == g.uuidZero { + return CValue{ctype: CreateCTypeBase(BTypeUUID), state: CStateZero} + } + return CValue{ctype: CreateCTypeBase(BTypeUUID), anyVal: v} +} + +// Fecha +func CreateCDate(v Date) CValue { + if v.IsZero() { + return CValue{ctype: CreateCTypeBase(BTypeDate), state: CStateZero} + } + if v.After(g.minTime) && v.Before(g.maxTime) { + return CValue{ + ctype: CreateCTypeBase(BTypeDate), state: CStateVersion, + intVal: v.UnixNano(), anyVal: v.Location(), + } + } + return CValue{ctype: CreateCTypeBase(BTypeDate), anyVal: v} +} + +// Tipos especiales y genéricos +func CreateCCValue(v CValue) CValue { return CValue{ctype: CreateCTypeBase(BTypeCValue), anyVal: v} } +func CreateCReflect(v reflect.Value) CValue { + if !v.IsValid() { + return CValue{ctype: CreateCTypeBase(BTypeReflect), state: CStateInvalid} + } + return CValue{ctype: CreateCTypeBase(BTypeReflect), anyVal: v} +} + +// Interfaces packables +func CreateCListPackable (v ListPackable ) CValue { return createCIfcs (BTypeListPackable,v) } +func CreateCMapPackable (v MapPackable ) CValue { return createCIfcs (BTypeMapPackable ,v) } +func CreateCObjectPackable (v ObjPackable ) CValue { return createCIfcs (BTypeObjPackable ,v) } +func CreateCPackable (v Packable ) CValue { return createCIfcs (BTypePackable ,v) } +func CreateCContext (v Context ) CValue { return createCIfcs (BTypeContext ,v) } +func CreateCError (v error ) CValue { return createCIfcs (BTypeError ,v) } +func CreateCStringer (v Stringer ) CValue { return createCIfcs (BTypeStringer ,v) } + +// Valores nulos o inválidos +func CreateCNil(_ any) CValue { + return CValue{ctype: CreateCTypeBase(BTypeNil), state: CStateNil} +} + +func createCInvalid(_ any) CValue { + return CValue{ctype: CreateCTypeBase(BTypeInvalid), state: CStateInvalid} +} + +func createCInvalidError(value any, s CState, err string) CValue { + s = CStateError | CStateInvalid + if value == nil { + s |= CStateNil + } + return CValue{ctype: CreateCTypeBase(BTypeInvalid), state: s, strVal: err, anyVal: value} +} + +// Añadir o combinar un estado a un valor +func (v CValue) WithState(state CState) CValue { + v.state |= state & cStateOps + return v +} + +// Funciones genéricas internas + +func createCInts[T ints](v T, t BType) CValue { + if v == 0 { + return CValue{ctype: CreateCTypeBase(t), state: CStateZero} + } + return CValue{ctype: CreateCTypeBase(t), intVal: int64(v)} +} + +func createCUints[T uints](v T, t BType) CValue { + if v == 0 { + return CValue{ctype: CreateCTypeBase(t), state: CStateZero} + } + if (t == BTypeUint64 || t == BTypeUintptr) && uint64(v) > math.MaxInt64 { + return CValue{ctype: CreateCTypeBase(t), state: CStateVersion, anyVal: v} + } + return CValue{ctype: CreateCTypeBase(t), intVal: int64(v)} +} + +func createCCmplx[T cmplx](v T, t BType) CValue { + if v == 0 { + return CValue{ctype: CreateCTypeBase(t), state: CStateZero} + } + return CValue{ctype: CreateCTypeBase(t), anyVal: v} +} + +func createCList[T lists](v T, t BType) CValue { + if v == nil { + return CValue{ctype: CreateCTypeBase(t), state: CStateNil} + } + ln := len(v) + if ln == 0 { + return CValue{ctype: CreateCTypeBase(t), state: CStateZero, anyVal: v} + } + return CValue{ctype: CreateCTypeBase(t), anyVal: v, intVal: int64(ln)} +} + +// createCIfcs crea un CValue para interfaces. +// Solo detecta interfaces completamente nil (v == nil). +// La detección de punteros nil envueltos en interfaces se delega +// al programador por razones de rendimiento. +func createCIfcs(t BType, v any) CValue { + if v == nil { + return CValue{ctype: CreateCTypeBase(t), anyVal: v, state: CStateNil} + } + + /* + // Código comentado: detección automática de nil envueltos + // Se omite por el costo de rendimiento de la reflection + else { + // Operación costosa: reflection para detectar valores nil + // envueltos en interfaces (ej: (*struct{})(nil) asignado a interface) + // Delegamos esta responsabilidad al programador + + rv := reflect.ValueOf(v) + s |= CStateReflected + switch rv.Kind() { + case reflect.Ptr, reflect.Interface, reflect.Func, reflect.Chan, reflect.Map, reflect.Slice: + if rv.IsNil() { + s |= CStateNil + } + } + } + */ + + // El programador debe de implementar las funciones IsNil específicas + // del interface (ej: IsNilError, IsNilListPackable) antes de llamar + // a esta función, o en su defecto asegurarse que el interface + // no va a ser nil. + // + // IsNilError verifica si un error interface es nil, + // incluyendo punteros nil envueltos en el interface. + /* + func IsNilError(err error) bool { + if err == nil { + return true + } + // Verifica si el valor subyacente es nil + return reflect.ValueOf(err).IsNil() + } + + */ + return CValue{ctype: CreateCTypeBase(t), anyVal: v} +} \ No newline at end of file diff --git a/src/corx/go.mod b/src/corx/go.mod new file mode 100644 index 0000000..d7f10d9 --- /dev/null +++ b/src/corx/go.mod @@ -0,0 +1,3 @@ +module corx + +go 1.24 diff --git a/src/go.work b/src/go.work index 7ab2b82..bf72bb3 100644 --- a/src/go.work +++ b/src/go.work @@ -5,4 +5,5 @@ use ( app base core + corx ) \ No newline at end of file