From cbcc27f1a35caa95ee11e9cb9d9ae751304c9dcc Mon Sep 17 00:00:00 2001 From: "Juan V. Navarro" Date: Mon, 20 Jan 2025 21:06:55 +0100 Subject: [PATCH] first commit --- .idea/.gitignore | 8 + .idea/Active-GO.iml | 9 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + core/errs/active.go | 192 ++++++++++++++++ core/errs/causer.go | 67 ++++++ core/errs/causers.go | 78 +++++++ core/errs/coder.go | 31 +++ core/errs/err_code.go | 71 ++++++ core/errs/err_multi.go | 82 +++++++ core/errs/err_panic.go | 80 +++++++ core/errs/err_param.go | 69 ++++++ core/errs/err_with.go | 77 +++++++ core/errs/err_with_cause.go | 59 +++++ core/errs/err_with_info.go | 82 +++++++ core/errs/err_with_message.go | 62 ++++++ core/errs/err_with_stack.go | 73 ++++++ core/errs/error_handler.go | 46 ++++ core/errs/error_list.go | 122 ++++++++++ core/errs/stack/frame.go | 155 +++++++++++++ core/errs/stack/stack.go | 162 ++++++++++++++ core/errs/stack/stacker.go | 40 ++++ core/errs/try_catch.go | 69 ++++++ core/errs/unwrapper.go | 43 ++++ core/errs/unwrapper_list.go | 43 ++++ core/go.mod | 5 + core/pods/maks/g_maks/active.go | 46 ++++ core/pods/maks/g_maks/g_mak2.go | 284 ++++++++++++++++++++++++ core/pods/scps/active.go | 74 ++++++ core/pods/scps/scope.go | 248 +++++++++++++++++++++ core/pods/scps/scope_entry.go | 91 ++++++++ core/pods/sets/g_sets/g_safe_set.go | 144 ++++++++++++ core/pods/sets/g_sets/g_set.go | 131 +++++++++++ core/pods/sets/g_sets/g_seter.go | 90 ++++++++ core/pods/sets/types.go | 115 ++++++++++ core/rets/active.go | 78 +++++++ core/rets/err_result.go | 46 ++++ core/rets/g_rets/g_error_result.go | 66 ++++++ core/rets/g_rets/g_resultor.go | 49 ++++ core/rets/g_rets/g_validator.go | 43 ++++ core/rets/g_rets/g_value_result.go | 58 +++++ core/rets/result.go | 36 +++ core/rets/result_types.go | 214 ++++++++++++++++++ core/rets/result_types_int.go | 164 ++++++++++++++ core/rets/result_types_ints.go | 175 +++++++++++++++ core/rets/result_types_slices.go | 210 ++++++++++++++++++ core/rets/result_types_uint.go | 181 +++++++++++++++ core/rets/result_types_uints.go | 181 +++++++++++++++ core/rets/valid_types.go | 216 ++++++++++++++++++ core/rets/value_result.go | 44 ++++ core/vals/blds/builder.go | 65 ++++++ core/vals/blds/fields_builder.go | 39 ++++ core/vals/blds/list_builder.go | 39 ++++ core/vals/blds/map_builder.go | 39 ++++ core/vals/blds/object_builder.go | 39 ++++ core/vals/flds/active.go | 73 ++++++ core/vals/flds/field.go | 74 ++++++ core/vals/flds/kind.go | 98 ++++++++ core/vals/g_vals/g_key_value_getter.go | 68 ++++++ core/vals/g_vals/g_key_value_setter.go | 74 ++++++ core/vals/g_vals/g_name_value_getter.go | 64 ++++++ core/vals/g_vals/g_name_value_setter.go | 74 ++++++ core/vals/g_vals/g_value.go | 47 ++++ core/vals/g_vals/g_value_getter.go | 68 ++++++ core/vals/g_vals/g_value_provider.go | 78 +++++++ core/vals/g_vals/g_value_setter.go | 72 ++++++ core/vals/types.go | 227 +++++++++++++++++++ go.mod | 3 + go.work | 6 + 69 files changed, 5970 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/Active-GO.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 core/errs/active.go create mode 100644 core/errs/causer.go create mode 100644 core/errs/causers.go create mode 100644 core/errs/coder.go create mode 100644 core/errs/err_code.go create mode 100644 core/errs/err_multi.go create mode 100644 core/errs/err_panic.go create mode 100644 core/errs/err_param.go create mode 100644 core/errs/err_with.go create mode 100644 core/errs/err_with_cause.go create mode 100644 core/errs/err_with_info.go create mode 100644 core/errs/err_with_message.go create mode 100644 core/errs/err_with_stack.go create mode 100644 core/errs/error_handler.go create mode 100644 core/errs/error_list.go create mode 100644 core/errs/stack/frame.go create mode 100644 core/errs/stack/stack.go create mode 100644 core/errs/stack/stacker.go create mode 100644 core/errs/try_catch.go create mode 100644 core/errs/unwrapper.go create mode 100644 core/errs/unwrapper_list.go create mode 100644 core/go.mod create mode 100644 core/pods/maks/g_maks/active.go create mode 100644 core/pods/maks/g_maks/g_mak2.go create mode 100644 core/pods/scps/active.go create mode 100644 core/pods/scps/scope.go create mode 100644 core/pods/scps/scope_entry.go create mode 100644 core/pods/sets/g_sets/g_safe_set.go create mode 100644 core/pods/sets/g_sets/g_set.go create mode 100644 core/pods/sets/g_sets/g_seter.go create mode 100644 core/pods/sets/types.go create mode 100644 core/rets/active.go create mode 100644 core/rets/err_result.go create mode 100644 core/rets/g_rets/g_error_result.go create mode 100644 core/rets/g_rets/g_resultor.go create mode 100644 core/rets/g_rets/g_validator.go create mode 100644 core/rets/g_rets/g_value_result.go create mode 100644 core/rets/result.go create mode 100644 core/rets/result_types.go create mode 100644 core/rets/result_types_int.go create mode 100644 core/rets/result_types_ints.go create mode 100644 core/rets/result_types_slices.go create mode 100644 core/rets/result_types_uint.go create mode 100644 core/rets/result_types_uints.go create mode 100644 core/rets/valid_types.go create mode 100644 core/rets/value_result.go create mode 100644 core/vals/blds/builder.go create mode 100644 core/vals/blds/fields_builder.go create mode 100644 core/vals/blds/list_builder.go create mode 100644 core/vals/blds/map_builder.go create mode 100644 core/vals/blds/object_builder.go create mode 100644 core/vals/flds/active.go create mode 100644 core/vals/flds/field.go create mode 100644 core/vals/flds/kind.go create mode 100644 core/vals/g_vals/g_key_value_getter.go create mode 100644 core/vals/g_vals/g_key_value_setter.go create mode 100644 core/vals/g_vals/g_name_value_getter.go create mode 100644 core/vals/g_vals/g_name_value_setter.go create mode 100644 core/vals/g_vals/g_value.go create mode 100644 core/vals/g_vals/g_value_getter.go create mode 100644 core/vals/g_vals/g_value_provider.go create mode 100644 core/vals/g_vals/g_value_setter.go create mode 100644 core/vals/types.go create mode 100644 go.mod create mode 100644 go.work diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/Active-GO.iml b/.idea/Active-GO.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/Active-GO.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..aac4dca --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/core/errs/active.go b/core/errs/active.go new file mode 100644 index 0000000..24147ac --- /dev/null +++ b/core/errs/active.go @@ -0,0 +1,192 @@ +package errs + +import ( + "core/errs/stack" + "fmt" + "regexp" +) + +const ( + // errCodePattern is the regular expression that defines a valid error code format. + // The error code can optionally have a module, which is separated by "::". + // The valid characters are alphanumeric characters and the symbols ":-_". + errCodePattern string = "^[a-zA-Z0-9._-]+(::[a-zA-Z0-9._-]+)?$" +) + +const ( + // ModuleSeparator is the separator used between the module and value parts of the error code. + ModuleSeparator string = "::" +) + +// Module configuration +const moduleName = "core.errs" + ModuleSeparator + +// Error messages for internal use +const ( + errNilWrapMsg string = "error trying to wrap % into a nil error" + errNilCauseMsg string = "error trying to wrap % into a nil cause" +) + +// Standard error codes for common error scenarios +const ( + CodePanicError string = "panic" + CodeMultiError string = "multiple-errors" + CodeParamError string = "Param" + CodeParamNilError string = "Param-nil" + CodeParamOutOfRangeError string = "Param-out-of-range" +) + +// G provides a global access point for common errors and information +// This struct combines documentation links and pre-initialized error instances +var ( + G = struct { + InfoHelp, + InfoLink string + + ErrParam, + ErrParamNil, + ErrParamOutOfRange, + ErrInvalidError, + ErrInvalidNilError, + ErrUnknownPanicError, + ErrInvalidErrCode ErrCode + }{ + InfoLink: "https://git.activething.com/go/active", + InfoHelp: "https://doc.activething.com/go/active", + + ErrParam: ErrCode(CodeParamError), + ErrParamNil: ErrCode(CodeParamNilError), + ErrParamOutOfRange: ErrCode(CodeParamOutOfRangeError), + ErrUnknownPanicError: ErrCode(moduleName + "unknown-panic-error"), + ErrInvalidNilError: ErrCode(moduleName + "invalid-nil-error"), + ErrInvalidError: ErrCode(moduleName + "invalid-error"), + ErrInvalidErrCode: ErrCode(moduleName + "invalid-err-code"), + } + + // g contains private package-level variables + g = struct { + panicErrNil *ErrPanic + + codeValidator *regexp.Regexp + }{ + + panicErrNil: NewErrPanic(G.ErrInvalidNilError), + + codeValidator: regexp.MustCompile(errCodePattern), + } +) + +// ToError converts any value to an error type +// Returns nil if the input is nil +// Converts []error to ErrMulti +// Uses fmt.Errorf for other types +func ToError(err any) error { + if err == nil { + return nil + } + switch e := err.(type) { + case error: + return e + case []error: + if len(e) == 0 { + return nil + } + return NewErrMulti(e...) + default: + return fmt.Errorf("%v", err) + } +} + +// PanicRecoveredError creates an error from a recovered panic value +// Returns nil if the recovered value is nil +func PanicRecoveredError(rec any) error { + if rec == nil { + return nil + } + return *NewErrPanic(ToError(rec)) +} + +// Unwrap provides standard error unwrapping functionality +// Implements the unwrap interface for error chains +func Unwrap(err error) error { + if err == nil { + return nil + } + if cs, is := err.(Unwrapper); is { + return cs.Unwrap() + } + return nil +} + +// UnwrapCause retrieves the root cause of an error chain +// Traverses the error chain looking for Causer implementation +func UnwrapCause(err error) error { + e := err + for e != nil { + cs, is := e.(Causer) + if is { + return cs.Cause() + } + e = Unwrap(e) + } + return nil +} + +// UnwrapCauses retrieves all causes in an error chain +// Returns a slice of errors representing the cause chain +func UnwrapCauses(err error) []error { + if err == nil { + return nil + } + if al, is := err.(Causers); is { + return al.Causes() + } + var l ErrorList + e := err + for e != nil { + l = append(l, e) + e = Unwrap(e) + } + return l +} + +// UnwrapList retrieves all errors in an error chain as an ErrorList +// Handles both UnwrapperList implementations and standard error chains +func UnwrapList(err error) ErrorList { + if err == nil { + return nil + } + if al, is := err.(UnwrapperList); is { + return al.Unwrap() + } + var l ErrorList + e := err + for e != nil { + l = append(l, e) + e = Unwrap(e) + } + return l +} + +// UnwrapTrace retrieves the stack trace from an error +func UnwrapTrace(err error) stack.Stack { + return stack.UnwrapStack(err, false) +} + +// WrapError combines two errors into a single error, establishing a cause relationship. +// If either error is nil, the non-nil error is returned. +// Otherwise, a new error is returned that has the first error as the cause. +func WrapError(err, cause error) error { + if err == nil { + return cause + } + if cause == nil { + return err + } + return *NewErrWithCause(err, cause) +} + +// ValidateCode check if un err code is valid +func ValidateCode(code string) bool { + return g.codeValidator.MatchString(code) +} diff --git a/core/errs/causer.go b/core/errs/causer.go new file mode 100644 index 0000000..e7b85ae --- /dev/null +++ b/core/errs/causer.go @@ -0,0 +1,67 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +// Causer is an interface for types that can provide an underlying cause of an error. +// It is commonly used in error wrapping and error chain scenarios to access the +// root cause of an error condition. +type ( + // Causer defines the interface for error types that can reveal their underlying cause. + // This interface is useful for implementing error wrapping patterns and + // for building error chains that preserve cause information. + Causer interface { + // Cause returns the underlying error that caused this error, if any. + // If there is no underlying error, it may return nil. + // + // Returns: + // - error: The underlying error that caused this error, or nil if none exists + Cause() error + } + + // CauseFnc is a function type that implements the Causer interface. + // It allows for dynamic generation of error causes and can be used + // to create error causes lazily or based on runtime conditions. + // + // The function is called when ErrWithCause() is invoked on the CauseFnc. + CauseFnc func() error +) + +// Cause implements the Causer interface for CauseFnc. +// It executes the function and returns its error result. +// +// Returns: +// - error: The result of executing the CauseFnc +// +// Example: +// +// cause := CauseFnc(func() error { +// return errors.New("root cause") +// }) +// err := cause.ErrWithCause() // returns "root cause" error +func (f CauseFnc) Cause() error { + return f() +} diff --git a/core/errs/causers.go b/core/errs/causers.go new file mode 100644 index 0000000..bde83c7 --- /dev/null +++ b/core/errs/causers.go @@ -0,0 +1,78 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +type ( + // Causers is an interface for types that can provide multiple underlying causes + // of an error. This is useful in scenarios where an error condition might have + // resulted from multiple underlying issues or failures. + // + // This interface is particularly useful for: + // - Aggregated error reporting + // - Parallel operation failures + // - Multiple validation errors + // - Complex error scenarios with multiple root causes + Causers interface { + // Causes returns a slice of errors that contributed to this error condition. + // The order of errors in the slice may be significant depending on the + // implementation. + // + // Returns: + // - []error: A slice of underlying errors that caused this error condition. + // May return an empty slice if there are no causes. + Causes() []error + } + + // CausesFnc is a function type that implements the Causers interface. + // It allows for dynamic generation of multiple error causes and can be used + // to create error causes lazily or based on runtime conditions. + // + // Common use cases include: + // - Lazy evaluation of error causes + // - Dynamic error aggregation + // - Conditional error collection + CausesFnc func() []error +) + +// Causes implements the Causers interface for CausesFnc. +// It executes the function and returns its slice of errors. +// +// Returns: +// - []error: The slice of errors returned by executing the CausesFnc +// +// Example: +// +// causes := CausesFnc(func() []error { +// return []error{ +// errors.New("first cause"), +// errors.New("second cause"), +// } +// }) +// errs := causes.Causes() // returns slice with both errors +func (f CausesFnc) Causes() []error { + return f() +} diff --git a/core/errs/coder.go b/core/errs/coder.go new file mode 100644 index 0000000..0fc51df --- /dev/null +++ b/core/errs/coder.go @@ -0,0 +1,31 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +type Coder interface { + Code() string +} diff --git a/core/errs/err_code.go b/core/errs/err_code.go new file mode 100644 index 0000000..76892a6 --- /dev/null +++ b/core/errs/err_code.go @@ -0,0 +1,71 @@ +package errs + +import ( + "fmt" + "strings" +) + +// ErrCode is a custom error type that represents an error code. +// It may include a module and a value, separated by "::". +type ErrCode string + +// MakeErrCode creates a new ErrCode from the given string. +// It validates that the string is non-empty and matches the predefined error code pattern. +// If the string is invalid, it panics. +func MakeErrCode(err string) ErrCode { + + if len(err) == 0 || !g.codeValidator.MatchString(err) { + // If the error code is invalid, panic with a predefined error Msg. + fmt.Println(err) + panic(G.ErrInvalidErrCode) + } + + // Return the created ErrCode. + return ErrCode(err) +} + +// Error implements the error interface for ErrCode. +// It returns the error code as a string. +func (e ErrCode) Error() string { + return string(e) +} + +// String returns the error code as a string representation. +func (e ErrCode) String() string { + return string(e) +} + +// Module extracts and returns the module part of the error code. +// If there is no module, it returns an empty string. +func (e ErrCode) Module() string { + // Check if the error code has a module, using the module separator "::". + if b, has := strings.CutSuffix(string(e), ModuleSeparator); has { + return b + } + // If no module is found, return an empty string. + return "" +} + +// Value extracts and returns the value part of the error code. +// If there is no value, it returns the entire error code. +func (e ErrCode) Value() string { + // Check if the error code has a value, using the module separator "::". + if b, has := strings.CutPrefix(string(e), ModuleSeparator); has { + return b + } + // If no module part is found, return the entire error code (it is considered as the value). + return string(e) +} + +// IsValid checks whether the error code is valid according to the defined pattern. +// It returns true if the error code matches the regular expression, otherwise false. +func (e ErrCode) IsValid() bool { + // Use the code validator to check if the error code matches the pattern. + return g.codeValidator.MatchString(string(e)) +} + +// With returns a WrapErrWith instance containing this ErrCode +// Enables using the wrapper's additional error handling functionality +func (e ErrCode) With() ErrWith { + return MakeErrWith(e) +} diff --git a/core/errs/err_multi.go b/core/errs/err_multi.go new file mode 100644 index 0000000..b8afe4f --- /dev/null +++ b/core/errs/err_multi.go @@ -0,0 +1,82 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +// ErrMulti is a struct that represents multiple errors as a single error +// It embeds ErrorList to provide all error list functionality +type ( + ErrMulti struct { + ErrorList + } +) + +// NewErrMulti creates a new ErrMulti instance from variable number of errors +// It cleans the error list by removing nil errors before creating the instance +// Returns a pointer to the new ErrMulti +func NewErrMulti(err ...error) *ErrMulti { + return &ErrMulti{ErrorList: ErrorList(err).Clean()} +} + +// NewErrMultiIf creates a new error from a slice of errors +// Returns nil if the input slice is empty +// Returns an ErrMulti pointer containing the errors otherwise +func NewErrMultiIf(errors []error) error { + if len(errors) == 0 { + return nil + } + return &ErrMulti{errors} +} + +// Code returns the error code for multi-error situations +// Returns the constant CodeMultiError +func (e ErrMulti) Code() string { + return CodeMultiError +} + +// Error implements the error interface +// Returns the CodeMultiError as the error Msg +func (e ErrMulti) Error() string { + return CodeMultiError +} + +// Unwrap implements the unwrap interface for multiple errors +// Returns the underlying slice of errors +func (e ErrMulti) Unwrap() []error { + return e.ErrorList +} + +// Causes returns all underlying errors +// This is an alias for Unwrap() providing a more semantic name +func (e ErrMulti) Causes() []error { + return e.ErrorList +} + +// With returns a WrapErrWith instance containing this ErrMulti +// Enables using the wrapper's additional error handling functionality +func (e ErrMulti) With() ErrWith { + return MakeErrWith(e) +} diff --git a/core/errs/err_panic.go b/core/errs/err_panic.go new file mode 100644 index 0000000..580efee --- /dev/null +++ b/core/errs/err_panic.go @@ -0,0 +1,80 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +// ErrPanic is a custom error type that represents a specific error case involving a panic. +// +// Fields: +// - cause: The underlying error that triggered the panic, if any. +type ErrPanic struct { + cause error +} + +// NewErrPanic creates a new instance of ErrPanic. +// +// Parameters: +// - cause: The underlying error that caused the panic. +// +// Returns: +// - A pointer to the newly created ErrPanic instance. +func NewErrPanic(cause error) *ErrPanic { + return &ErrPanic{cause: cause} +} + +// Error returns a string representation of the ErrPanic error. +// This is the implementation of the error interface. +// +// Returns: +// - A constant string (CodePanicError) representing the error message. +func (e ErrPanic) Error() string { + return CodePanicError // Note: Ensure CodePanicError is defined elsewhere. +} + +// Unwrap provides access to the underlying error (if any) in the ErrPanic instance. +// +// Returns: +// - The underlying error that caused the panic, or nil if there is no cause. +// Note: Currently, this implementation always returns nil. +func (e ErrPanic) Unwrap() error { + return nil // Consider returning e.cause for compatibility with errors.Unwrap. +} + +// Cause retrieves the underlying cause of the ErrPanic error. +// +// Returns: +// - The underlying error that caused the panic. +func (e ErrPanic) Cause() error { + return e.cause +} + +// With wraps the ErrPanic instance into an ErrWith structure for additional context. +// +// Returns: +// - An ErrWith instance containing the ErrPanic error. +func (e ErrPanic) With() ErrWith { + return MakeErrWith(e) +} diff --git a/core/errs/err_param.go b/core/errs/err_param.go new file mode 100644 index 0000000..62688bc --- /dev/null +++ b/core/errs/err_param.go @@ -0,0 +1,69 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +import "fmt" + +type ( + ErrParam struct { + code string + Param string + Msg string + } +) + +func NewErrParam(param string, msgf string, params ...any) *ErrParam { + return &ErrParam{ + code: CodeParamError, + Param: param, + Msg: fmt.Sprintf(msgf, params...)} +} + +func NewErrNilParam(param string, msgf string, params ...any) *ErrParam { + return &ErrParam{ + code: CodeParamNilError, + Param: param, + Msg: fmt.Sprintf(msgf, params...)} +} + +func (e ErrParam) Code() string { + return e.code +} + +func (e ErrParam) Error() string { + return e.code +} + +func (e ErrParam) Message() string { + return e.Msg +} + +// With returns a WrapErrWith instance containing this ErrParam +// Enables using the wrapper's additional error handling functionality +func (e ErrParam) With() ErrWith { + return MakeErrWith(e) +} diff --git a/core/errs/err_with.go b/core/errs/err_with.go new file mode 100644 index 0000000..bcb5826 --- /dev/null +++ b/core/errs/err_with.go @@ -0,0 +1,77 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +// ErrWith is a struct that wraps an error and provides additional error handling functionality +// It embeds the error interface to maintain error compatibility +type ErrWith struct { + error +} + +func NewErrWith(err error) *ErrWith { + if err == nil { + panic(g.panicErrNil) + } + return &ErrWith{err} +} + +func MakeErrWith(err error) ErrWith { + return *NewErrWith(err) +} + +// Unwrap returns the wrapped error +// This method complies with Go's error unwrapping convention +func (w ErrWith) Unwrap() error { + return w.error +} + +// Cause creates a new error with cause by wrapping the current error +// and associating it with a cause error +// Returns a pointer to ErrWithCause containing both errors +func (w ErrWith) Cause(cause error) *ErrWithCause { + return NewErrWithCause(w.error, cause) +} + +// Message creates a new error with an additional Msg +// Returns a pointer to ErrWithMessage containing the original error and new Msg +func (w ErrWith) Message(msg string) *ErrWithMessage { + return NewErrWithMessage(w.error, msg) +} + +// MessageF creates a new error with a formatted Msg using printf-style formatting +// params are used to format the Msg string +// Returns a pointer to ErrWithMessage containing the original error and formatted Msg +func (w ErrWith) MessageF(format string, params ...any) *ErrWithMessage { + return NewErrWithMessageF(w.error, format, params...) +} + +// Stack creates a new error with stack trace information +// offset parameter determines how many stack frames to skip +// Returns a pointer to ErrWithStack containing the original error and stack trace +func (w ErrWith) Stack(offset int) *ErrWithStack { + return NewErrWithStack(w.error, offset) +} diff --git a/core/errs/err_with_cause.go b/core/errs/err_with_cause.go new file mode 100644 index 0000000..550daf5 --- /dev/null +++ b/core/errs/err_with_cause.go @@ -0,0 +1,59 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +type ( + ErrWithCause struct { + error + cause error + } +) + +func NewErrWithCause(err error, cause error) *ErrWithCause { + if err == nil { + panic(G.ErrInvalidNilError.With().MessageF(errNilWrapMsg, "ErrWithCause")) + } + if cause == nil { + panic(G.ErrInvalidNilError.With().MessageF(errNilCauseMsg, "ErrWithCause")) + } + return &ErrWithCause{ + error: err, + cause: cause, + } +} + +func (e ErrWithCause) Unwrap() error { + return e.error +} + +func (e ErrWithCause) Cause() error { + return e.cause +} + +func (e ErrWithCause) With() ErrWith { + return MakeErrWith(e) +} diff --git a/core/errs/err_with_info.go b/core/errs/err_with_info.go new file mode 100644 index 0000000..bccbf7f --- /dev/null +++ b/core/errs/err_with_info.go @@ -0,0 +1,82 @@ +// ------------------------------------------------------------------------ +// Project active2 +// Active Thing (activething.com) git.activething.com/go +// +// File name errMeta.go +// Created by DEV +// Modified 24/03/2024 +// +// Copyright 2024 activething.com +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ------------------------------------------------------------------------ + +package errs + +import ( + "time" +) + +// ErrWithInfo is an error type that enriches errors with additional context and metadata +// It wraps an existing error and adds fields for documentation, timing, and descriptions +type ( + ErrWithInfo struct { + error // Embedded error interface + Msg string // Custom error Msg + Info string // Additional information about the error + Desc string // Detailed description of the error + Help string // Help text for resolving the error + Link string // URL to documentation or additional resources + Date time.Time // Timestamp when the error was created + } + + // ErrWithInfoFnc is a function type used for the functional options pattern + // It allows flexible configuration of ErrWithInfo instances + ErrWithInfoFnc func(*ErrWithInfo) +) + +// NewErrWithInfo creates a new ErrWithInfo instance with the given error and options +// Panics if the input error is nil +// The options parameter allows customizing the error information using functional options +func NewErrWithInfo(err error, options ...ErrWithInfoFnc) *ErrWithInfo { + if err == nil { + panic(G.ErrInvalidNilError.With().MessageF(errNilWrapMsg, "ErrWithInfo")) + } + ei := &ErrWithInfo{ + error: err, + Link: G.InfoLink, + Date: time.Now(), + } + for _, o := range options { + o(ei) + } + return ei +} + +// Message returns the custom Msg associated with the error +// Implements the Message() string interface +func (e ErrWithInfo) Message() string { + return e.Msg +} + +// Unwrap returns the underlying error +// Implements the Unwrapper interface +func (e ErrWithInfo) Unwrap() error { + return e.error +} + +// With returns a WrapErrWith instance containing this error +// Enables using the wrapper's additional error handling functionality +func (e ErrWithInfo) With() ErrWith { + return MakeErrWith(e) +} diff --git a/core/errs/err_with_message.go b/core/errs/err_with_message.go new file mode 100644 index 0000000..c9e2048 --- /dev/null +++ b/core/errs/err_with_message.go @@ -0,0 +1,62 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +import "fmt" + +type ( + ErrWithMessage struct { + error + message string + } +) + +func NewErrWithMessage(err error, msg string) *ErrWithMessage { + if err == nil { + panic(G.ErrInvalidNilError.With().MessageF(errNilWrapMsg, "ErrWithMessage")) + } + return &ErrWithMessage{ + error: err, + message: msg, + } +} + +func NewErrWithMessageF(err error, msgf string, params ...any) *ErrWithMessage { + return NewErrWithMessage(err, fmt.Sprintf(msgf, params...)) +} + +func (e ErrWithMessage) Message() string { + return e.message +} + +func (e ErrWithMessage) Unwrap() error { + return e.error +} + +func (e ErrWithMessage) With() ErrWith { + return MakeErrWith(e) +} diff --git a/core/errs/err_with_stack.go b/core/errs/err_with_stack.go new file mode 100644 index 0000000..b44a4de --- /dev/null +++ b/core/errs/err_with_stack.go @@ -0,0 +1,73 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +import "core/errs/stack" + +// ErrWithStack represents an error that includes a stack trace. +// It combines an error with a stack trace, enabling stack trace preservation during error propagation. +type ErrWithStack struct { + error // Embedding the base error + Stack stack.Stack // The stack trace associated with the error +} + +// NewErrWithStack creates a new ErrWithStack instance, which includes both an error and a stack trace. +// If the provided error is nil, it will panic with an appropriate error message. +// It checks if the error implements the stack.Stacker interface to determine if it already has a stack trace. +// If the error does not have a stack trace, it creates a new one using the provided offset. +func NewErrWithStack(err error, offset int) *ErrWithStack { + if err == nil { + panic(G.ErrInvalidNilError.With().MessageF(errNilWrapMsg, "ErrWithStack")) // Panic if the error is nil + } + var st stack.Stack + // Check if the error already implements the stack.Stacker interface + tc, is := err.(stack.Stacker) + if !is { + // If the error does not implement stack.Stacker, create a new stack trace using the offset + st = stack.MakeStack(offset) + } else { + // If the error has a stack trace, use it + st = tc.Stack() + } + // Return a new ErrWithStack containing both the error and the stack trace + return &ErrWithStack{ + error: err, // Set the embedded error + Stack: st, // Set the stack trace + } +} + +// Unwrap returns the underlying error that is wrapped by ErrWithStack. +// This allows the error to be unwrapped using Go's error handling mechanisms (e.g., errors.Is or errors.As). +func (e ErrWithStack) Unwrap() error { + return e.error // Return the embedded error +} + +// With provides an ErrWith instance to allow further extension of the error. +// This method enables the chaining of additional information or metadata on top of the error. +func (e ErrWithStack) With() ErrWith { + return MakeErrWith(e) // Create and return an ErrWith instance +} diff --git a/core/errs/error_handler.go b/core/errs/error_handler.go new file mode 100644 index 0000000..e889431 --- /dev/null +++ b/core/errs/error_handler.go @@ -0,0 +1,46 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +// ErrorHandler defines an interface for objects that can handle errors +// This interface is used to abstract error handling logic +type ( + ErrorHandler interface { + // HandleError processes an error according to the implementation's strategy + HandleError(err error) + } + + // HandleErrorFnc is a function type that implements ErrorHandler interface + // It allows regular functions to be used as error handlers through type conversion + HandleErrorFnc func(err error) +) + +// HandleError implements the ErrorHandler interface for HandleErrorFnc +// This allows using the function directly as an ErrorHandler +func (f HandleErrorFnc) HandleError(err error) { + f(err) +} diff --git a/core/errs/error_list.go b/core/errs/error_list.go new file mode 100644 index 0000000..9619adb --- /dev/null +++ b/core/errs/error_list.go @@ -0,0 +1,122 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +// ErrorList represents a slice of errors that provides convenient methods for error handling +type ErrorList []error + +// Any returns true if the list contains at least one non-nil error +func (l ErrorList) Any() bool { + for _, e := range l { + if e != nil { + return true + } + } + return false +} + +// Len returns the total length of the error list, including nil errors +func (l ErrorList) Len() int { + return len(l) +} + +// Count returns the number of non-nil errors in the list +func (l ErrorList) Count() int { + c := 0 + for _, e := range l { + if e != nil { + c++ + } + } + return c +} + +// First returns the first non-nil error in the list +// If no non-nil error exists, returns nil +func (l ErrorList) First() error { + for _, e := range l { + if e != nil { + return e + } + } + return nil +} + +// Last returns the last non-nil error in the list +// If no non-nil error exists, returns nil +func (l ErrorList) Last() error { + for i := len(l) - 1; i >= 0; i-- { + if l[i] != nil { + return l[i] + } + } + return nil +} + +// Append adds an error to the end of the list, regardless of whether it's nil +// Returns the modified error list +func (l ErrorList) Append(err error) ErrorList { + return append(l, err) +} + +// AppendNotNil adds an error to the list only if it's not nil +// Returns the modified error list or the original list if the error was nil +func (l ErrorList) AppendNotNil(err error) ErrorList { + if err != nil { + return append(l, err) + } + return l +} + +// Reset removes all errors from the list by resetting its length to zero +// Returns the emptied error list +func (l ErrorList) Reset() ErrorList { + return l[:0] +} + +// Clean removes any nil errors from the list +// Returns a new error list containing only non-nil errors +func (l ErrorList) Clean() ErrorList { + return l.filter(func(e error) bool { + return e != nil + }) +} + +// filter creates a new error list containing only errors that satisfy the filter function +// Returns nil if no errors match the filter criteria +func (l ErrorList) filter(filter func(error) bool) ErrorList { + rs := make([]error, 0, len(l)) + for _, e := range l { + if filter(e) { + rs = append(rs, e) + } + } + if len(rs) == 0 { + return nil + } + return rs +} diff --git a/core/errs/stack/frame.go b/core/errs/stack/frame.go new file mode 100644 index 0000000..d852173 --- /dev/null +++ b/core/errs/stack/frame.go @@ -0,0 +1,155 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package stack + +import ( + "bufio" + "bytes" + "os" + "runtime" + "strings" +) + +// Frame represents a single stack frame in a program's execution stack. +// It contains detailed information about the source code location, +// function, and package where the frame was created. +type Frame struct { + // LineNumber is the line number in the source file where this frame was created + LineNumber int + + // File is the full path to the source file containing this frame + File string + + // FuncName is the name of the function where this frame was created, + // with any receiver types removed + FuncName string + + // Package is the full package path where this frame was created + Package string + + // Counter is the program counter address for this frame + Counter uintptr + + // files is an internal cache of file contents + files map[string][]byte +} + +// NewFrame creates a new Frame instance from a program counter address. +// It extracts the source code location, function name, and package information +// from the runtime stack. +// +// Parameters: +// - counter: Program counter address to create the frame from +// +// Returns: +// - *Frame: A new Frame instance, or nil if counter is 0 +// +// Example: +// +// pc := runtime.Caller(0) +// frame := NewFrame(pc) +func NewFrame(counter uintptr) *Frame { + if counter == 0 { + return nil + } + sf := &Frame{ + Counter: counter, + } + fn := runtime.FuncForPC(counter) + sf.Package, sf.FuncName = packageAndName(fn) + sf.File, sf.LineNumber = fn.FileLine(counter - 1) + return sf +} + +// SourceLine retrieves the actual source code line for this stack frame. +// It reads the source file and returns the line of code that created this frame. +// +// Returns: +// - string: The source code line, or "unknown" if the line cannot be found +// - error: Any error encountered while reading the source file +// +// Example: +// +// frame := NewFrame(runtime.Caller(0)) +// line, err := frame.SourceLine() +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println("Source line:", line) +func (f Frame) SourceLine() (string, error) { + if f.LineNumber <= 0 { + return stackUnknownInfo, nil + } + file, err := os.Open(f.File) + if err != nil { + return "", err + } + scanner := bufio.NewScanner(file) + currentLine := 1 + for scanner.Scan() { + if currentLine == f.LineNumber { + return string(bytes.Trim(scanner.Bytes(), " \t")), nil + } + currentLine++ + } + _ = file.Close() + if err := scanner.Err(); err != nil { + return "", err + } + return stackUnknownInfo, nil +} + +// packageAndName splits a fully qualified function name into its package and function parts. +// It handles nested packages and removes any receiver type information from the function name. +// +// Parameters: +// - fn: Runtime function information +// +// Returns: +// - string: Package path +// - string: Function name with receiver types removed +// +// Example: +// +// fn := runtime.FuncForPC(pc) +// pkg, name := packageAndName(fn) +// // For "github.com/user/pkg.(*Type).Method" +// // pkg = "github.com/user/pkg" +// // name = "Type.Method" +func packageAndName(fn *runtime.Func) (string, string) { + nm := fn.Name() + pg := "" + if ls := strings.LastIndex(nm, "/"); ls >= 0 { + pg = nm[:ls] + "/" + nm = nm[ls+1:] + } + if pd := strings.Index(nm, "."); pd >= 0 { + pg += nm[:pd] + nm = nm[pd+1:] + } + return pg, strings.Replace(nm, "·", ".", -1) +} diff --git a/core/errs/stack/stack.go b/core/errs/stack/stack.go new file mode 100644 index 0000000..2b78262 --- /dev/null +++ b/core/errs/stack/stack.go @@ -0,0 +1,162 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package stack + +import ( + "errors" + "runtime" +) + +// Constantes utilizadas para la configuración y manejo de stack traces +const ( + // stackSkipFrames define cuántos frames iniciales se omiten al capturar el stack + // Se omiten 2 frames para excluir las llamadas internas del sistema + stackSkipFrames = 2 + + // stackMaxFrames define el número máximo de frames que se capturarán + // Limita la profundidad del stack trace a 32 frames + stackMaxFrames = 32 + + // stackUnknownInfo es el valor por defecto cuando no se puede obtener + // información sobre un frame del stack + stackUnknownInfo = "???" +) + +// Stack represents a slice of program counters (uintptr) that point to function call locations +type Stack []uintptr + +// MakeStack creates a new Stack with program counters from the current goroutine's stack trace +// Parameters: +// - offset: Number of stack frames to skip from the call point. If negative, it's set to 0 +// +// Returns: +// - Stack: A slice containing program counter values for each stack frame +// +// The function captures up to stackMaxFrames frames, starting from offset+stackSkipFrames +func MakeStack(offset int) Stack { + // Create a slice to store program counters with maximum capacity + ls := make([]uintptr, stackMaxFrames) + + // Ensure offset is not negative + if offset < 0 { + offset = 0 + } + + // Capture the stack trace using runtime.Callers + // cn will contain the actual number of frames captured + cn := runtime.Callers(offset+stackSkipFrames, ls) + + // Return only the slice containing valid program counters + return ls[:cn] +} + +// Frames converts the Stack's program counters into Frame objects +// that contain detailed information about each stack frame +// +// Returns: +// - []Frame: Slice of Frame objects containing function call information +func (s Stack) Frames() []Frame { + // Create a slice to store Frame objects + f := make([]Frame, len(s)) + + // Convert each program counter to a Frame object + for i, p := range s { + f[i] = *NewFrame(p) + } + + return f +} + +// UnwrapStack extrae el Stack de un error, navegando por la cadena de errores +// si es necesario. Puede buscar también en las causas del error si se especifica. +// +// Parámetros: +// - err: El error del cual extraer el stack trace +// - cause: Si es true, también busca en las causas del error +// +// Returns: +// - Stack: El stack trace encontrado o nil si no se encuentra ninguno +func UnwrapStack(err error, cause bool) Stack { + // Si el error es nil, retorna nil + if err == nil { + return nil + } + + // Primero busca en la cadena principal de errores + e := err + for e != nil { + // Intenta convertir el error a Stacker + if st, is := e.(Stacker); is { + return st.Stack() + } + e = errors.Unwrap(e) + } + + // Si cause es true, busca en las causas del error + if cause { + e = err + for e != nil { + // Busca en errores que implementan Cause() error + if cs, is := e.(interface{ Cause() error }); is { + UnwrapStack(cs.Cause(), cause) + } + + // Busca en errores que implementan Causes() []error + if cs, is := e.(interface{ Causes() []error }); is { + if tc := unwrapStackMulti(cs.Causes()); tc != nil { + return tc + } + } + + // Busca en errores que implementan Unwrap() []error + if cs, is := e.(interface{ Unwrap() []error }); is { + if tc := unwrapStackMulti(cs.Unwrap()); tc != nil { + return tc + } + } + + e = errors.Unwrap(e) + } + } + return nil +} + +// unwrapStackMulti busca un Stack en un slice de errores +// +// Parámetros: +// - ers: Slice de errores a examinar +// +// Returns: +// - Stack: El primer stack trace encontrado o nil si no se encuentra ninguno +func unwrapStackMulti(ers []error) Stack { + for _, e := range ers { + if tc := UnwrapStack(e, true); tc != nil { + return tc + } + } + return nil +} diff --git a/core/errs/stack/stacker.go b/core/errs/stack/stacker.go new file mode 100644 index 0000000..a8d460b --- /dev/null +++ b/core/errs/stack/stacker.go @@ -0,0 +1,40 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package stack + +// Stacker defines an interface for types that can provide their stack trace +// Types implementing this interface must be able to return their current call stack +type Stacker interface { + // Stack returns the current stack trace + // + // Returns: + // - Stack: A slice of program counters representing the call stack + // + // This method should capture and return the relevant stack frames + // at the point of invocation + Stack() Stack +} diff --git a/core/errs/try_catch.go b/core/errs/try_catch.go new file mode 100644 index 0000000..33209c0 --- /dev/null +++ b/core/errs/try_catch.go @@ -0,0 +1,69 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +// TryCatch struct defines the structure for handling Try-Catch-Finally operations. +// - Try: A function that will be executed in the "try" block. +// - Catch: A function that will be executed if a panic occurs in the "try" block (catching the panic). +// - Finally: A function that will be executed at the end of the execution, regardless of success or failure (finally block). +type TryCatch struct { + Try func(params ...any) // Function to execute in the "try" block + Catch func(err error) // Function to handle errors if a panic occurs (catch block) + Finally func(params ...any) // Function to execute in the "finally" block (always runs) +} + +// Do executes the Try, Catch, and Finally blocks based on the provided parameters. +// It will: +// 1. Execute the Try block. +// 2. Catch any panics that occur during the Try block execution and pass them to the Catch block. +// 3. Always execute the Finally block at the end, whether an error occurred or not. +func (c TryCatch) Do(params ...any) { + // If a Finally block is provided, defer its execution to ensure it runs last. + if c.Finally != nil { + defer c.Finally(params...) + } + + ok := false // A flag to ensure the Catch block is only executed once. + + // If a Catch block is provided, defer a function that recovers from panics. + // The recovery will invoke the Catch block if a panic occurs. + if c.Catch != nil { + defer func(done *bool) { + if !(*done) { // Ensure the Catch block is only executed once. + if rc := recover(); rc != nil { // If a panic occurred, handle it. + c.Catch(*NewErrPanic(ToError(rc))) // Pass the recovered value (converted to error) to the Catch block. + } + } + }(&ok) + } + + // Execute the Try block. + c.Try(params...) + + // Mark the flag as true to indicate the Try block has completed without triggering a panic. + ok = true +} diff --git a/core/errs/unwrapper.go b/core/errs/unwrapper.go new file mode 100644 index 0000000..15e18bc --- /dev/null +++ b/core/errs/unwrapper.go @@ -0,0 +1,43 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +// Unwrapper is an interface that defines the method Unwrap. +// The Unwrap method should return the underlying error that is wrapped by the type implementing this interface. +type Unwrapper interface { + Unwrap() error +} + +// UnwrapperFnc is a function type that implements the Unwrapper interface. +// It is a function that returns an error when called. +type UnwrapperFnc func() error + +// Unwrap implements the Unwrapper interface for the UnwrapperFnc type. +// It invokes the function f and returns the error that the function returns. +func (f UnwrapperFnc) Unwrap() error { + return f() // Call the function and return its error result. +} diff --git a/core/errs/unwrapper_list.go b/core/errs/unwrapper_list.go new file mode 100644 index 0000000..65ca87e --- /dev/null +++ b/core/errs/unwrapper_list.go @@ -0,0 +1,43 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package errs + +// UnwrapperList is an interface that defines the method Unwrap. +// The Unwrap method should return a slice of errors (i.e., []error) that are wrapped by the type implementing this interface. +type UnwrapperList interface { + Unwrap() []error +} + +// UnwrapperListFnc is a function type that implements the UnwrapperList interface. +// It is a function that returns a slice of errors when called. +type UnwrapperListFnc func() []error + +// Unwrap implements the UnwrapperList interface for the UnwrapperListFnc type. +// It invokes the function f and returns the slice of errors that the function returns. +func (f UnwrapperListFnc) Unwrap() []error { + return f() // Call the function and return its slice of error results. +} diff --git a/core/go.mod b/core/go.mod new file mode 100644 index 0000000..7a62470 --- /dev/null +++ b/core/go.mod @@ -0,0 +1,5 @@ +module core + +go 1.22 + + diff --git a/core/pods/maks/g_maks/active.go b/core/pods/maks/g_maks/active.go new file mode 100644 index 0000000..d980b99 --- /dev/null +++ b/core/pods/maks/g_maks/active.go @@ -0,0 +1,46 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_maks + +import "core/errs" + +const ( + moduleName = "core.pods.maks" + errs.ModuleSeparator +) + +var ( + G = struct { + ErrKeyNotFound, + ErrBadKeys, + ErrDuplicatedKey errs.ErrCode + }{ + + ErrBadKeys: errs.MakeErrCode(moduleName + "bad-keys"), + ErrKeyNotFound: errs.MakeErrCode(moduleName + "key-not-found"), + ErrDuplicatedKey: errs.MakeErrCode(moduleName + "duplicated-key"), + } +) diff --git a/core/pods/maks/g_maks/g_mak2.go b/core/pods/maks/g_maks/g_mak2.go new file mode 100644 index 0000000..a4de49f --- /dev/null +++ b/core/pods/maks/g_maks/g_mak2.go @@ -0,0 +1,284 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_maks + +import ( + "sort" +) + +// GMak2 is a generic structure that supports two indices for fast lookups. +// - T represents the type of data stored. +// - I1 and I2 are the types for the two indices (must be comparable). +type ( + GMak2[T any, I1, I2 comparable] struct { + entries []gEntry2k[T, I1, I2] // Data slice storing all elements. + free []int // List of free positions for recycling. + zero T // A zero value of the generic type to reset data. + map1 map[I1]int // Map for the first key to the position in the data slice. + map2 map[I2]int // Map for the second key to the position in the data slice. + } + + // gEntry2k holds the data and associated keys for the entries in GMak2. + gEntry2k[T any, I1, I2 any] struct { + data T // The data associated with this entry. + key1 I1 // The first key used for indexing. + key2 I2 // The second key used for indexing. + isFree bool + } +) + +// NewGMak2 creates a new instance of GMak2 with initialized maps. +func NewGMak2[T any, I1, I2 comparable]() *GMak2[T, I1, I2] { + return &GMak2[T, I1, I2]{ + map1: make(map[I1]int), + map2: make(map[I2]int), + } +} + +// HasKey1 checks if the first key exists in map1. +func (m *GMak2[_, I1, I2]) HasKey1(key I1) bool { + _, exists := m.map1[key] + return exists +} + +// HasKey2 checks if the second key exists in map2. +func (m *GMak2[_, I1, I2]) HasKey2(key I2) bool { + _, exists := m.map2[key] + return exists +} + +// HasKeys checks if both keys exist in the respective maps. +func (m *GMak2[_, I1, I2]) HasKeys(key1 I1, key2 I2) bool { + _, h1 := m.map1[key1] + _, h2 := m.map2[key2] + return h1 && h2 +} + +// Add inserts a new element into the GMak2 structure, associating it with the provided keys. +func (m *GMak2[T, I1, I2]) Add(data T, key1 I1, key2 I2) error { + if m.HasKeys(key1, key2) { + return G.ErrDuplicatedKey // Error if the keys already exist. + } + return m.add(data, key1, key2) +} + +// add adds the data to the structure, either reusing a free position or appending to the entries slice. +func (m *GMak2[T, I1, I2]) add(data T, key1 I1, key2 I2) error { + var pos int + if len(m.free) > 0 { + // Reuse a free position from the free list. + pos = m.free[len(m.free)-1] + m.free = m.free[:len(m.free)-1] // Remove the last free position. + m.entries[pos].data = data + m.entries[pos].key1 = key1 + m.entries[pos].key2 = key2 + m.entries[pos].isFree = false + } else { + // If no free positions, append a new entry to the entries slice. + pos = len(m.entries) + m.entries = append(m.entries, gEntry2k[T, I1, I2]{ + data: data, + key1: key1, + key2: key2, + isFree: false, + }) + } + + // Map the keys to the corresponding position in the entries slice. + m.map1[key1] = pos + m.map2[key2] = pos + return nil +} + +// GetByKey1 retrieves the data associated with the first key. +func (m *GMak2[T, I1, I2]) GetByKey1(key I1) (T, bool) { + pos, exists := m.map1[key] + if !exists { + return m.zero, false + } + return m.entries[pos].data, true +} + +// GetByKey2 retrieves the data associated with the second key. +func (m *GMak2[T, I1, I2]) GetByKey2(key I2) (T, bool) { + pos, exists := m.map2[key] + if !exists { + return m.zero, false + } + return m.entries[pos].data, true +} + +// DelByKey1 removes an element by the first key and frees the position for reuse. +func (m *GMak2[T, I1, I2]) DelByKey1(key I1) error { + pos, has := m.map1[key] + if !has { + return G.ErrKeyNotFound // Error if the key is not found. + } + m.del(pos) // Perform the deletion and free the position. + return nil +} + +// DelByKey2 removes an element by the second key and frees the position for reuse. +func (m *GMak2[T, I1, I2]) DelByKey2(key I2) error { + pos, has := m.map2[key] + if !has { + return G.ErrKeyNotFound // Error if the key is not found. + } + m.del(pos) // Perform the deletion and free the position. + return nil +} + +// del deletes an entry by position and frees up the space for reuse. +func (m *GMak2[T, I1, I2]) del(pos int) { + m.free = append(m.free, pos) // Add the position to the free list. + delete(m.map1, m.entries[pos].key1) // Remove the first key from map1. + delete(m.map2, m.entries[pos].key2) // Remove the second key from map2. + m.entries[pos].data = m.zero // Reset the data to the zero value. + m.entries[pos].isFree = true +} + +// SetByKey1 updates the data associated with the first key. +func (m *GMak2[T, I1, I2]) SetByKey1(key I1, newData T) error { + pos, exists := m.map1[key] + if !exists { + return G.ErrKeyNotFound // Error if the key is not found. + } + m.entries[pos].data = newData + return nil +} + +// SetByKey2 updates the data associated with the second key. +func (m *GMak2[T, I1, I2]) SetByKey2(key I2, newData T) error { + pos, exists := m.map2[key] + if !exists { + return G.ErrKeyNotFound // Error if the key is not found. + } + m.entries[pos].data = newData + return nil +} + +// SetOrAdd inserts a new element or updates the existing element if both keys are already present. +func (m *GMak2[T, I1, I2]) SetOrAdd(data T, key1 I1, key2 I2) error { + // Check if either key1 or key2 already exists in the respective maps + p1, h1 := m.map1[key1] + p2, h2 := m.map2[key2] + + if !h1 && !h2 { + return m.add(data, key1, key2) + } + if p1 != p2 { + return G.ErrBadKeys // Error if keys point to different positions. + } + m.entries[p1].data = data + return nil +} + +// Iterate iterates through all entries and applies the provided function to each entry. +func (m *GMak2[T, I1, I2]) Iterate(fn func(data T, key1 I1, key2 I2) bool) { + for _, entry := range m.entries { + if entry.isFree { + continue + } + if !fn(entry.data, entry.key1, entry.key2) { + break + } + } +} + +// Reset clears all entries, maps, and free positions in the GMak2 structure. +// This function is useful for reinitializing the GMak2 structure without creating a new instance. +func (m *GMak2[_, _, _]) Reset() { + // Iterate through all entries and delete their associated keys from the maps. + for _, d := range m.entries { + delete(m.map1, d.key1) + delete(m.map2, d.key2) + } + + // Reset the free list and the entries slice. + m.free = m.free[:0] // Clear the free positions list. + m.entries = m.entries[:0] // Clear the entries slice. +} + +// compact removes free entries by moving valid entries to the beginning of the slice. +func (m *GMak2[T, I1, I2]) compact() { + writeIndex := 0 // Posición donde escribir la próxima entrada válida. + + for readIndex := 0; readIndex < len(m.entries); readIndex++ { + entry := m.entries[readIndex] + if !entry.isFree { + // Mover entrada válida hacia adelante si es necesario. + if writeIndex != readIndex { + m.entries[writeIndex] = entry + } + writeIndex++ + } + } + + // Reducir el slice al tamaño compactado. + m.entries = m.entries[:writeIndex] + m.free = m.free[:0] // All free positions are cleared. +} + +// Compact removes free entries by moving valid entries to the beginning of the slice. +// It updates the maps to reflect the new positions. +func (m *GMak2[T, I1, I2]) Compact() { + m.compact() + m.rebuildMaps() +} + +// SortByKey1 sorts the entries based on the provided comparison function for key1. +// The `less` function determines the ordering between two keys of type I1. +func (m *GMak2[T, I1, I2]) SortByKey1(less func(key1, key2 I1) bool) { + m.compact() + sort.SliceStable(m.entries, func(i, j int) bool { + return less(m.entries[i].key1, m.entries[j].key1) + }) + m.rebuildMaps() +} + +// SortByKey2 sorts the entries based on the provided comparison function for key2. +// The `less` function determines the ordering between two keys of type I2. +func (m *GMak2[T, I1, I2]) SortByKey2(less func(key1, key2 I2) bool) { + m.compact() + sort.SliceStable(m.entries, func(i, j int) bool { + return less(m.entries[i].key2, m.entries[j].key2) + }) + m.rebuildMaps() +} + +// Helper function to update maps after sorting. +func (m *GMak2[_, I1, I2]) rebuildMaps() { + // Rebuild the maps to reflect the new positions of keys. + m.map1 = make(map[I1]int) + m.map2 = make(map[I2]int) + for i, entry := range m.entries { + if !entry.isFree { + m.map1[entry.key1] = i + m.map2[entry.key2] = i + } + } +} diff --git a/core/pods/scps/active.go b/core/pods/scps/active.go new file mode 100644 index 0000000..f3d40a3 --- /dev/null +++ b/core/pods/scps/active.go @@ -0,0 +1,74 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package scps + +import ( + "core/errs" + "core/rets" +) + +// moduleName defines the unique identifier for this module in the error system. +// It uses the standardized module separator from the errs package. +const moduleName = "core.scps" + errs.ModuleSeparator + +// G exports public error codes for the module. +// This struct provides centralized access to all error codes that can be +// used by other packages and external code. +// +// Error codes include: +// - ErrKeyNotFound: When a requested key doesn't exist in the scope +// - ErrInvalidKey: When a key is nil or otherwise invalid +// - ErrInvalidValue: When attempting to store an invalid value +// - ErrReadOnlyScope: When attempting to modify a read-only scope +var ( + G = struct { + ErrKeyNotFound, + ErrInvalidKey, + ErrInvalidValue, + ErrReadOnlyScope errs.ErrCode + }{ + ErrKeyNotFound: errs.MakeErrCode(moduleName + "key-not-found"), + ErrInvalidKey: errs.MakeErrCode(moduleName + "invalid-key"), + ErrInvalidValue: errs.MakeErrCode(moduleName + "invalid-value"), + ErrReadOnlyScope: errs.MakeErrCode(moduleName + "read-only-store"), + } + + // g provides package-private result instances for common error conditions. + // These are pre-created for efficiency and consistency in error handling + // throughout the package. + g = struct { + ResultKeyNotFound, + ResultInvalidKey, + ResultInvalidValue, + ResultReadOnly rets.Result + }{ + ResultKeyNotFound: rets.NewErrorResult(G.ErrKeyNotFound), + ResultInvalidKey: rets.NewErrorResult(G.ErrInvalidKey), + ResultInvalidValue: rets.NewErrorResult(G.ErrInvalidValue), + ResultReadOnly: rets.NewErrorResult(G.ErrReadOnlyScope), + } +) diff --git a/core/pods/scps/scope.go b/core/pods/scps/scope.go new file mode 100644 index 0000000..d661547 --- /dev/null +++ b/core/pods/scps/scope.go @@ -0,0 +1,248 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package scps + +// Package scope provides a hierarchical key-value store implementation with thread-safety +// and parent-child relationship support. It allows for creating isolated scopes that can +// inherit values from parent scopes while maintaining their own independent modifications. + +import ( + "core/rets" + "core/vals" + "sync" +) + +type ( + + // Scope represents a hierarchical key-value store with thread-safe operations. + // Each Scope can have a parent from which it inherits values, and can be marked + // as read-only to prevent modifications. + Scope struct { + // parent represents the parent scope from which this scope inherits values + parent vals.KeyValueGetter + // entries stores the key-value pairs in a thread-safe map + entries sync.Map + // isReadOnly indicates whether the scope can be modified + isReadOnly bool + } + + // ScopeFnc defines a function type for scope configuration operations. + // It's used in the functional options pattern for configuring new scopes. + ScopeFnc func(*Scope) error +) + +// NewScope creates a new Scope instance with an optional parent and configuration options. +// It initializes an empty scope and applies the provided configuration functions in order. +// +// Parameters: +// - parent: The parent scope from which the new scope will inherit values (can be nil) +// - ops: Optional configuration functions to be applied to the new scope +// +// Returns: +// - *Scope: The newly created scope +// - error: An error if any configuration operation fails +func NewScope(parent vals.KeyValueGetter, ops ...ScopeFnc) (*Scope, error) { + sc := &Scope{ + parent: parent, + entries: sync.Map{}, + } + for _, op := range ops { + if er := op(sc); er != nil { + return nil, er + } + } + return sc, nil +} + +// IsReadOnly returns whether the scope is in read-only mode. +// Read-only scopes cannot be modified through SetValue, DelValue, or Reset operations. +func (s *Scope) IsReadOnly() bool { return s.isReadOnly } + +// NewChild creates a new child Scope inheriting from the current Scope. +// The child Scope can have its own independent key-value pairs and optional configurations. +// +// Parameters: +// - ops: Optional configuration functions to be applied to the child scope +// +// Returns: +// - *Scope: The newly created child scope +// - error: An error if creation or configuration fails +func (s *Scope) NewChild(ops ...ScopeFnc) (*Scope, error) { + sc, er := NewScope(s, ops...) + if er != nil { + return nil, er + } + return sc, nil +} + +// DelValue removes a key-value pair from the current Scope by its key. +// If the Scope is marked as read-only, the operation returns an error. +// +// Parameters: +// - key: The key to remove from the scope +// +// Returns: +// - error: ErrReadOnlyScope if the scope is read-only, nil otherwise +func (s *Scope) DelValue(key any) error { + if s.IsReadOnly() { + // No modifications allowed if the Scope is read-only. + return G.ErrReadOnlyScope + } + s.entries.Delete(key) // Delete the key-value pair. + return nil +} + +// GetValue retrieves a value from the scope by its key. +// If the key is not found in the current scope and a parent exists, +// the request is delegated to the parent scope. +// +// Parameters: +// - key: The key to look up +// +// Returns: +// - rets.Resulter: A result containing the value if found, or an error result if: +// - The key is nil (ResultInvalidKey) +// - The key is not found in this scope or any parent scope (ResultKeyNotFound) +func (s *Scope) GetValue(key any) rets.Result { + if key == nil { + return g.ResultInvalidKey + } + if en, ok := s.entries.Load(key); ok { + return (en.(scopeEntry)).Result() + } + if s.parent != nil { + return s.parent.GetValue(key) + } + return g.ResultKeyNotFound +} + +// SetValue stores a key-value pair in the current scope. +// If the scope is read-only or the key is nil, an error is returned. +// If the key already exists and is associated with a provider, the operation fails. +// +// Parameters: +// - key: The key under which to store the value +// - value: The value to store +// +// Returns: +// - error: An error if: +// - The key is nil (ErrInvalidKey) +// - The scope is read-only (ErrReadOnlyScope) +// - The key exists and is associated with a provider (ErrInvalidValue) +func (s *Scope) SetValue(key, value any) error { + var en scopeEntry + if key == nil { + return G.ErrInvalidKey + } + if s.isReadOnly { + return G.ErrReadOnlyScope + } + if ob, ok := s.entries.Load(key); ok { + en = ob.(scopeEntry) + if !en.isValue { + // si es un provider no podemos cambiarlo una vez + // establecido el valor como un valor simple + // + return G.ErrInvalidValue + } + // + en.value = value + } else { + en = *newScopeEntry(value) + } + s.entries.Store(key, en) + return nil +} + +// Range iterates over all key-value pairs in the current Scope. +// For each pair, it invokes the provided function with the key and value. +// The iteration stops if the function returns false. +// +// Parameters: +// - fnc: A function that receives each key-value pair and returns whether to continue iteration +func (s *Scope) Range(fnc func(key, value any) bool) { + s.entries.Range(func(key, value any) bool { + entry := value.(scopeEntry) + if entry.isValue { + return fnc(key, entry.value) + } + return fnc(key, entry.provider.Value()) + }) +} + +// Reset clears all key-value pairs from the current Scope. +// If the Scope is marked as read-only, the operation returns an error. +// +// Returns: +// - error: ErrReadOnlyScope if the scope is read-only, nil otherwise +func (s *Scope) Reset() error { + if s.isReadOnly { + return G.ErrReadOnlyScope // No modifications allowed if the Scope is read-only. + } + s.entries.Range(func(k, _ any) bool { + s.entries.Delete(k) // Delete each key-value pair. + return true + }) + return nil +} + +// ScopeWithReadOnly returns a ScopeFnc that sets the scope to read-only mode. +// Once applied, the scope will not allow any modifications to its values. +// +// Returns: +// - ScopeFnc: A function that when called will mark the scope as read-only +// +// Example: +// +// scope, _ := NewScope(ScopeWithReadOnly()) +// // scope is now read-only +func ScopeWithReadOnly() ScopeFnc { + return func(s *Scope) error { + s.isReadOnly = true + return nil + } +} + +// ScopeWithValue returns a ScopeFnc that sets an initial key-value pair in the scope. +// This function is used during scope creation to initialize the scope with values. +// +// Parameters: +// - key: The key under which to store the value (can be of any type) +// - value: The value to store (can be of any type) +// +// Returns: +// - ScopeFnc: A function that when called will set the specified key-value pair +// +// Example: +// +// scope, _ := NewScope(ScopeWithValue("key", "value")) +// // scope now contains "key":"value" +func ScopeWithValue(key, value any) ScopeFnc { + return func(s *Scope) error { + return s.SetValue(key, value) + } +} diff --git a/core/pods/scps/scope_entry.go b/core/pods/scps/scope_entry.go new file mode 100644 index 0000000..3c0b4d8 --- /dev/null +++ b/core/pods/scps/scope_entry.go @@ -0,0 +1,91 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package scps + +import ( + "core/rets" + "core/vals" +) + +// scopeEntry represents a value stored in a Scope, which can be either +// a direct value or a value provider. This type handles the dual nature +// of scope values, allowing for both static values and dynamic value generation. +type ( + scopeEntry struct { + // isValue indicates whether the entry contains a direct value (true) + // or a value provider (false) + isValue bool + + // value stores the actual value when isValue is true + // This field is used for direct value storage + value any + + // provider stores a ValueProvider interface when isValue is false + // This field is used for dynamic value generation + provider vals.ValueProvider + } +) + +// newScopeEntry creates a new scopeEntry instance based on the provided value. +// It automatically determines whether the value is a direct value or a value provider. +// +// Parameters: +// - value: The value to store, which can be either a direct value or a ValueProvider +// +// Returns: +// - *scopeEntry: A new scope entry configured according to the value type +// +// The function checks if the provided value implements the ValueProvider interface. +// If it does, the entry is configured to use the provider; otherwise, it stores +// the value directly. +func newScopeEntry(value any) *scopeEntry { + pr, is := vals.CheckValueProvider(value) + if is { + return &scopeEntry{provider: pr} + } + return &scopeEntry{ + value: value, + isValue: true, + } +} + +// Result returns the entry's value wrapped in a Resulter interface. +// For direct values, it returns the stored value directly. +// For providers, it returns the value obtained by calling the provider's Value() method. +// +// Returns: +// - rets.Resulter: A result containing either the direct value or the provider's generated value +// +// The returned Resulter will contain: +// - For direct values: the stored value wrapped in a ValueResult +// - For providers: the result of calling Value() on the provider wrapped in a ValueResult +func (e scopeEntry) Result() rets.Result { + if e.isValue { + return rets.ValueResult{V: e.value} + } + return rets.ValueResult{V: e.provider.Value()} +} diff --git a/core/pods/sets/g_sets/g_safe_set.go b/core/pods/sets/g_sets/g_safe_set.go new file mode 100644 index 0000000..9dd24c9 --- /dev/null +++ b/core/pods/sets/g_sets/g_safe_set.go @@ -0,0 +1,144 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_sets + +import "sync" + +// GSafeSet provides a thread-safe wrapper around GSet, implementing synchronized +// access to all set operations through read-write mutex locks. +// +// Type Parameters: +// - T: Any comparable type that can be used as set elements +// +// The struct ensures thread-safe access to the underlying GSet by: +// - Using RWMutex for optimized read/write operations +// - Providing exclusive locks for modifications +// - Allowing concurrent reads with read locks +type GSafeSet[T comparable] struct { + // mux provides mutual exclusion for thread-safe operations + mux sync.RWMutex + // inner holds the actual set implementation + inner *GSet[T] +} + +// NewGSafeSet creates and initializes a new thread-safe set. +// +// Type Parameters: +// - T: The type of elements the set will contain +// +// Returns: +// - *GSafeSet[T]: A pointer to a new, initialized thread-safe set +// +// Example: +// +// safeSet := NewGSafeSet[string]() +func NewGSafeSet[T comparable]() *GSafeSet[T] { + return &GSafeSet[T]{inner: NewGSet[T]()} +} + +// Has checks if a value exists in the set using a read lock. +// +// Parameters: +// - value: The element to check for existence +// +// Returns: +// - bool: true if the value exists in the set, false otherwise +// +// Example: +// +// set := NewGSafeSet[int]() +// set.Add(1) +// exists := set.Has(1) // true +func (s *GSafeSet[T]) Has(value T) (rs bool) { + s.mux.RLock() + rs = s.inner.Has(value) + s.mux.RUnlock() + return +} + +// Add inserts a new value into the set if it doesn't already exist. +// Uses a write lock to ensure thread-safe modification. +// +// Parameters: +// - value: The element to add to the set +// +// Returns: +// - bool: true if the value was added, false if it already existed +// +// Example: +// +// set := NewGSafeSet[string]() +// added := set.Add("hello") // true +// added = set.Add("hello") // false, already exists +func (s *GSafeSet[T]) Add(value T) (rs bool) { + s.mux.Lock() + rs = s.inner.Add(value) + s.mux.Unlock() + return +} + +// Del removes a value from the set if it exists. +// Uses a write lock to ensure thread-safe modification. +// +// Parameters: +// - value: The element to remove from the set +// +// Returns: +// - bool: true if the value was removed, false if it didn't exist +// +// Example: +// +// set := NewGSafeSet[int]() +// set.Add(42) +// removed := set.Del(42) // true +// removed = set.Del(42) // false, doesn't exist +func (s *GSafeSet[T]) Del(value T) (rs bool) { + s.mux.Lock() + rs = s.inner.Del(value) + s.mux.Unlock() + return +} + +// List returns a slice containing all elements in the set. +// Uses a read lock since it doesn't modify the set. +// The order of elements in the returned slice is not guaranteed. +// +// Returns: +// - []T: A slice containing all elements currently in the set +// +// Example: +// +// set := NewGSafeSet[string]() +// set.Add("a") +// set.Add("b") +// elements := set.List() // []string{"a", "b"} (order not guaranteed) +func (s *GSafeSet[T]) List() (rs []T) { + s.mux.RLock() + rs = s.inner.List() + s.mux.RUnlock() + return +} diff --git a/core/pods/sets/g_sets/g_set.go b/core/pods/sets/g_sets/g_set.go new file mode 100644 index 0000000..d5fb187 --- /dev/null +++ b/core/pods/sets/g_sets/g_set.go @@ -0,0 +1,131 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_sets + +// GSet implements a generic set data structure using a map with empty structs as values. +// This implementation provides memory-efficient storage of unique elements of any comparable type. +// +// Type Parameters: +// - T: Any comparable type that can be used as set elements +// +// The underlying map[T]struct{} representation ensures: +// - O(1) average time complexity for all operations +// - Minimal memory overhead by using empty structs as values +type GSet[T comparable] map[T]struct{} + +// NewGSet creates and initializes a new empty set. +// +// Type Parameters: +// - T: The type of elements the set will contain +// +// Returns: +// - *GSet[T]: A pointer to a new, initialized empty set +// +// Example: +// +// set := NewGSet[string]() +func NewGSet[T comparable]() *GSet[T] { + s := make(GSet[T]) + return &s +} + +// Has checks if a value exists in the set. +// +// Parameters: +// - value: The element to check for existence +// +// Returns: +// - bool: true if the value exists in the set, false otherwise +// +// Example: +// +// set := NewGSet[int]() +// set.Add(1) +// exists := set.Has(1) // true +func (s *GSet[T]) Has(value T) bool { + _, h := (*s)[value] + return h +} + +// Add inserts a new value into the set if it doesn't already exist. +// +// Parameters: +// - value: The element to add to the set +// +// Returns: +// - bool: true if the value was added, false if it already existed +// +// Example: +// +// set := NewGSet[string]() +// added := set.Add("hello") // true +// added = set.Add("hello") // false, already exists +func (s *GSet[T]) Add(value T) bool { + l := len(*s) + (*s)[value] = struct{}{} + return l != len(*s) +} + +// Del removes a value from the set if it exists. +// +// Parameters: +// - value: The element to remove from the set +// +// Returns: +// - bool: true if the value was removed, false if it didn't exist +// +// Example: +// +// set := NewGSet[int]() +// set.Add(42) +// removed := set.Del(42) // true +// removed = set.Del(42) // false, doesn't exist +func (s *GSet[T]) Del(value T) bool { + l := len(*s) + delete(*s, value) + return l != len(*s) +} + +// List returns a slice containing all elements in the set. +// The order of elements in the returned slice is not guaranteed. +// +// Returns: +// - []T: A slice containing all elements currently in the set +// +// Example: +// +// set := NewGSet[string]() +// set.Add("a") +// set.Add("b") +// elements := set.List() // []string{"a", "b"} (order not guaranteed) +func (s *GSet[T]) List() []T { + l := make([]T, len(*s)) + for k := range *s { + l = append(l, k) + } + return l +} diff --git a/core/pods/sets/g_sets/g_seter.go b/core/pods/sets/g_sets/g_seter.go new file mode 100644 index 0000000..9577c14 --- /dev/null +++ b/core/pods/sets/g_sets/g_seter.go @@ -0,0 +1,90 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_sets + +// GSeter represents a generic set interface that works with any comparable type. +// It provides basic set operations like adding, removing, checking membership, +// and listing elements. +// +// Type Parameters: +// - T: Any comparable type that can be used as set elements. +// The comparable constraint ensures that values can be compared for equality. +// +// The interface ensures that implementations provide thread-safe operations +// for managing a collection of unique elements of type T. +type GSeter[T comparable] interface { + // Has checks if the given value exists in the set. + // + // Parameters: + // - value: The element to check for membership + // + // Returns: + // - bool: true if the value exists in the set, false otherwise + Has(value T) bool + + // Add inserts a new value into the set if it doesn't already exist. + // + // Parameters: + // - value: The element to add to the set + // + // Returns: + // - bool: true if the value was added, false if it already existed + Add(value T) bool + + // Del removes a value from the set if it exists. + // + // Parameters: + // - value: The element to remove from the set + // + // Returns: + // - bool: true if the value was removed, false if it didn't exist + Del(value T) bool + + // List returns a slice containing all elements in the set. + // The order of elements in the returned slice is not guaranteed. + // + // Returns: + // - []T: A slice containing all elements currently in the set + List() []T +} + +// Example usage: +// +// type StringSet struct { +// // implementation details +// } +// +// // Verify StringSet implements GSeter[string] +// var _ GSeter[string] = (*StringSet)(nil) +// +// func Example() { +// var set GSeter[string] +// set.Add("hello") // true +// set.Has("hello") // true +// set.Del("hello") // true +// set.List() // []string{} +// } diff --git a/core/pods/sets/types.go b/core/pods/sets/types.go new file mode 100644 index 0000000..fb8dea7 --- /dev/null +++ b/core/pods/sets/types.go @@ -0,0 +1,115 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package sets + +import "core/pods/sets/g_sets" + +// Package provides predefined type aliases for common set types + +// Non-thread-safe set type aliases for primitive types +type ( + // StringSet is a set of string values + StringSet = g_sets.GSet[string] + + // BoolSet is a set of boolean values + BoolSet = g_sets.GSet[bool] + + // Integer set types + + // IntSet is a set of platform-dependent sized integers + IntSet = g_sets.GSet[int] + // Int8Set is a set of 8-bit integers + Int8Set = g_sets.GSet[int8] + // Int16Set is a set of 16-bit integers + Int16Set = g_sets.GSet[int16] + // Int32Set is a set of 32-bit integers + Int32Set = g_sets.GSet[int32] + // Int64Set is a set of 64-bit integers + Int64Set = g_sets.GSet[int64] + + // Unsigned integer set types + + // UintSet is a set of platform-dependent sized unsigned integers + UintSet = g_sets.GSet[uint] + // Uint8Set is a set of 8-bit unsigned integers + Uint8Set = g_sets.GSet[uint8] + // Uint16Set is a set of 16-bit unsigned integers + Uint16Set = g_sets.GSet[uint16] + // Uint32Set is a set of 32-bit unsigned integers + Uint32Set = g_sets.GSet[uint32] + // Uint64Set is a set of 64-bit unsigned integers + Uint64Set = g_sets.GSet[uint64] + + // Floating-point set types + + // Float32Set is a set of 32-bit floating-point numbers + Float32Set = g_sets.GSet[float32] + // Float64Set is a set of 64-bit floating-point numbers + Float64Set = g_sets.GSet[float64] +) + +// Thread-safe set type aliases for primitive types +type ( + // SafeStringSet is a thread-safe set of string values + SafeStringSet = g_sets.GSafeSet[string] + + // SafeBoolSet is a thread-safe set of boolean values + SafeBoolSet = g_sets.GSafeSet[bool] + + // Thread-safe integer set types + + // SafeIntSet is a thread-safe set of platform-dependent sized integers + SafeIntSet = g_sets.GSafeSet[int] + // SafeInt8Set is a thread-safe set of 8-bit integers + SafeInt8Set = g_sets.GSafeSet[int8] + // SafeInt16Set is a thread-safe set of 16-bit integers + SafeInt16Set = g_sets.GSafeSet[int16] + // SafeInt32Set is a thread-safe set of 32-bit integers + SafeInt32Set = g_sets.GSafeSet[int32] + // SafeInt64Set is a thread-safe set of 64-bit integers + SafeInt64Set = g_sets.GSafeSet[int64] + + // Thread-safe unsigned integer set types + + // SafeUintSet is a thread-safe set of platform-dependent sized unsigned integers + SafeUintSet = g_sets.GSafeSet[uint] + // SafeUint8Set is a thread-safe set of 8-bit unsigned integers + SafeUint8Set = g_sets.GSafeSet[uint8] + // SafeUint16Set is a thread-safe set of 16-bit unsigned integers + SafeUint16Set = g_sets.GSafeSet[uint16] + // SafeUint32Set is a thread-safe set of 32-bit unsigned integers + SafeUint32Set = g_sets.GSafeSet[uint32] + // SafeUint64Set is a thread-safe set of 64-bit unsigned integers + SafeUint64Set = g_sets.GSafeSet[uint64] + + // Thread-safe floating-point set types + + // SafeFloat32Set is a thread-safe set of 32-bit floating-point numbers + SafeFloat32Set = g_sets.GSafeSet[float32] + // SafeFloat64Set is a thread-safe set of 64-bit floating-point numbers + SafeFloat64Set = g_sets.GSafeSet[float64] +) diff --git a/core/rets/active.go b/core/rets/active.go new file mode 100644 index 0000000..05135dc --- /dev/null +++ b/core/rets/active.go @@ -0,0 +1,78 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package rets + +var ( + + // G provides a global set of predefined invalid values for various types. + // These values are useful as placeholders or defaults when representing invalid states. + // Each type has its corresponding `Invalid` structure to signify that the value is not valid. + G = struct { + NotValidString InvalidString + NotValidBool InvalidBool + + NotValidInt InvalidInt + NotValidInt8 InvalidInt8 + NotValidInt16 InvalidInt16 + NotValidInt32 InvalidInt32 + NotValidInt64 InvalidInt64 + + NotValidUint InvalidUint + NotValidUint8 InvalidUint8 + NotValidUint16 InvalidUint16 + NotValidUint32 InvalidUint32 + NotValidUint64 InvalidUint64 + + NotValidFloat32 InvalidFloat32 + NotValidFloat64 InvalidFloat64 + + NotValidComplex64 InvalidComplex64 + NotValidComplex128 InvalidComplex128 + }{ + + NotValidString: InvalidString{}, + NotValidBool: InvalidBool{}, + + NotValidInt: InvalidInt{}, + NotValidInt8: InvalidInt8{}, + NotValidInt16: InvalidInt16{}, + NotValidInt32: InvalidInt32{}, + NotValidInt64: InvalidInt64{}, + + NotValidUint: InvalidUint{}, + NotValidUint8: InvalidUint8{}, + NotValidUint16: InvalidUint16{}, + NotValidUint32: InvalidUint32{}, + NotValidUint64: InvalidUint64{}, + + NotValidFloat32: InvalidFloat32{}, + NotValidFloat64: InvalidFloat64{}, + + NotValidComplex64: InvalidComplex64{}, + NotValidComplex128: InvalidComplex128{}, + } +) diff --git a/core/rets/err_result.go b/core/rets/err_result.go new file mode 100644 index 0000000..2a746b4 --- /dev/null +++ b/core/rets/err_result.go @@ -0,0 +1,46 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package rets + +import ( + "core/rets/g_rets" +) + +// ErrorResult is an alias for the GErrorResult type from the g_rets package. +// This alias simplifies usage by referring to GErrorResult with the generic type `any`, +// making it easier to work with error results in the program. +type ErrorResult = g_rets.GErrorResult[any] + +// NewErrorResult creates a new instance of ErrorResult using the g_rets package's NewGErrorResult function. +// It takes an error as input and returns a pointer to an ErrorResult containing that error. +// +// The function uses the `any` type for generic handling, allowing you to create error results +// for any specific type of error, even though the error itself is of the `error` type. +func NewErrorResult(err error) *ErrorResult { + // Create and return an error result using the provided error. + return g_rets.NewGErrorResult[any](err) +} diff --git a/core/rets/g_rets/g_error_result.go b/core/rets/g_rets/g_error_result.go new file mode 100644 index 0000000..64e7ac1 --- /dev/null +++ b/core/rets/g_rets/g_error_result.go @@ -0,0 +1,66 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_rets + +import "core/errs" + +// GErrorResult is a generic struct that represents an error result containing an error of type T. +// This type is used to encapsulate an error and indicates that the result is invalid. +type GErrorResult[T any] struct { + error // The error associated with the result. +} + +// NewGErrorResult creates a new instance of GErrorResult with the given error. +// If the error is nil, it should handle the error appropriately (e.g., you may return a default error). +// It returns a pointer to a GErrorResult containing the provided error. +func NewGErrorResult[T any](err error) *GErrorResult[T] { + if err == nil { + // Valid Error is required, panic if is nil + panic(errs.G.ErrInvalidError) + } + return &GErrorResult[T]{err} +} + +// IsValid returns false because GErrorResult represents an invalid result due to the error. +// This indicates that the result is not valid because it contains an error. +func (_ GErrorResult[T]) IsValid() bool { + return false +} + +// Value returns nothing, as GErrorResult is considered invalid and has no valid value. +// This method can be used to indicate that there's no valid value associated with the error result. +func (_ GErrorResult[T]) Value() (zero T) { + // No valid value to return. This method could be modified to return a default or zero value + // if desired, but as it stands, it signifies that the result has no valid value due to the error. + return +} + +// Err returns the error associated with the result. +// This method allows access to the error wrapped in the GErrorResult. +func (r GErrorResult[T]) Err() error { + return r.error // Return the stored error +} diff --git a/core/rets/g_rets/g_resultor.go b/core/rets/g_rets/g_resultor.go new file mode 100644 index 0000000..fbf8ae5 --- /dev/null +++ b/core/rets/g_rets/g_resultor.go @@ -0,0 +1,49 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_rets + +// GResultor is a generic interface that extends the GValidator interface by +// adding the ability to handle errors alongside validation and value. +// It simplifies the return values of functions by combining the value, +// its validity status, and any potential error in one result. +// +// T represents the type of the value being returned. +// GResultor extends GValidator to include error handling. +// This interface combines validation, value retrieval, and error reporting +// into a single return value, making it useful for functions that may +// return a valid value or an error. +type GResultor[T any] interface { + // GValidator is the embedded interface that provides validation + // and value retrieval functionality. + GValidator[T] + + // Err returns any error associated with the result. + // If there is an error, it will be returned; otherwise, it returns nil. + // This simplifies error handling by encapsulating both the value + // and error in a single result. + Err() error +} diff --git a/core/rets/g_rets/g_validator.go b/core/rets/g_rets/g_validator.go new file mode 100644 index 0000000..335b645 --- /dev/null +++ b/core/rets/g_rets/g_validator.go @@ -0,0 +1,43 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_rets + +// GValidator is a generic interface designed to simplify function return values +// by combining both the value and a validity status into a single result. +// +// T represents the type of the value being returned. +type GValidator[T any] interface { + // IsValid checks if the value is valid. + // Returns true if the value is considered valid, otherwise false. + // This method simplifies the validation logic by returning just one result. + IsValid() bool + + // Value returns the actual value of type T. + // This value is returned only if IsValid is true. + // It simplifies the function return by encapsulating both the value and its validity status. + Value() T +} diff --git a/core/rets/g_rets/g_value_result.go b/core/rets/g_rets/g_value_result.go new file mode 100644 index 0000000..ea55e9d --- /dev/null +++ b/core/rets/g_rets/g_value_result.go @@ -0,0 +1,58 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_rets + +// GValueResult is a generic struct that represents a valid result containing a value of type T. +// This type is used to encapsulate a valid value, indicating that the value is valid +// and that there is no error associated with it. +type GValueResult[T any] struct { + V T // The value of type T that is being wrapped in the result +} + +// NewGValueResult creates a new instance of GValueResult with the given value. +// It returns a pointer to a GValueResult containing the value passed as an argument. +func NewGValueResult[T any](value T) *GValueResult[T] { + return &GValueResult[T]{V: value} // Initialize the struct with the provided value +} + +// IsValid returns true because GValueResult represents a valid result. +// It indicates that the value wrapped in the struct is considered valid. +func (_ GValueResult[T]) IsValid() bool { + return true +} + +// Err returns nil because GValueResult does not contain any errors. +// This method indicates that the result is valid and there is no associated error. +func (_ GValueResult[T]) Err() error { + return nil +} + +// Value returns the value of type T that is stored inside the GValueResult. +// This method allows access to the actual value encapsulated by the result. +func (r GValueResult[T]) Value() T { + return r.V // Return the stored value +} diff --git a/core/rets/result.go b/core/rets/result.go new file mode 100644 index 0000000..20ca410 --- /dev/null +++ b/core/rets/result.go @@ -0,0 +1,36 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package rets + +import "core/rets/g_rets" + +// Result is an alias for the GResultor type from the g_rets package with the generic type `any`. +// This alias is used to simplify working with function results that encapsulate a value +// and an error. By using `Result`, you can handle any type of value along with error information +// in a standardized way. + +type Result = g_rets.GResultor[any] diff --git a/core/rets/result_types.go b/core/rets/result_types.go new file mode 100644 index 0000000..46499c2 --- /dev/null +++ b/core/rets/result_types.go @@ -0,0 +1,214 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package rets + +import "core/rets/g_rets" + +type ( + + // BoolResult represents a valid bool result. + BoolResult bool + + // BoolError represents an invalid bool result with an error. + BoolError struct{ error } + + // StringResult represents a valid string result. + StringResult string + + // StringError represents an invalid string result with an error. + StringError g_rets.GErrorResult[string] + + // Float32Result represents a valid float32 result. + Float32Result float32 + + // Float32Error represents an invalid float32 result with an error. + Float32Error struct{ error } + + // Float64Result represents a valid float64 result. + Float64Result float64 + + // Float64Error represents an invalid float64 result with an error. + Float64Error struct{ error } + + // Complex64Result represents a valid complex64 result. + Complex64Result complex64 + + // Complex64Error represents an invalid complex64 result with an error. + Complex64Error struct{ error } + + // Complex128Result represents a valid complex128 result. + Complex128Result complex128 + + // Complex128Error represents an invalid complex128 result with an error. + Complex128Error struct{ error } +) + +// BoolResult ******************************************* +// + +// IsValid checks if the BoolResult is valid (always true). +func (_ BoolResult) IsValid() bool { return true } + +// Err returns nil as there is no error for BoolResult. +func (_ BoolResult) Err() error { return nil } + +// Value returns the integer value for BoolResult. +func (r BoolResult) Value() bool { return bool(r) } + +// BoolError ******************************************* +func NewBoolError(er error) *BoolError { + return &BoolError{er} +} + +// IsValid checks if the BoolError is valid (always false). +func (_ BoolError) IsValid() bool { return false } + +// Value returns 0 for BoolError, as it is considered invalid. +func (_ BoolError) Value() bool { return false } + +// Err returns the error for BoolError. +func (r BoolError) Err() error { return r.error } + +// StringResult ******************************************* +// + +// IsValid checks if the StringResult is valid (always true). +func (_ StringResult) IsValid() bool { return true } + +// Err returns nil as there is no error for StringResult. +func (_ StringResult) Err() error { return nil } + +// Value returns the integer value for StringResult. +func (r StringResult) Value() string { return string(r) } + +// StringError ******************************************* +func NewStringError(er error) *StringError { return &StringError{er} } + +// IsValid checks if the StringError is valid (always false). +func (_ StringError) IsValid() bool { return false } + +// Value returns 0 for StringError, as it is considered invalid. +func (_ StringError) Value() string { return "" } + +// Err returns the error for StringError. +func (r StringError) Err() error { return r.error } + +// Float32Result ******************************************* +// + +// IsValid checks if the Float32Result is valid (always true). +func (_ Float32Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Float32Result. +func (_ Float32Result) Err() error { return nil } + +// Value returns the integer value for Float32Result. +func (r Float32Result) Value() float32 { return float32(r) } + +// Float32Error ******************************************* +// + +// IsValid checks if the Float32Error is valid (always false). +func (_ Float32Error) IsValid() bool { return false } + +// Value returns 0 for Float32Error, as it is considered invalid. +func (_ Float32Error) Value() float32 { return 0 } + +// Err returns the error for Float32Error. +func (r Float32Error) Err() error { return r.error } + +// Float64Result ******************************************* +// + +// IsValid checks if the Float64Result is valid (always true). +func (_ Float64Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Float64Result. +func (_ Float64Result) Err() error { return nil } + +// Value returns the integer value for Float64Result. +func (r Float64Result) Value() float64 { return float64(r) } + +// Float64Error ******************************************* +// + +// IsValid checks if the Float64Error is valid (always false). +func (_ Float64Error) IsValid() bool { return false } + +// Value returns 0 for Float64Error, as it is considered invalid. +func (_ Float64Error) Value() float64 { return 0 } + +// Err returns the error for Float64Error. +func (r Float64Error) Err() error { return r.error } + +// Complex64Result ******************************************* +// + +// IsValid checks if the Complex64Result is valid (always true). +func (_ Complex64Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Complex64Result. +func (_ Complex64Result) Err() error { return nil } + +// Value returns the integer value for Complex64Result. +func (r Complex64Result) Value() complex64 { return complex64(r) } + +// Complex64Error ******************************************* +// + +// IsValid checks if the Complex64Error is valid (always false). +func (_ Complex64Error) IsValid() bool { return false } + +// Value returns 0 for Complex64Error, as it is considered invalid. +func (_ Complex64Error) Value() complex64 { return 0 } + +// Err returns the error for Complex64Error. +func (r Complex64Error) Err() error { return r.error } + +// Complex128Result ******************************************* +// + +// IsValid checks if the Complex128Result is valid (always true). +func (_ Complex128Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Complex128Result. +func (_ Complex128Result) Err() error { return nil } + +// Value returns the integer value for Complex128Result. +func (r Complex128Result) Value() complex128 { return complex128(r) } + +// Complex128Error ******************************************* +// + +// IsValid checks if the Complex128Error is valid (always false). +func (_ Complex128Error) IsValid() bool { return false } + +// Value returns 0 for Complex128Error, as it is considered invalid. +func (_ Complex128Error) Value() complex128 { return 0 } + +// Err returns the error for Complex128Error. +func (r Complex128Error) Err() error { return r.error } diff --git a/core/rets/result_types_int.go b/core/rets/result_types_int.go new file mode 100644 index 0000000..a448b86 --- /dev/null +++ b/core/rets/result_types_int.go @@ -0,0 +1,164 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package rets + +// Type definitions for integer results and errors of different integer types +type ( + + // IntResult represents a valid integer result. + IntResult int + // IntError represents an invalid integer result with an error. + IntError struct{ error } + + // Int8Result represents a valid int8 result. + Int8Result int8 + // Int8Error represents an invalid int8 result with an error. + Int8Error struct{ error } + + // Int16Result represents a valid int16 result. + Int16Result int16 + // Int16Error represents an invalid int16 result with an error. + Int16Error struct{ error } + + // Int32Result represents a valid int32 result. + Int32Result int32 + // Int32Error represents an invalid int32 result with an error. + Int32Error struct{ error } + + // Int64Result represents a valid int64 result. + Int64Result int64 + // Int64Error represents an invalid int64 result with an error. + Int64Error struct{ error } +) + +// IntResult ******************************************* +// + +// IsValid checks if the IntResult is valid (always true). +func (_ IntResult) IsValid() bool { return true } + +// Err returns nil as there is no error for IntResult. +func (_ IntResult) Err() error { return nil } + +// Value returns the integer value for IntResult. +func (r IntResult) Value() int { return int(r) } + +// IntError ******************************************* +// + +// IsValid checks if the IntError is valid (always false, as it represents an error). +func (_ IntError) IsValid() bool { return false } + +// Value returns 0 for IntError, as it is considered invalid. +func (_ IntError) Value() int { return 0 } + +// Err returns the error for IntError. +func (r IntError) Err() error { return r.error } + +// Int8Result ******************************************* +// + +// IsValid checks if the Int8Result is valid (always true). +func (_ Int8Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Int8Result. +func (_ Int8Result) Err() error { return nil } + +// Value returns the integer value for Int8Result. +func (r Int8Result) Value() int8 { return int8(r) } + +// Int8Error ******************************************* +// + +// IsValid checks if the Int8Error is valid (always false). +func (_ Int8Error) IsValid() bool { return false } + +// Value returns 0 for Int8Error, as it is considered invalid. +func (_ Int8Error) Value() int8 { return 0 } + +// Err returns the error for Int8Error. +func (r Int8Error) Err() error { return r.error } + +// Int16Result ******************************************* +// + +// IsValid checks if the Int16Result is valid (always true). +func (_ Int16Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Int16Result. +func (_ Int16Result) Err() error { return nil } + +// Value returns the integer value for Int16Result. +func (r Int16Result) Value() int16 { return int16(r) } + +// Int32Result ******************************************* +// + +// IsValid checks if the Int32Result is valid (always true). +func (_ Int32Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Int32Result. +func (_ Int32Result) Err() error { return nil } + +// Value returns the integer value for Int32Result. +func (r Int32Result) Value() int32 { return int32(r) } + +// Int32Error ******************************************* +// + +// IsValid checks if the Int32Error is valid (always false). +func (_ Int32Error) IsValid() bool { return false } + +// Value returns 0 for Int32Error, as it is considered invalid. +func (_ Int32Error) Value() int32 { return 0 } + +// Err returns the error for Int32Error. +func (r Int32Error) Err() error { return r.error } + +// Int64Result ******************************************* +// + +// IsValid checks if the Int64Result is valid (always true). +func (_ Int64Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Int64Result. +func (_ Int64Result) Err() error { return nil } + +// Value returns the integer value for Int64Result. +func (r Int64Result) Value() int64 { return int64(r) } + +// Int64Error ******************************************* +// + +// IsValid checks if the Int64Error is valid (always false). +func (_ Int64Error) IsValid() bool { return false } + +// Value returns 0 for Int64Error, as it is considered invalid. +func (_ Int64Error) Value() int64 { return 0 } + +// Err returns the error for Int64Error. +func (r Int64Error) Err() error { return r.error } diff --git a/core/rets/result_types_ints.go b/core/rets/result_types_ints.go new file mode 100644 index 0000000..ca3a90b --- /dev/null +++ b/core/rets/result_types_ints.go @@ -0,0 +1,175 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package rets + +// Type definitions for slices of integer results and errors of different integer types +type ( + // IntsResult represents a valid slice of integer results. + IntsResult []int + // IntsError represents an invalid slice of integer results with an error. + IntsError struct{ error } + + // Ints8Result represents a valid slice of int8 results. + Ints8Result []int8 + // Ints8Error represents an invalid slice of int8 results with an error. + Ints8Error struct{ error } + + // Ints16Result represents a valid slice of int16 results. + Ints16Result []int16 + // Ints16Error represents an invalid slice of int16 results with an error. + Ints16Error struct{ error } + + // Ints32Result represents a valid slice of int32 results. + Ints32Result []int32 + // Ints32Error represents an invalid slice of int32 results with an error. + Ints32Error struct{ error } + + // Ints64Result represents a valid slice of int64 results. + Ints64Result []int64 + // Ints64Error represents an invalid slice of int64 results with an error. + Ints64Error struct{ error } +) + +// IntsResult ******************************************* +// + +// IsValid checks if the IntsResult is valid (always true). +func (_ IntsResult) IsValid() bool { return true } + +// Err returns nil as there is no error for IntsResult. +func (_ IntsResult) Err() error { return nil } + +// Value returns the slice of integers for IntsResult. +func (r IntsResult) Value() []int { return r } + +// IntsError ******************************************* +// + +// IsValid checks if the IntsError is valid (always false, as it represents an error). +func (_ IntsError) IsValid() bool { return false } + +// Value returns nil for IntsError, as it is considered invalid. +func (_ IntsError) Value() []int { return nil } + +// Err returns the error for IntsError. +func (r IntsError) Err() error { return r.error } + +// Ints8Result ******************************************* +// + +// IsValid checks if the Ints8Result is valid (always true). +func (_ Ints8Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Ints8Result. +func (_ Ints8Result) Err() error { return nil } + +// Value returns the slice of int8 values for Ints8Result. +func (r Ints8Result) Value() []int8 { return r } + +// Ints8Error ******************************************* +// + +// IsValid checks if the Ints8Error is valid (always false). +func (_ Ints8Error) IsValid() bool { return false } + +// Value returns nil for Ints8Error, as it is considered invalid. +func (_ Ints8Error) Value() []int8 { return nil } + +// Err returns the error for Ints8Error. +func (r Ints8Error) Err() error { return r.error } + +// Ints16Result ******************************************* +// + +// IsValid checks if the Ints16Result is valid (always true). +func (_ Ints16Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Ints16Result. +func (_ Ints16Result) Err() error { return nil } + +// Value returns the slice of int16 values for Ints16Result. +func (r Ints16Result) Value() []int16 { return r } + +// Ints16Error ******************************************* +// + +// IsValid checks if the Ints16Error is valid (always false). +func (_ Ints16Error) IsValid() bool { return false } + +// Value returns nil for Ints16Error, as it is considered invalid. +func (_ Ints16Error) Value() []int16 { return nil } + +// Err returns the error for Ints16Error. +func (r Ints16Error) Err() error { return r.error } + +// Ints32Result ******************************************* +// + +// IsValid checks if the Ints32Result is valid (always true). +func (_ Ints32Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Ints32Result. +func (_ Ints32Result) Err() error { return nil } + +// Value returns the slice of int32 values for Ints32Result. +func (r Ints32Result) Value() []int32 { return r } + +// Ints32Error ******************************************* +// + +// IsValid checks if the Ints32Error is valid (always false). +func (_ Ints32Error) IsValid() bool { return false } + +// Value returns nil for Ints32Error, as it is considered invalid. +func (_ Ints32Error) Value() []int32 { return nil } + +// Err returns the error for Ints32Error. +func (r Ints32Error) Err() error { return r.error } + +// Ints64Result ******************************************* +// + +// IsValid checks if the Ints64Result is valid (always true). +func (_ Ints64Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Ints64Result. +func (_ Ints64Result) Err() error { return nil } + +// Value returns the slice of int64 values for Ints64Result. +func (r Ints64Result) Value() []int64 { return r } + +// Ints64Error ******************************************* +// + +// IsValid checks if the Ints64Error is valid (always false). +func (_ Ints64Error) IsValid() bool { return false } + +// Value returns nil for Ints64Error, as it is considered invalid. +func (_ Ints64Error) Value() []int64 { return nil } + +// Err returns the error for Ints64Error. +func (r Ints64Error) Err() error { return r.error } diff --git a/core/rets/result_types_slices.go b/core/rets/result_types_slices.go new file mode 100644 index 0000000..587e930 --- /dev/null +++ b/core/rets/result_types_slices.go @@ -0,0 +1,210 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package rets + +type ( + + // BoolsResult represents a valid bool result. + BoolsResult []bool + + // BoolsError represents an invalid bool result with an error. + BoolsError struct{ error } + + // StringsResult represents a valid string result. + StringsResult []string + + // StringsError represents an invalid string result with an error. + StringsError struct{ error } + + // Floats32Result represents a valid float32 result. + Floats32Result []float32 + + // Floats32Error represents an invalid float32 result with an error. + Floats32Error struct{ error } + + // Floats64Result represents a valid float64 result. + Floats64Result []float64 + + // Floats64Error represents an invalid float64 result with an error. + Floats64Error struct{ error } + + // Complexs64Result represents a valid complex64 result. + Complexs64Result []complex64 + + // Complexs64Error represents an invalid complex64 result with an error. + Complexs64Error struct{ error } + + // Complexs128Result represents a valid complex128 result. + Complexs128Result []complex128 + + // Complexs128Error represents an invalid complex128 result with an error. + Complexs128Error struct{ error } +) + +// BoolResult ******************************************* +// + +// IsValid checks if the BoolResult is valid (always true). +func (_ BoolsResult) IsValid() bool { return true } + +// Err returns nil as there is no error for BoolResult. +func (_ BoolsResult) Err() error { return nil } + +// Value returns the integer value for BoolResult. +func (r BoolsResult) Value() []bool { return r } + +// BoolError ******************************************* +// + +// IsValid checks if the BoolError is valid (always false). +func (_ BoolsError) IsValid() bool { return false } + +// Value returns 0 for BoolError, as it is considered invalid. +func (_ BoolsError) Value() []bool { return nil } + +// Err returns the error for BoolError. +func (r BoolsError) Err() error { return r.error } + +// StringResult ******************************************* +// + +// IsValid checks if the StringResult is valid (always true). +func (_ StringsResult) IsValid() bool { return true } + +// Err returns nil as there is no error for StringResult. +func (_ StringsResult) Err() error { return nil } + +// Value returns the integer value for StringResult. +func (r StringsResult) Value() []string { return r } + +// StringError ******************************************* +// + +// IsValid checks if the StringError is valid (always false). +func (_ StringsError) IsValid() bool { return false } + +// Value returns 0 for StringError, as it is considered invalid. +func (_ StringsError) Value() []string { return nil } + +// Err returns the error for StringError. +func (r StringsError) Err() error { return r.error } + +// Float32Result ******************************************* +// + +// IsValid checks if the Float32Result is valid (always true). +func (_ Floats32Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Float32Result. +func (_ Floats32Result) Err() error { return nil } + +// Value returns the integer value for Float32Result. +func (r Floats32Result) Value() []float32 { return r } + +// Float32Error ******************************************* +// + +// IsValid checks if the Float32Error is valid (always false). +func (_ Floats32Error) IsValid() bool { return false } + +// Value returns 0 for Float32Error, as it is considered invalid. +func (_ Floats32Error) Value() []float32 { return nil } + +// Err returns the error for Float32Error. +func (r Floats32Error) Err() error { return r.error } + +// Float64Result ******************************************* +// + +// IsValid checks if the Float64Result is valid (always true). +func (_ Floats64Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Float64Result. +func (_ Floats64Result) Err() error { return nil } + +// Value returns the integer value for Float64Result. +func (r Floats64Result) Value() []float64 { return r } + +// Float64Error ******************************************* +// + +// IsValid checks if the Float64Error is valid (always false). +func (_ Floats64Error) IsValid() bool { return false } + +// Value returns 0 for Float64Error, as it is considered invalid. +func (_ Floats64Error) Value() []float64 { return nil } + +// Err returns the error for Float64Error. +func (r Floats64Error) Err() error { return r.error } + +// Complex64Result ******************************************* +// + +// IsValid checks if the Complex64Result is valid (always true). +func (_ Complexs64Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Complex64Result. +func (_ Complexs64Result) Err() error { return nil } + +// Value returns the integer value for Complex64Result. +func (r Complexs64Result) Value() []complex64 { return r } + +// Complex64Error ******************************************* +// + +// IsValid checks if the Complex64Error is valid (always false). +func (_ Complexs64Error) IsValid() bool { return false } + +// Value returns 0 for Complex64Error, as it is considered invalid. +func (_ Complexs64Error) Value() []complex64 { return nil } + +// Err returns the error for Complex64Error. +func (r Complexs64Error) Err() error { return r.error } + +// Complex128Result ******************************************* +// + +// IsValid checks if the Complex128Result is valid (always true). +func (_ Complexs128Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Complex128Result. +func (_ Complexs128Result) Err() error { return nil } + +// Value returns the integer value for Complex128Result. +func (r Complexs128Result) Value() []complex128 { return r } + +// Complex128Error ******************************************* +// + +// IsValid checks if the Complex128Error is valid (always false). +func (_ Complexs128Error) IsValid() bool { return false } + +// Value returns 0 for Complex128Error, as it is considered invalid. +func (_ Complexs128Error) Value() []complex128 { return nil } + +// Err returns the error for Complex128Error. +func (r Complexs128Error) Err() error { return r.error } diff --git a/core/rets/result_types_uint.go b/core/rets/result_types_uint.go new file mode 100644 index 0000000..3a837af --- /dev/null +++ b/core/rets/result_types_uint.go @@ -0,0 +1,181 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package rets + +// Type definitions for unsigned results and errors of different unsigned types +type ( + + // UintResult represents a valid unsigned result. + UintResult uint + + // UintError represents an invalid unsigned result with an error. + UintError struct{ error } + + // Uint8Result represents a valid uint8 result. + Uint8Result uint8 + + // Uint8Error represents an invalid uint8 result with an error. + Uint8Error struct{ error } + + // Uint16Result represents a valid uint16 result. + Uint16Result uint16 + + // Uint16Error represents an invalid uint16 result with an error. + Uint16Error struct{ error } + + // Uint32Result represents a valid uint32 result. + Uint32Result uint32 + + // Uint32Error represents an invalid uint32 result with an error. + Uint32Error struct{ error } + + // Uint64Result represents a valid uint64 result. + Uint64Result uint64 + + // Uint64Error represents an invalid uint64 result with an error. + Uint64Error struct{ error } +) + +// UintResult ******************************************* +// + +// IsValid checks if the UintResult is valid (always true). +func (_ UintResult) IsValid() bool { return true } + +// Err returns nil as there is no error for UintResult. +func (_ UintResult) Err() error { return nil } + +// Value returns the uinteger value for UintResult. +func (r UintResult) Value() uint { return uint(r) } + +// UintError ******************************************* +// + +// IsValid checks if the UintError is valid (always false, as it represents an error). +func (_ UintError) IsValid() bool { return false } + +// Value returns 0 for UintError, as it is considered invalid. +func (_ UintError) Value() uint { return 0 } + +// Err returns the error for UintError. +func (r UintError) Err() error { return r.error } + +// Uint8Result ******************************************* +// + +// IsValid checks if the Uint8Result is valid (always true). +func (_ Uint8Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Uint8Result. +func (_ Uint8Result) Err() error { return nil } + +// Value returns the uinteger value for Uint8Result. +func (r Uint8Result) Value() uint8 { return uint8(r) } + +// Uint8Error ******************************************* +// + +// IsValid checks if the Uint8Error is valid (always false). +func (_ Uint8Error) IsValid() bool { return false } + +// Value returns 0 for Uint8Error, as it is considered invalid. +func (_ Uint8Error) Value() uint8 { return 0 } + +// Err returns the error for Uint8Error. +func (r Uint8Error) Err() error { return r.error } + +// Uint16Result ******************************************* +// + +// IsValid checks if the Uint16Result is valid (always true). +func (_ Uint16Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Uint16Result. +func (_ Uint16Result) Err() error { return nil } + +// Value returns the uinteger value for Uint16Result. +func (r Uint16Result) Value() uint16 { return uint16(r) } + +// Uint16Error ******************************************* +// + +// IsValid checks if the Uint16Error is valid (always false). +func (_ Uint16Error) IsValid() bool { return false } + +// Value returns 0 for Uint16Error, as it is considered invalid. +func (_ Uint16Error) Value() uint16 { return 0 } + +// Err returns the error for Uint16Error. +func (r Uint16Error) Err() error { return r.error } + +// Uint32Result ******************************************* +// + +// IsValid checks if the Uint32Result is valid (always true). +func (_ Uint32Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Uint32Result. +func (_ Uint32Result) Err() error { return nil } + +// Value returns the uinteger value for Uint32Result. +func (r Uint32Result) Value() uint32 { return uint32(r) } + +// Uint32Error ******************************************* +// + +// IsValid checks if the Uint32Error is valid (always false). +func (_ Uint32Error) IsValid() bool { return false } + +// Value returns 0 for Uint32Error, as it is considered invalid. +func (_ Uint32Error) Value() uint32 { return 0 } + +// Err returns the error for Uint32Error. +func (r Uint32Error) Err() error { return r.error } + +// Uint64Result ******************************************* +// + +// IsValid checks if the Uint64Result is valid (always true). +func (_ Uint64Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Uint64Result. +func (_ Uint64Result) Err() error { return nil } + +// Value returns the uinteger value for Uint64Result. +func (r Uint64Result) Value() uint64 { return uint64(r) } + +// Uint64Error ******************************************* +// + +// IsValid checks if the Uint64Error is valid (always false). +func (_ Uint64Error) IsValid() bool { return false } + +// Value returns 0 for Uint64Error, as it is considered invalid. +func (_ Uint64Error) Value() uint64 { return 0 } + +// Err returns the error for Uint64Error. +func (r Uint64Error) Err() error { return r.error } diff --git a/core/rets/result_types_uints.go b/core/rets/result_types_uints.go new file mode 100644 index 0000000..02a573d --- /dev/null +++ b/core/rets/result_types_uints.go @@ -0,0 +1,181 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package rets + +// Type definitions for slices of unsigned results and errors of different unsigned types +type ( + + // UintsResult represents a valid slice of unsigned results. + UintsResult []uint + + // UintsError represents an invalid slice of unsigned results with an error. + UintsError struct{ error } + + // Uints8Result represents a valid slice of uint8 results. + Uints8Result []uint8 + + // Uints8Error represents an invalid slice of uint8 results with an error. + Uints8Error struct{ error } + + // Uints16Result represents a valid slice of uint16 results. + Uints16Result []uint16 + + // Uints16Error represents an invalid slice of uint16 results with an error. + Uints16Error struct{ error } + + // Uints32Result represents a valid slice of uint32 results. + Uints32Result []uint32 + + // Uints32Error represents an invalid slice of uint32 results with an error. + Uints32Error struct{ error } + + // Uints64Result represents a valid slice of uint64 results. + Uints64Result []uint64 + + // Uints64Error represents an invalid slice of uint64 results with an error. + Uints64Error struct{ error } +) + +// UintsResult ******************************************* +// + +// IsValid checks if the UintsResult is valid (always true). +func (_ UintsResult) IsValid() bool { return true } + +// Err returns nil as there is no error for UintsResult. +func (_ UintsResult) Err() error { return nil } + +// Value returns the slice of unsigned for UintsResult. +func (r UintsResult) Value() []uint { return r } + +// UintsError ******************************************* +// + +// IsValid checks if the UintsError is valid (always false, as it represents an error). +func (_ UintsError) IsValid() bool { return false } + +// Value returns nil for UintsError, as it is considered invalid. +func (_ UintsError) Value() []uint { return nil } + +// Err returns the error for UintsError. +func (r UintsError) Err() error { return r.error } + +// Uints8Result ******************************************* +// + +// IsValid checks if the Uints8Result is valid (always true). +func (_ Uints8Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Uints8Result. +func (_ Uints8Result) Err() error { return nil } + +// Value returns the slice of uint8 values for Uints8Result. +func (r Uints8Result) Value() []uint8 { return r } + +// Uints8Error ******************************************* +// + +// IsValid checks if the Uints8Error is valid (always false). +func (_ Uints8Error) IsValid() bool { return false } + +// Value returns nil for Uints8Error, as it is considered invalid. +func (_ Uints8Error) Value() []uint8 { return nil } + +// Err returns the error for Uints8Error. +func (r Uints8Error) Err() error { return r.error } + +// Uints16Result ******************************************* +// + +// IsValid checks if the Uints16Result is valid (always true). +func (_ Uints16Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Uints16Result. +func (_ Uints16Result) Err() error { return nil } + +// Value returns the slice of uint16 values for Uints16Result. +func (r Uints16Result) Value() []uint16 { return r } + +// Uints16Error ******************************************* +// + +// IsValid checks if the Uints16Error is valid (always false). +func (_ Uints16Error) IsValid() bool { return false } + +// Value returns nil for Uints16Error, as it is considered invalid. +func (_ Uints16Error) Value() []uint16 { return nil } + +// Err returns the error for Uints16Error. +func (r Uints16Error) Err() error { return r.error } + +// Uints32Result ******************************************* +// + +// IsValid checks if the Uints32Result is valid (always true). +func (_ Uints32Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Uints32Result. +func (_ Uints32Result) Err() error { return nil } + +// Value returns the slice of uint32 values for Uints32Result. +func (r Uints32Result) Value() []uint32 { return r } + +// Uints32Error ******************************************* +// + +// IsValid checks if the Uints32Error is valid (always false). +func (_ Uints32Error) IsValid() bool { return false } + +// Value returns nil for Uints32Error, as it is considered invalid. +func (_ Uints32Error) Value() []uint32 { return nil } + +// Err returns the error for Uints32Error. +func (r Uints32Error) Err() error { return r.error } + +// Uints64Result ******************************************* +// + +// IsValid checks if the Uints64Result is valid (always true). +func (_ Uints64Result) IsValid() bool { return true } + +// Err returns nil as there is no error for Uints64Result. +func (_ Uints64Result) Err() error { return nil } + +// Value returns the slice of uint64 values for Uints64Result. +func (r Uints64Result) Value() []uint64 { return r } + +// Uints64Error ******************************************* +// + +// IsValid checks if the Uints64Error is valid (always false). +func (_ Uints64Error) IsValid() bool { return false } + +// Value returns nil for Uints64Error, as it is considered invalid. +func (_ Uints64Error) Value() []uint64 { return nil } + +// Err returns the error for Uints64Error. +func (r Uints64Error) Err() error { return r.error } diff --git a/core/rets/valid_types.go b/core/rets/valid_types.go new file mode 100644 index 0000000..5d98575 --- /dev/null +++ b/core/rets/valid_types.go @@ -0,0 +1,216 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package rets + +import "core/rets/g_rets" + +type ( + + // String + StringResultor = g_rets.GResultor[string] + StringValidator = g_rets.GValidator[string] + ValidString string + InvalidString struct{} + + // Bool + BoolResultor = g_rets.GResultor[bool] + BoolValidator = g_rets.GValidator[bool] + ValidBool bool + InvalidBool struct{} + + // Ints + IntValidator = g_rets.GValidator[int] + ValidInt int + InvalidInt struct{} + + Int8Validator = g_rets.GValidator[int8] + ValidInt8 int8 + InvalidInt8 struct{} + + Int16Validator = g_rets.GValidator[int16] + ValidInt16 int16 + InvalidInt16 struct{} + + Int32Validator = g_rets.GValidator[int32] + ValidInt32 int32 + InvalidInt32 struct{} + + Int64Validator = g_rets.GValidator[int64] + ValidInt64 int64 + InvalidInt64 struct{} + + // Uints + UintValidator = g_rets.GValidator[uint] + ValidUint uint + InvalidUint struct{} + + Uint8Validator = g_rets.GValidator[uint8] + ValidUint8 uint8 + InvalidUint8 struct{} + + Uint16Validator = g_rets.GValidator[uint16] + ValidUint16 uint16 + InvalidUint16 struct{} + + Uint32Validator = g_rets.GValidator[uint32] + ValidUint32 uint32 + InvalidUint32 struct{} + + Uint64Validator = g_rets.GValidator[uint64] + ValidUint64 uint64 + InvalidUint64 struct{} + + // Floats + Float32Validator = g_rets.GValidator[float32] + ValidFloat32 float32 + InvalidFloat32 struct{} + + FloatValidator = g_rets.GValidator[float64] + ValidFloat64 float64 + InvalidFloat64 struct{} + + // Complex + Complex64Validator = g_rets.GValidator[complex64] + ValidComplex64 complex64 + InvalidComplex64 struct{} + + Complex128Validator = g_rets.GValidator[complex128] + ValidComplex128 complex128 + InvalidComplex128 struct{} +) + +// String Methods +func (_ ValidString) IsValid() bool { return true } +func (r ValidString) Value() string { return string(r) } + +func (_ InvalidString) IsValid() bool { return false } +func (_ InvalidString) Value() string { return "" } + +// Bool Methods +func (_ ValidBool) IsValid() bool { return true } +func (r ValidBool) Value() bool { return bool(r) } + +func (_ InvalidBool) IsValid() bool { return false } +func (_ InvalidBool) Value() bool { return false } + +// Int Methods +func (_ ValidInt) IsValid() bool { return true } +func (r ValidInt) Value() int { return int(r) } + +func (_ InvalidInt) IsValid() bool { return false } +func (_ InvalidInt) Value() int { return 0 } + +// Int8 Methods +func (_ ValidInt8) IsValid() bool { return true } +func (r ValidInt8) Value() int8 { return int8(r) } + +func (_ InvalidInt8) IsValid() bool { return false } +func (_ InvalidInt8) Value() int8 { return 0 } + +// Int16 Methods +func (_ ValidInt16) IsValid() bool { return true } +func (r ValidInt16) Value() int16 { return int16(r) } + +func (_ InvalidInt16) IsValid() bool { return false } +func (_ InvalidInt16) Value() int16 { return 0 } + +// Int32 Methods +func (_ ValidInt32) IsValid() bool { return true } +func (r ValidInt32) Value() int32 { return int32(r) } + +func (_ InvalidInt32) IsValid() bool { return false } +func (_ InvalidInt32) Value() int32 { return 0 } + +// Int64 Methods +func (_ ValidInt64) IsValid() bool { return true } +func (r ValidInt64) Value() int64 { return int64(r) } + +func (_ InvalidInt64) IsValid() bool { return false } +func (_ InvalidInt64) Value() int64 { return 0 } + +// Uint Methods +func (_ ValidUint) IsValid() bool { return true } +func (r ValidUint) Value() uint { return uint(r) } + +func (_ InvalidUint) IsValid() bool { return false } +func (_ InvalidUint) Value() uint { return 0 } + +// Uint8 Methods +func (_ ValidUint8) IsValid() bool { return true } +func (r ValidUint8) Value() uint8 { return uint8(r) } + +func (_ InvalidUint8) IsValid() bool { return false } +func (_ InvalidUint8) Value() uint8 { return 0 } + +// Uint16 Methods +func (_ ValidUint16) IsValid() bool { return true } +func (r ValidUint16) Value() uint16 { return uint16(r) } + +func (_ InvalidUint16) IsValid() bool { return false } +func (_ InvalidUint16) Value() uint16 { return 0 } + +// Uint32 Methods +func (_ ValidUint32) IsValid() bool { return true } +func (r ValidUint32) Value() uint32 { return uint32(r) } + +func (_ InvalidUint32) IsValid() bool { return false } +func (_ InvalidUint32) Value() uint32 { return 0 } + +// Uint64 Methods +func (_ ValidUint64) IsValid() bool { return true } +func (r ValidUint64) Value() uint64 { return uint64(r) } + +func (_ InvalidUint64) IsValid() bool { return false } +func (_ InvalidUint64) Value() uint64 { return 0 } + +// Float32 Methods +func (_ ValidFloat32) IsValid() bool { return true } +func (r ValidFloat32) Value() float32 { return float32(r) } + +func (_ InvalidFloat32) IsValid() bool { return false } +func (_ InvalidFloat32) Value() float32 { return 0 } + +// Float64 Methods +func (_ ValidFloat64) IsValid() bool { return true } +func (r ValidFloat64) Value() float64 { return float64(r) } + +func (_ InvalidFloat64) IsValid() bool { return false } +func (_ InvalidFloat64) Value() float64 { return 0 } + +// Complex64 Methods +func (_ ValidComplex64) IsValid() bool { return true } +func (r ValidComplex64) Value() complex64 { return complex64(r) } + +func (_ InvalidComplex64) IsValid() bool { return false } +func (_ InvalidComplex64) Value() complex64 { return 0 } + +// Complex128 Methods +func (_ ValidComplex128) IsValid() bool { return true } +func (r ValidComplex128) Value() complex128 { return complex128(r) } + +func (_ InvalidComplex128) IsValid() bool { return false } +func (_ InvalidComplex128) Value() complex128 { return 0 } diff --git a/core/rets/value_result.go b/core/rets/value_result.go new file mode 100644 index 0000000..a4242f1 --- /dev/null +++ b/core/rets/value_result.go @@ -0,0 +1,44 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package rets + +import "core/rets/g_rets" + +// ValueResult is an alias for the GValueResult type from the g_rets package. +// This alias simplifies usage by referring to GValueResult with the generic type `any`, +// making it easier to work with any type of value as a result in the program. +type ValueResult = g_rets.GValueResult[any] + +// NewValueResult creates a new instance of ValueResult using the g_rets package's NewGValueResult function. +// It takes a value of any type as input and returns a pointer to a ValueResult containing that value. +// +// The function uses the `any` type for generic handling, allowing you to create value results +// for any specific type of value that needs to be encapsulated in the result. +func NewValueResult(value any) *ValueResult { + // Create and return a value result using the provided value. + return g_rets.NewGValueResult[any](value) +} diff --git a/core/vals/blds/builder.go b/core/vals/blds/builder.go new file mode 100644 index 0000000..9a90cb2 --- /dev/null +++ b/core/vals/blds/builder.go @@ -0,0 +1,65 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package blds + +import "time" + +type Builder interface { + Any(value any) + + Raw(value []byte) + + Binary(value []byte) + String(value string) + + Bool(value bool) + + Int(value int) + Int8(value int8) + Int16(value int16) + Int32(value int32) + Int64(value int64) + + Uint(value uint) + Uint8(value uint8) + Uint16(value uint16) + Uint32(value uint32) + Uint64(value uint64) + Uintptr(value uintptr) + + Float32(value float32) + Float64(value float64) + + Error(value error) + + Time(value time.Time) + Duration(value time.Duration) + + List(buildFn func(b ListBuilder)) + Map(buildFn func(b MapBuilder)) + Object(buildFn func(b ObjectBuilder)) +} diff --git a/core/vals/blds/fields_builder.go b/core/vals/blds/fields_builder.go new file mode 100644 index 0000000..d93680b --- /dev/null +++ b/core/vals/blds/fields_builder.go @@ -0,0 +1,39 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package blds + +type ( + FieldsBuilder interface { + Build(builder ObjectBuilder) + } + + FieldsBuilderFnc func(builder ObjectBuilder) +) + +func (f FieldsBuilderFnc) BuildField(builder ObjectBuilder) { + f(builder) +} diff --git a/core/vals/blds/list_builder.go b/core/vals/blds/list_builder.go new file mode 100644 index 0000000..11c6f90 --- /dev/null +++ b/core/vals/blds/list_builder.go @@ -0,0 +1,39 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package blds + +type ( + ListBuilder interface { + BuildItem() Builder + } + + ListBuilderFnc func() Builder +) + +func (f ListBuilderFnc) BuildItem() Builder { + return f() +} diff --git a/core/vals/blds/map_builder.go b/core/vals/blds/map_builder.go new file mode 100644 index 0000000..72cf3f7 --- /dev/null +++ b/core/vals/blds/map_builder.go @@ -0,0 +1,39 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package blds + +type ( + MapBuilder interface { + BuildElement(key any) Builder + } + + MapBuilderFnc func(key any) Builder +) + +func (f MapBuilderFnc) BuildElement(key any) Builder { + return f(key) +} diff --git a/core/vals/blds/object_builder.go b/core/vals/blds/object_builder.go new file mode 100644 index 0000000..6cbd26f --- /dev/null +++ b/core/vals/blds/object_builder.go @@ -0,0 +1,39 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package blds + +type ( + ObjectBuilder interface { + BuildField(name string) Builder + } + + ObjectBuilderFnc func(name string) Builder +) + +func (f ObjectBuilderFnc) BuildField(name string) Builder { + return f(name) +} diff --git a/core/vals/flds/active.go b/core/vals/flds/active.go new file mode 100644 index 0000000..f443d9a --- /dev/null +++ b/core/vals/flds/active.go @@ -0,0 +1,73 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package flds + +import ( + "core/errs" + "core/rets" + "regexp" +) + +const ( + // namePattern is the regular expression that defines a valid error code format. + // The error code can optionally have a module, which is separated by "::". + // The valid characters are alphanumeric characters and the symbols ":-_". + namePattern string = "^[a-zA-Z][a-zA-Z0-9_-]*$" +) + +const ( + moduleName = "core.vals.flds" + errs.ModuleSeparator +) + +var ( + G = struct { + ErrInvalidName, + ErrInvalidValue, + ErrInvalidCast, + ErrDuplicatedName errs.ErrCode + }{ + + ErrInvalidCast: errs.MakeErrCode(moduleName + "invalid-cast-type"), + ErrInvalidName: errs.MakeErrCode(moduleName + "invalid-field-name"), + } + + g = struct { + nameValidator *regexp.Regexp + boolCastError rets.BoolError + stringCastError rets.StringError + }{ + + nameValidator: regexp.MustCompile(namePattern), + + boolCastError: *rets.NewBoolError(G.ErrInvalidCast), + stringCastError: *rets.NewStringError(G.ErrInvalidCast), + } +) + +func ValidateName(name string) bool { + return g.nameValidator.MatchString(name) +} diff --git a/core/vals/flds/field.go b/core/vals/flds/field.go new file mode 100644 index 0000000..7b4d911 --- /dev/null +++ b/core/vals/flds/field.go @@ -0,0 +1,74 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package flds + +import ( + "core/rets" + "core/vals" +) + +type Field struct { + vals.ValueProvider + name string + kind Kind +} + +func newField(provider vals.ValueProvider, name string, kind Kind) *Field { + return &Field{ + ValueProvider: provider, + name: name, + kind: kind, + } +} + +func (f Field) Name() string { + return f.name +} + +func (f Field) Kind() Kind { + return f.kind +} + +func (f Field) AsString() rets.StringResultor { + if f.kind.IsString() { + return rets.StringResult((f.Value()).(string)) + } + if vl, is := (f.Value()).(string); is { + return rets.StringResult(vl) + } + return g.stringCastError +} + +func (f Field) AsBool() rets.BoolResultor { + if f.kind.IsBool() { + return rets.BoolResult((f.Value()).(bool)) + } + if vl, is := (f.Value()).(bool); is { + return rets.BoolResult(vl) + } + return g.boolCastError +} diff --git a/core/vals/flds/kind.go b/core/vals/flds/kind.go new file mode 100644 index 0000000..736fecb --- /dev/null +++ b/core/vals/flds/kind.go @@ -0,0 +1,98 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package flds + +const ( + KindAny Kind = 1 << iota + KindBool + KindBinary + KindString + KindInt + KindUint + KindFloat + KindTime + KindDuration + KindError + KindReflect + + KindDefer Kind = 8192 + KindDeferOnce Kind = 16384 + + typesMask Kind = 0b0000011111111111 +) + +type ( + Kind uint16 +) + +func (k Kind) DataType() Kind { + return k & typesMask +} + +func (k Kind) IsAny() bool { + return k&KindAny != 0 +} + +func (k Kind) IsBool() bool { + return k&KindBool != 0 +} + +func (k Kind) IsInt() bool { + return k&KindInt != 0 +} + +func (k Kind) IsUint() bool { + return k&KindUint != 0 +} + +func (k Kind) IsFloat() bool { + return k&KindFloat != 0 +} + +func (k Kind) IsString() bool { + return k&KindString != 0 +} + +func (k Kind) IsTime() bool { + return k&KindTime != 0 +} + +func (k Kind) IsDuration() bool { + return k&KindDuration != 0 +} + +func (k Kind) IsBinary() bool { + return k&KindBinary != 0 +} + +func (k Kind) IsError() bool { + return k&KindError != 0 +} + +func (k Kind) IsReflect() bool { + return k&KindReflect != 0 +} diff --git a/core/vals/g_vals/g_key_value_getter.go b/core/vals/g_vals/g_key_value_getter.go new file mode 100644 index 0000000..a062662 --- /dev/null +++ b/core/vals/g_vals/g_key_value_getter.go @@ -0,0 +1,68 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_vals + +import "core/rets/g_rets" + +type ( + // GKeyValueGetter defines a generic interface for retrieving values from a key-value store. + // The interface is parameterized with two type parameters: + // K: The key type, which must be comparable + // T: The value type, which can be any type + // + // This interface provides a single method for value retrieval that returns + // a generic result type, allowing for type-safe error handling. + GKeyValueGetter[K comparable, T any] interface { + // GetValue retrieves a value of type T associated with the given key. + // Returns a GResulter containing either the value or an error. + GetValue(key K) g_rets.GResultor[T] + } + + // GetKeyValueFnc is a function type that implements the GKeyValueGetter interface. + // It allows simple functions to be used as key-value getters without creating + // a full struct implementation. + // + // Type parameters: + // K: The key type, which must be comparable + // T: The value type, which can be any type + // + // This type enables functional programming patterns and easy adaptation + // of existing functions to the GKeyValueGetter interface. + GetKeyValueFnc[K comparable, T any] func(key K) g_rets.GResultor[T] +) + +// GetValue implements the GKeyValueGetter interface for the GetKeyValueFnc type. +// This method allows the function type to be used directly as a GKeyValueGetter. +// +// Parameters: +// - key: The key of type K to look up +// +// Returns: +// - g_rets.GResulter[T]: The result of calling the underlying function +func (f GetKeyValueFnc[K, T]) GetValue(key K) g_rets.GResultor[T] { + return f(key) +} diff --git a/core/vals/g_vals/g_key_value_setter.go b/core/vals/g_vals/g_key_value_setter.go new file mode 100644 index 0000000..0e1cd8a --- /dev/null +++ b/core/vals/g_vals/g_key_value_setter.go @@ -0,0 +1,74 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_vals + +type ( + // GNameValueSetter defines a generic interface for storing values in a name-value store. + // The interface is parameterized with type parameter: + // T: The value type, which can be any type + // + // This interface provides a single method for storing values with type safety + // and error handling. + GNameValueSetter[T any] interface { + // SetValue stores a value of type T associated with the given name. + // Returns an error if the operation fails. + // + // Parameters: + // - name: The string name under which to store the value + // - value: The value to store + // + // Returns: + // - error: nil if successful, otherwise an error describing the failure + SetValue(name string, value T) error + } + + // GNameValueSetterFnc is a function type that implements the GNameValueSetter interface. + // It allows simple functions to be used as name-value setters without creating + // a full struct implementation. + // + // Parameters: + // - name: The string name under which to store the value + // Type parameters: + // T: The value type, which can be any type + // + // This type enables functional programming patterns and easy adaptation + // of existing functions to the GNameValueSetter interface. + GNameValueSetterFnc[T any] func(name string, value T) error +) + +// SetValue implements the GNameValueSetter interface for the GKeyValueSetterFnc type. +// This method allows the function type to be used directly as a GNameValueSetter. +// +// Parameters: +// - name: The name string under which to store the value +// - value: The value of type T to store +// +// Returns: +// - error: The result of calling the underlying function +func (f GNameValueSetterFnc[T]) SetValue(name string, value T) error { + return f(name, value) +} diff --git a/core/vals/g_vals/g_name_value_getter.go b/core/vals/g_vals/g_name_value_getter.go new file mode 100644 index 0000000..2847d9b --- /dev/null +++ b/core/vals/g_vals/g_name_value_getter.go @@ -0,0 +1,64 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_vals + +// GNameValueGetter is a generic interface that defines a contract for retrieving +// values of type T using a string name as the key. +// +// Type Parameters: +// - T: The type of value to be retrieved. Can be any valid Go type. +// +// Methods: +// - GetValue(name string) T: Returns a value of type T associated with the given name. +type ( + GNameValueGetter[T any] interface { + GetValue(name string) T + } + + // GNameValueGetterFnc is a function type that implements GNameValueGetter. + // It allows for creating value getters from simple functions, following + // the adapter pattern. + // + // Type Parameters: + // - T: The type of value to be returned by the function. + // + // The function signature matches the GetValue method of GNameValueGetter: + // - Input: name string - The key to lookup the value + // - Output: T - The value associated with the name + GNameValueGetterFnc[T any] func(name string) T +) + +// GetValue implements the GNameValueGetter interface for GNameValueGetterFnc. +// It simply calls the function itself, allowing the function to be used +// wherever a GNameValueGetter is expected. +// +// Parameters: +// - name: The key to lookup the value +// +// Returns: +// - T: The value associated with the name +func (f GNameValueGetterFnc[T]) GetValue(name string) T { return f(name) } diff --git a/core/vals/g_vals/g_name_value_setter.go b/core/vals/g_vals/g_name_value_setter.go new file mode 100644 index 0000000..69f4cf2 --- /dev/null +++ b/core/vals/g_vals/g_name_value_setter.go @@ -0,0 +1,74 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_vals + +type ( + // GKeyValueSetter defines a generic interface for storing values in a key-value store. + // The interface is parameterized with two type parameters: + // K: The key type, which must be comparable + // T: The value type, which can be any type + // + // This interface provides a single method for storing values with type safety + // and error handling. + GKeyValueSetter[K comparable, T any] interface { + // SetValue stores a value of type T associated with the given key. + // Returns an error if the operation fails. + // + // Parameters: + // - key: The key under which to store the value + // - value: The value to store + // + // Returns: + // - error: nil if successful, otherwise an error describing the failure + SetValue(key K, value T) error + } + + // GKeyValueSetterFnc is a function type that implements the GKeyValueSetter interface. + // It allows simple functions to be used as key-value setters without creating + // a full struct implementation. + // + // Type parameters: + // K: The key type, which must be comparable + // T: The value type, which can be any type + // + // This type enables functional programming patterns and easy adaptation + // of existing functions to the GKeyValueSetter interface. + GKeyValueSetterFnc[K comparable, T any] func(key K, value T) error +) + +// SetValue implements the GKeyValueSetter interface for the GKeyValueSetterFnc type. +// This method allows the function type to be used directly as a GKeyValueSetter. +// +// Parameters: +// - key: The key of type K under which to store the value +// - value: The value of type T to store +// +// Returns: +// - error: The result of calling the underlying function +func (f GKeyValueSetterFnc[K, T]) SetValue(key K, value T) error { + return f(key, value) +} diff --git a/core/vals/g_vals/g_value.go b/core/vals/g_vals/g_value.go new file mode 100644 index 0000000..7dd65a4 --- /dev/null +++ b/core/vals/g_vals/g_value.go @@ -0,0 +1,47 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_vals + +// GValue is a generic container struct that wraps a single value of any type. +// It provides a simple way to store and retrieve values in a type-safe manner. +// +// Type Parameters: +// - T: The type of the contained value. Can be any valid Go type. +// +// Fields: +// - V: The stored value of type T +type GValue[T any] struct { + V T +} + +// Value returns the contained value of type T. +// This method provides a consistent way to access the wrapped value, +// following the getter pattern common in Go. +// +// Returns: +// - T: The stored value +func (v GValue[T]) Value() T { return v.V } diff --git a/core/vals/g_vals/g_value_getter.go b/core/vals/g_vals/g_value_getter.go new file mode 100644 index 0000000..a232677 --- /dev/null +++ b/core/vals/g_vals/g_value_getter.go @@ -0,0 +1,68 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_vals + +type ( + // GValueGetter defines a generic interface for retrieving values. + // Unlike GKeyValueGetter, this interface is simpler and doesn't require a key. + // It's parameterized with a single type parameter T that can be any type. + // + // This interface is useful for: + // - Lazy value evaluation + // - Value providers + // - Deferred computation + // - Wrapping value sources + GValueGetter[T any] interface { + // GetValue retrieves a value of type T. + // This method represents a simple value retrieval operation + // without parameters. + // + // Returns: + // - T: The retrieved value + GetValue() T + } + + // GValueGetterFnc is a function type that implements the GValueGetter interface. + // It allows simple functions to be used as value getters without creating + // a full struct implementation. + // + // Type parameters: + // T: The type of value to be retrieved + // + // This type enables functional programming patterns and easy creation + // of value providers from simple functions. + GValueGetterFnc[T any] func() T +) + +// GetValue implements the GValueGetter interface for the GValueGetterFnc type. +// This method allows the function type to be used directly as a GValueGetter. +// +// Returns: +// - T: The result of calling the underlying function +func (f GValueGetterFnc[T]) GetValue() T { + return f() +} diff --git a/core/vals/g_vals/g_value_provider.go b/core/vals/g_vals/g_value_provider.go new file mode 100644 index 0000000..840cc55 --- /dev/null +++ b/core/vals/g_vals/g_value_provider.go @@ -0,0 +1,78 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_vals + +// Package g_vals provides generic interfaces for value provision operations. + +type ( + // GValueProvider defines a generic interface for providing values. + // It represents a source of values of type T, similar to GValueGetter + // but with a more specific semantic meaning of "providing" rather than + // "getting" values. + // + // Type parameters: + // T: The type of value to be provided, can be any type + // + // This interface is useful for: + // - Factory patterns + // - Lazy value generation + // - Dynamic value creation + // - Dependency injection + // - Value computation + GValueProvider[T any] interface { + // Value returns a value of type T. + // This method represents the provision of a value, which could be: + // - A computed value + // - A generated instance + // - A cached result + // - A factory-created object + // + // Returns: + // - T: The provided value + Value() T + } + + // GValueProviderFnc is a function type that implements the GValueProvider interface. + // It allows simple functions to be used as value providers without creating + // a full struct implementation. + // + // Type parameters: + // T: The type of value to be provided + // + // This type enables functional programming patterns and easy creation + // of value providers from simple functions. + GValueProviderFnc[T any] func() T +) + +// Value implements the GValueProvider interface for the GValueProviderFnc type. +// This method allows the function type to be used directly as a GValueProvider. +// +// Returns: +// - T: The result of calling the underlying function +func (f GValueProviderFnc[T]) Value() T { + return f() +} diff --git a/core/vals/g_vals/g_value_setter.go b/core/vals/g_vals/g_value_setter.go new file mode 100644 index 0000000..5fee16f --- /dev/null +++ b/core/vals/g_vals/g_value_setter.go @@ -0,0 +1,72 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package g_vals + +// Package g_vals provides generic interfaces for value manipulation operations. + +type ( + // GValueSetter defines a generic interface for setting values. + // It provides a simple, type-safe way to store or update values + // without the complexity of key-value operations. + // + // Type parameters: + // T: The type of value to be set, can be any type + // + // This interface is useful for: + // - Value containers + // - State updaters + // - Configuration setters + // - Property writers + GValueSetter[T any] interface { + // SetValue updates or stores a value of type T. + // This method represents a simple value setting operation. + // + // Parameters: + // - value: The value of type T to be stored or updated + SetValue(T) + } + + // GValueSetterFnc is a function type that implements the GValueSetter interface. + // It allows simple functions to be used as value setters without creating + // a full struct implementation. + // + // Type parameters: + // T: The type of value to be set + // + // This type enables functional programming patterns and easy creation + // of value setters from simple functions. + GValueSetterFnc[T any] func(T) +) + +// SetValue implements the GValueSetter interface for the GValueSetterFnc type. +// This method allows the function type to be used directly as a GValueSetter. +// +// Parameters: +// - value: The value of type T to be set +func (f GValueSetterFnc[T]) SetValue(value T) { + f(value) +} diff --git a/core/vals/types.go b/core/vals/types.go new file mode 100644 index 0000000..a49272c --- /dev/null +++ b/core/vals/types.go @@ -0,0 +1,227 @@ +// ============================================================================= +// Active-GO Framework +// Copyright (c) 2024 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. +// +// ============================================================================= + +package vals + +import ( + "core/vals/g_vals" + "reflect" + "time" +) + +type ( + + // ValueProvider defines an interface for providing any type of value + ValueProvider = g_vals.GValueProvider[any] + + // ValueProviderFnc is a function implementation of ValueProvider + ValueProviderFnc = g_vals.GValueProviderFnc[any] + + // ValueGetter defines an interface for getting any type of value + ValueGetter = g_vals.GValueGetter[any] + + // ValueGetterFnc is a function implementation of ValueGetter + ValueGetterFnc = g_vals.GValueGetterFnc[any] + + // ValueSetter defines an interface for setting any type of value + ValueSetter = g_vals.GValueSetter[any] + + // ValueSetterFnc is a function implementation of ValueSetter + ValueSetterFnc = g_vals.GValueSetterFnc[any] + + // KeyValueGetter is a type alias for the generic GKeyValueGetter interface + // specialized for any key and value types. It defines the read operations + // that can be performed on a key-value store. + // + // The interface allows for type-safe value retrieval while maintaining + // flexibility through the use of 'any' type parameters. + KeyValueGetter = g_vals.GKeyValueGetter[any, any] + + // KeyValueSetter is a type alias for the generic GKeyValueSetter interface + // specialized for any key and value types. It defines the write operations + // that can be performed on a key-value store. + // + // The interface allows for type-safe value setting while maintaining + // flexibility through the use of 'any' type parameters. + KeyValueSetter = g_vals.GKeyValueSetter[any, any] +) + +// AsValue extracts the actual value from various types of value containers. +// It handles nil values, value providers, getters, basic types, and functions. +// +// The function will: +// - Return nil for nil input +// - Call Value() for ValueProvider +// - Call GetValue() for ValueGetter +// - Return the value directly for basic types and their slices +// - Execute functions that take no parameters and return one value +// - Use reflection for generic functions with matching signature +// - Return the original object if no other case matches +// +// Parameters: +// - object: any type of value or value container +// +// Returns: +// - the extracted or computed value +func AsValue(object any) any { + if object == nil { + return nil + } + switch obj := object.(type) { + case ValueProvider: + return obj.Value() + case ValueGetter: + return obj.GetValue() + // Basic types (returned directly) + case string, bool, + int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, + float32, float64, complex64, complex128, + []string, []bool, + []int, []int8, []int16, []int32, []int64, + []uint, []uint8, []uint16, []uint32, []uint64, + []float32, []float64, + []complex64, []complex128, + map[string]string, map[string]any, + map[string]int, map[int]string, map[int]any, + time.Time, *time.Time, time.Duration, *time.Duration, + error, chan string, chan int, chan bool, chan any: + return obj + // Common function types + case func() any: + return obj() + case func() string: + return obj() + case func() int: + return obj() + case func() uint: + return obj() + case func() float64: + return obj() + case func() bool: + return obj() + case func() error: + return obj() + default: + // Use reflection for generic functions + rv := reflect.ValueOf(object) + if rv.Kind() == reflect.Func && rv.Type().NumOut() == 1 && rv.Type().NumIn() == 0 { + return rv.Call(nil)[0].Interface() + } + } + // Return the object directly if no other case matches + return object +} + +// AsValueProvider wraps an object into a ValueProvider interface. +// It's a convenience wrapper around CheckValueProvider that ignores the boolean return value. +// +// Parameters: +// - object: any value to be wrapped as a ValueProvider +// +// Returns: +// - a ValueProvider that will return the wrapped value +func AsValueProvider(object any) (prov ValueProvider) { + prov, _ = CheckValueProvider(object) + return +} + +// CheckValueProvider creates a ValueProvider from any value and indicates if the value +// is a natural provider (true) or was wrapped (false). +// +// A natural provider is: +// - An existing ValueProvider +// - A ValueGetter +// - A function returning a value +// +// The function handles: +// - nil values +// - Basic types and their slices +// - Common map types +// - Time-related types +// - Error types +// - Channel types +// - Common function types +// - Generic functions through reflection +// +// Parameters: +// - object: any value to be converted to a ValueProvider +// +// Returns: +// - ValueProvider: a provider that will return the value +// - bool: true if the object was naturally a provider, false if it was wrapped +func CheckValueProvider(object any) (ValueProvider, bool) { + if object == nil { + return ValueProviderFnc(func() any { return nil }), true + } + switch obj := object.(type) { + case ValueProvider: + return obj, true + case ValueGetter: + return ValueProviderFnc(obj.GetValue), true + // Basic types and collections (wrapped as providers) + case string, bool, + int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, + float32, float64, + complex64, complex128, + []string, []bool, + []int, []int8, []int16, []int32, []int64, + []uint, []uint8, []uint16, []uint32, []uint64, + []float32, []float64, + []complex64, []complex128, + map[string]string, + map[string]int, map[int]string, + map[string]any, + map[int]any, + time.Time, *time.Time, + time.Duration, *time.Duration, + error, + chan string, chan int, chan bool, + chan any: + return ValueProviderFnc(func() any { return obj }), false + // Common function types (natural providers) + case func() string: + return ValueProviderFnc(func() any { return obj() }), true + case func() int: + return ValueProviderFnc(func() any { return obj() }), true + case func() uint: + return ValueProviderFnc(func() any { return obj() }), true + case func() float64: + return ValueProviderFnc(func() any { return obj() }), true + case func() error: + return ValueProviderFnc(func() any { return obj() }), true + case func() any: + return ValueProviderFnc(obj), true + default: + // Handle generic functions through reflection + rv := reflect.ValueOf(object) + if rv.Kind() == reflect.Func && rv.Type().NumOut() == 1 && rv.Type().NumIn() == 0 { + return ValueProviderFnc(func() any { return rv.Call(nil)[0].Interface() }), true + } + return ValueProviderFnc(func() any { return object }), false + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..36f408f --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module Active-GO + +go 1.22 diff --git a/go.work b/go.work new file mode 100644 index 0000000..ff2664d --- /dev/null +++ b/go.work @@ -0,0 +1,6 @@ +go 1.22 + +use ( + . + core +) \ No newline at end of file