This commit is contained in:
XOF
2025-11-20 12:24:05 +08:00
commit f28bdc751f
164 changed files with 64248 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
// Filename: internal/pkg/reflectutil/structs.go
package reflectutil
import (
"fmt"
"reflect"
"strconv"
)
// SetFieldFromString sets a struct field's value from a string.
func SetFieldFromString(field reflect.Value, value string) error {
if !field.CanSet() {
return fmt.Errorf("cannot set field")
}
switch field.Kind() {
case reflect.Int, reflect.Int64:
intVal, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
field.SetInt(intVal)
case reflect.String:
field.SetString(value)
case reflect.Bool:
boolVal, err := strconv.ParseBool(value)
if err != nil {
return err
}
field.SetBool(boolVal)
default:
return fmt.Errorf("unsupported field type: %s", field.Type())
}
return nil
}
// FieldTypeToString converts a reflect.Type to a simple string representation.
func FieldTypeToString(t reflect.Type) string {
switch t.Kind() {
case reflect.Int, reflect.Int64:
return "int"
case reflect.String:
return "string"
case reflect.Bool:
return "bool"
default:
return "unknown"
}
}
// MergeNilFields uses reflection to merge non-nil pointer fields from 'override' into 'base'.
// Both base and override must be pointers to structs of the same type.
func MergeNilFields(base, override interface{}) error {
baseVal := reflect.ValueOf(base)
overrideVal := reflect.ValueOf(override)
if baseVal.Kind() != reflect.Ptr || overrideVal.Kind() != reflect.Ptr {
return fmt.Errorf("base and override must be pointers")
}
baseElem := baseVal.Elem()
overrideElem := overrideVal.Elem()
if baseElem.Kind() != reflect.Struct || overrideElem.Kind() != reflect.Struct {
return fmt.Errorf("base and override must be pointers to structs")
}
if baseElem.Type() != overrideElem.Type() {
return fmt.Errorf("base and override must be of the same struct type")
}
for i := 0; i < overrideElem.NumField(); i++ {
overrideField := overrideElem.Field(i)
if overrideField.Kind() == reflect.Ptr && !overrideField.IsNil() {
baseField := baseElem.Field(i)
if baseField.CanSet() {
baseField.Set(overrideField)
}
}
}
return nil
}

View File

@@ -0,0 +1,57 @@
// Filename: internal/pkg/stringutil/string.go
package stringutil
import (
"fmt"
"strings"
)
// MaskAPIKey masks an API key for safe logging.
func MaskAPIKey(key string) string {
length := len(key)
if length <= 8 {
return key
}
return fmt.Sprintf("%s****%s", key[:4], key[length-4:])
}
// TruncateString shortens a string to a maximum length.
func TruncateString(s string, maxLength int) string {
if len(s) > maxLength {
return s[:maxLength]
}
return s
}
// SplitAndTrim splits a string by a separator
func SplitAndTrim(s string, sep string) []string {
if s == "" {
return []string{}
}
parts := strings.Split(s, sep)
result := make([]string, 0, len(parts))
for _, part := range parts {
trimmed := strings.TrimSpace(part)
if trimmed != "" {
result = append(result, trimmed)
}
}
return result
}
// StringToSet converts a separator-delimited string into a set
func StringToSet(s string, sep string) map[string]struct{} {
parts := SplitAndTrim(s, sep)
if len(parts) == 0 {
return nil
}
set := make(map[string]struct{}, len(parts))
for _, part := range parts {
set[part] = struct{}{}
}
return set
}