You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

560 lines
16 KiB

/* ——————————————————————————————————————————————————————————————————————————
Proyecto goat
—————————————————————————————————————————————————————————————————————————————
Fichero go
Package cvls
Autor Juan V. Navarro juanvnl@activething.com
Creado 05/02/2026
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
-------------------------
This software is licensed under the Elastic License v2.0 (the "License").
For full terms and additional information regarding permitted and prohibited
uses, please visit:
https://activething.com/ATGO/licenses
You may use, copy, modify, and redistribute this software internally within
your organization for any purpose, including research, development, and
testing, subject to the terms of this License.
You may NOT, however, use, provide, distribute, or make this software
available to any third party as part of a hosted service, SaaS offering, or
commercial product without first obtaining a commercial license from
Active Thing.
You may combine this software with other code, provided that such
combination does not circumvent the restrictions of this License.
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 NON-INFRINGEMENT. In no event shall
the authors or copyright holders be liable for any claim, damages, or other
liability arising from the use of this software.
—————————————————————————————————————————————————————————————————————————————
Web : activething.com | activething.com/goat
git : g.activething.com | github.com/activething/goat
Correo : dev@activething.com
—————————————————————————————————————————————————————————————————————————————
No deseo caminar sobre el agua", dijo Siddhartha.
Que los antiguos chamanes se contenten con tales habilidades.
—— Hermann Hesse, Siddhartha
—————————————————————————————————————————————————————————————————————————————
Copyright (c) 2026 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package cvls
import (
"core/errs"
"math"
"time"
"unsafe"
)
type CValue struct {
Spec // uint16 - 2
State // uint8 - 1
intVal int64 // - 8
strVal string // -16
anyVal any // -16
}
func MakeCValue(value any) CValue {
return specs.createCValue(value)
}
func MakeCValueAny(val any) CValue {
if val == nil {
return CValue{Spec: makeSpecScalar(KindAny), State: StateNil}
}
return CValue{Spec: makeSpecScalar(KindAny), anyVal: val}
}
func MakeCValueBool(val bool) CValue {
if !val {
return CValue{Spec: makeSpecScalar(KindBool), State: StateZero}
}
return CValue{Spec: makeSpecScalar(KindBool), intVal: 1}
}
func MakeCValueString(val string) CValue {
if val == "" {
return CValue{Spec: makeSpecScalar(KindString), State: StateZero}
}
return CValue{Spec: makeSpecScalar(KindString), strVal: val}
}
func MakeCValueInt(val int) CValue { return makeCInts[int](val, KindInt) }
func MakeCValueInt8(val int8) CValue { return makeCInts[int8](val, KindInt8) }
func MakeCValueInt16(val int16) CValue { return makeCInts[int16](val, KindInt16) }
func MakeCValueInt32(val int32) CValue { return makeCInts[int32](val, KindInt32) }
func MakeCValueInt64(val int64) CValue { return makeCInts[int64](val, KindInt64) }
func MakeCValueDuration(val Duration) CValue { return makeCInts[Duration](val, KindDuration) }
func MakeCValueUint(val uint) CValue { return makeCUints[uint](val, KindUint) }
func MakeCValueUint8(val uint8) CValue { return makeCUints[uint8](val, KindUint8) }
func MakeCValueUint16(val uint16) CValue { return makeCUints[uint16](val, KindUint16) }
func MakeCValueUint32(val uint32) CValue { return makeCUints[uint32](val, KindUint32) }
func MakeCValueUint64(val uint64) CValue { return makeCUints[uint64](val, KindUint64) }
func MakeCValueUintptr(val uintptr) CValue { return makeCUints[uintptr](val, KindUintptr) }
func MakeCValueHashAlg(val HashAlg) CValue { return makeCUints[HashAlg](val, KindHashAlg) }
func MakeCValueFloat32(val float32) CValue {
if val == 0 {
return CValue{Spec: makeSpecScalar(KindFloat32), State: StateZero}
}
return CValue{Spec: makeSpecScalar(KindFloat32), intVal: int64(math.Float32bits(val))}
}
func MakeCValueFloat64(val float64) CValue {
if val == 0 {
return CValue{Spec: makeSpecScalar(KindFloat64), State: StateZero}
}
return CValue{Spec: makeSpecScalar(KindFloat64), intVal: int64(math.Float64bits(val))}
}
func MakeCValueComplex64(val complex64) CValue { return makeCComplex[complex64](val, KindComplex64) }
func MakeCValueComplex128(val complex128) CValue {
return makeCComplex[complex128](val, KindComplex128)
}
func MakeCValueBytes(val Bytes) CValue {
if val == nil {
return CValue{Spec: makeSpecList(KindBytes), State: StateNil}
}
if len(val) == 0 {
return CValue{Spec: makeSpecList(KindBytes), State: StateZero}
}
// Convertimos []byte a string sin copiar memoria (Zero-copy).
// Esto evita que el slice escape al heap vía anyVal.
// Requiere Go 1.20+
s := unsafe.String(unsafe.SliceData(val), len(val))
return CValue{
Spec: makeSpecList(KindBytes),
strVal: s, // Guardamos en el campo string
}
}
func MakeCValueStack(val Stack) CValue { return makeCList[Stack](val, KindStack) }
func MakeCValueUUID(val UUID) CValue {
if val == uuidZero {
return CValue{Spec: makeSpecScalar(KindUUID), State: StateZero}
}
return CValue{Spec: makeSpecScalar(KindUUID), strVal: string(val[:])}
}
func MakeCValueDate(val Date) CValue {
if val.IsZero() {
return CValue{Spec: makeSpecScalar(KindDate), State: StateZero}
}
return CValue{
Spec: makeSpecScalar(KindDate),
State: StateVersion,
intVal: val.UnixNano()}
}
func MakeCValueReflect(val Reflect) CValue {
if !val.IsValid() {
return CValue{Spec: makeSpecScalar(KindReflect), State: StateInvalid}
}
return CValue{Spec: makeSpecScalar(KindReflect), anyVal: val}
}
func MakeCValuePackable(val Packable) CValue {
if val == nil {
return CValue{Spec: makeSpecScalar(KindPackable), State: StateNil}
}
return CValue{Spec: makeSpecScalar(KindPackable), anyVal: val}
}
func MakeCValueStringer(val Stringer) CValue {
if val == nil {
return CValue{Spec: makeSpecScalar(KindStringer), State: StateNil}
}
return CValue{Spec: makeSpecScalar(KindStringer), anyVal: val}
}
func MakeCValueError(val error) CValue {
if val == nil {
return CValue{Spec: makeSpecScalar(KindError), State: StateNil}
}
return CValue{Spec: makeSpecScalar(KindError), anyVal: val}
}
// Value Devuelve el valor almacenado en
// el CValue
func (v CValue) Value() any {
// Casos especiales de estado
if v.HasNil() {
return nil
}
var val any
switch v.ValueKind() {
case KindBool:
val, _ = v.AsBool()
case KindInt:
val, _ = v.AsInt()
case KindInt8:
val, _ = v.AsInt8()
case KindInt16:
val, _ = v.AsInt16()
case KindInt32:
val, _ = v.AsInt32()
case KindInt64:
val, _ = v.AsInt64()
case KindDuration:
val, _ = v.AsDuration()
case KindUint:
val, _ = v.AsUint()
case KindUint8:
val, _ = v.AsUint8()
case KindUint16:
val, _ = v.AsUint16()
case KindUint32:
val, _ = v.AsUint32()
case KindUint64:
val, _ = v.AsUint64()
case KindUintptr:
val, _ = v.AsUintptr()
case KindHashAlg:
val, _ = v.AsHashalg()
case KindFloat32:
val, _ = v.AsFloat32()
case KindFloat64:
val, _ = v.AsFloat64()
case KindComplex64:
val, _ = v.AsComplex64()
case KindComplex128:
val, _ = v.AsComplex128()
case KindString:
val, _ = v.AsString()
case KindBytes:
val, _ = v.AsBytes()
case KindStack:
val, _ = v.AsStack()
case KindUUID:
val, _ = v.AsUUID()
case KindDate:
val, _ = v.AsDate()
case KindReflect:
val, _ = v.AsReflect()
case KindPackable:
val, _ = v.AsPackable()
case KindStringer:
val, _ = v.AsStringer()
case KindError:
val, _ = v.AsError()
case KindObject:
val, _ = v.AsObject()
}
return val
}
// Error indica si el CValue contiene un error
// ojo no confundir con un CValue que almacena
// un error, este error esta asociado con
// el state del mismo.
func (v CValue) Error() error {
if v.HasError() {
return errs.Code(v.strVal)
}
return nil
}
func (v CValue) AsBool() (bool, bool) {
if v.ValueKind() != KindBool {
return false, false
}
if v.HasZero() {
return false, true
}
if v.IsDefer() {
return v.anyVal.(func() bool)(), true
}
return v.intVal != 0, true
}
func (v CValue) AsInt() (int, bool) { return asCValueFromInt[int](v, KindInt) }
func (v CValue) AsInt8() (int8, bool) { return asCValueFromInt[int8](v, KindInt8) }
func (v CValue) AsInt16() (int16, bool) { return asCValueFromInt[int16](v, KindInt16) }
func (v CValue) AsInt32() (int32, bool) { return asCValueFromInt[int32](v, KindInt32) }
func (v CValue) AsInt64() (int64, bool) { return asCValueFromInt[int64](v, KindInt64) }
func (v CValue) AsDuration() (Duration, bool) { return asCValueFromIntVer[Duration](v, KindDuration) }
func (v CValue) AsUint() (uint, bool) { return asCValueFromInt[uint](v, KindUint) }
func (v CValue) AsUint8() (uint8, bool) { return asCValueFromInt[uint8](v, KindUint8) }
func (v CValue) AsUint16() (uint16, bool) { return asCValueFromInt[uint16](v, KindUint16) }
func (v CValue) AsUint32() (uint32, bool) { return asCValueFromInt[uint32](v, KindUint32) }
func (v CValue) AsUint64() (uint64, bool) { return asCValueFromIntVer[uint64](v, KindUint64) }
func (v CValue) AsUintptr() (uintptr, bool) { return asCValueFromIntVer[uintptr](v, KindUintptr) }
func (v CValue) AsHashalg() (HashAlg, bool) { return asCValueFromIntVer[HashAlg](v, KindHashAlg) }
func (v CValue) AsFloat32() (float32, bool) {
if v.ValueKind() != KindFloat32 {
return 0, false
}
if v.HasZero() {
return 0, true
}
if v.IsDefer() {
return (v.anyVal.(func() float32))(), true
}
return math.Float32frombits(uint32(v.intVal)), true
}
func (v CValue) AsFloat64() (float64, bool) {
if v.ValueKind() != KindFloat64 {
return 0, false
}
if v.HasZero() {
return 0, true
}
if v.IsDefer() {
return (v.anyVal.(func() float64))(), true
}
return math.Float64frombits(uint64(v.intVal)), true
}
func (v CValue) AsComplex64() (complex64, bool) { return asCValueFromAny[complex64](v, KindComplex64) }
func (v CValue) AsComplex128() (complex128, bool) {
return asCValueFromAny[complex128](v, KindComplex128)
}
func (v CValue) AsString() (string, bool) {
if v.ValueKind() != KindString {
return "", false
}
if v.HasZero() {
return "", true
}
if v.IsDefer() {
return v.anyVal.(func() string)(), true
}
return v.strVal, true
}
func (v CValue) AsBytes() (Bytes, bool) {
if v.ValueKind() != KindBytes {
return nil, false
}
if v.HasNil() {
return nil, true
}
if v.HasZero() {
return Bytes{}, true
}
if v.IsDefer() {
return v.anyVal.(func() Bytes)(), true
}
// Revertimos de string a []byte sin copia
return unsafe.Slice(unsafe.StringData(v.strVal), len(v.strVal)), true
}
func (v CValue) AsStack() (Stack, bool) {
if v.ValueKind() != KindStack {
return nil, false
}
if v.HasNil() {
return nil, true
}
if v.HasZero() {
return Stack{}, true
}
if v.IsDefer() {
return v.anyVal.(func() Stack)(), true
}
return v.anyVal.(Stack), true
}
func (v CValue) AsUUID() (UUID, bool) {
if v.ValueKind() != KindUUID {
return uuidZero, false
}
if v.HasZero() {
return uuidZero, true
}
var rs UUID
copy(rs[:], v.strVal)
return rs, true
}
func (v CValue) AsDate() (Date, bool) {
if v.ValueKind() != KindDate {
return Date{}, false
}
if v.HasZero() {
return Date{}, true
}
if v.IsDefer() {
return v.anyVal.(func() Date)(), true
}
return time.Unix(0, v.intVal).UTC(), true
}
func (v CValue) AsReflect() (Reflect, bool) { return asCValueFromAny[Reflect](v, KindReflect) }
func (v CValue) AsObject() (any, bool) {
return asCValueFromAny[any](v, KindObject)
}
func (v CValue) AsPackable() (Packable, bool) {
if v.ValueKind() != KindPackable {
return nil, false
}
if v.HasNil() {
return nil, true
}
if v.IsDefer() {
return (v.anyVal.(func() Packable))(), true
}
return v.anyVal.(Packable), true
}
func (v CValue) AsStringer() (Stringer, bool) {
if v.ValueKind() != KindStringer {
return nil, false
}
if v.HasNil() {
return nil, true
}
if v.IsDefer() {
return (v.anyVal.(func() Stringer))(), true
}
return v.anyVal.(Stringer), true
}
func (v CValue) AsError() (error, bool) {
if v.ValueKind() != KindError {
return nil, false
}
if v.HasNil() {
return nil, true
}
if v.HasZero() {
return error(nil), true
}
if v.IsDefer() {
return (v.anyVal.(func() error))(), true
}
return v.anyVal.(error), true
}
func asCValueFromInt[T uints | ints](v CValue, k Kind) (T, bool) {
if v.ValueKind() != k {
return T(0), false
}
if v.HasZero() {
return T(0), true
}
if v.IsDefer() {
return v.anyVal.(func() T)(), true
}
return T(v.intVal), true
}
func asCValueFromIntVer[T uints | ints](v CValue, k Kind) (T, bool) {
if v.ValueKind() != k {
return T(0), false
}
if v.HasZero() {
return T(0), true
}
if v.IsDefer() {
return v.anyVal.(func() T)(), true
}
return T(v.intVal), true
}
func asCValueFromAny[T any](v CValue, k Kind) (T, bool) {
if v.ValueKind() != k {
return *new(T), false
}
if v.HasZero() || v.HasInvalid() || v.HasNil() {
return *new(T), true
}
if v.IsDefer() {
return v.anyVal.(func() T)(), true
}
return v.anyVal.(T), true
}
func makeCValueCObject(val any) CValue {
if val == nil {
return CValue{Spec: makeSpecScalar(KindObject), State: StateNil | StateError, strVal: string(ErrInvalidCValueForType), anyVal: val}
}
return CValue{Spec: makeSpecScalar(KindObject), anyVal: val}
}
func makeCValueInvalid(_ any) CValue {
return CValue{Spec: makeSpecScalar(KindAny), State: StateInvalid}
}
func makeCValueWithInvalidError(value any, kind Kind, state State, er string) CValue {
return CValue{
Spec: makeSpecScalar(KindAny),
State: StateInvalid | StateError | state,
intVal: int64(kind),
anyVal: value,
strVal: er,
}
}
func makeCInts[T ints](val T, kind Kind) CValue {
if val == 0 {
return CValue{Spec: makeSpecScalar(kind), State: StateZero}
}
return CValue{Spec: makeSpecScalar(kind), intVal: int64(val)}
}
func makeCUints[T uints](val T, kind Kind) CValue {
if val == 0 {
return CValue{Spec: makeSpecScalar(kind), State: StateZero}
}
return CValue{Spec: makeSpecScalar(kind), intVal: int64(val)}
}
func makeCComplex[T cmplx](val T, kind Kind) CValue {
if val == 0 {
return CValue{Spec: makeSpecScalar(kind), State: StateZero}
}
return CValue{Spec: makeSpecScalar(kind), anyVal: val}
}
func makeCList[T lists](val T, kind Kind) CValue {
if val == nil {
return CValue{Spec: makeSpecList(kind), State: StateNil}
}
ln := len(val)
if ln == 0 {
return CValue{Spec: makeSpecList(kind), State: StateZero}
}
return CValue{Spec: makeSpecList(kind), intVal: int64(ln), anyVal: val}
}

Powered by TurnKey Linux.