package utils import ( "context" "encoding/json" "math/big" "reflect" "strings" "time" "github.com/google/uuid" ) // GenerateID generates a new UUID func GenerateID() uuid.UUID { return uuid.New() } // ParseUUID parses a string to UUID func ParseUUID(s string) (uuid.UUID, error) { return uuid.Parse(s) } // MustParseUUID parses a string to UUID, panics on error func MustParseUUID(s string) uuid.UUID { id, err := uuid.Parse(s) if err != nil { panic(err) } return id } // IsValidUUID checks if a string is a valid UUID func IsValidUUID(s string) bool { _, err := uuid.Parse(s) return err == nil } // ToJSON converts an interface to JSON bytes func ToJSON(v interface{}) ([]byte, error) { return json.Marshal(v) } // FromJSON converts JSON bytes to an interface func FromJSON(data []byte, v interface{}) error { return json.Unmarshal(data, v) } // NowUTC returns the current UTC time func NowUTC() time.Time { return time.Now().UTC() } // TimePtr returns a pointer to the time func TimePtr(t time.Time) *time.Time { return &t } // NowPtr returns a pointer to the current time func NowPtr() *time.Time { now := NowUTC() return &now } // BigIntToBytes converts a big.Int to bytes (32 bytes, left-padded) func BigIntToBytes(n *big.Int) []byte { if n == nil { return make([]byte, 32) } b := n.Bytes() if len(b) > 32 { return b[:32] } if len(b) < 32 { result := make([]byte, 32) copy(result[32-len(b):], b) return result } return b } // BytesToBigInt converts bytes to big.Int func BytesToBigInt(b []byte) *big.Int { return new(big.Int).SetBytes(b) } // StringSliceContains checks if a string slice contains a value func StringSliceContains(slice []string, value string) bool { for _, s := range slice { if s == value { return true } } return false } // StringSliceRemove removes a value from a string slice func StringSliceRemove(slice []string, value string) []string { result := make([]string, 0, len(slice)) for _, s := range slice { if s != value { result = append(result, s) } } return result } // UniqueStrings returns unique strings from a slice func UniqueStrings(slice []string) []string { seen := make(map[string]struct{}) result := make([]string, 0, len(slice)) for _, s := range slice { if _, ok := seen[s]; !ok { seen[s] = struct{}{} result = append(result, s) } } return result } // TruncateString truncates a string to max length func TruncateString(s string, maxLen int) string { if len(s) <= maxLen { return s } return s[:maxLen] } // SafeString returns an empty string if the pointer is nil func SafeString(s *string) string { if s == nil { return "" } return *s } // StringPtr returns a pointer to the string func StringPtr(s string) *string { return &s } // IntPtr returns a pointer to the int func IntPtr(i int) *int { return &i } // BoolPtr returns a pointer to the bool func BoolPtr(b bool) *bool { return &b } // IsZero checks if a value is zero/empty func IsZero(v interface{}) bool { return reflect.ValueOf(v).IsZero() } // Coalesce returns the first non-zero value func Coalesce[T comparable](values ...T) T { var zero T for _, v := range values { if v != zero { return v } } return zero } // MapKeys returns the keys of a map func MapKeys[K comparable, V any](m map[K]V) []K { keys := make([]K, 0, len(m)) for k := range m { keys = append(keys, k) } return keys } // MapValues returns the values of a map func MapValues[K comparable, V any](m map[K]V) []V { values := make([]V, 0, len(m)) for _, v := range m { values = append(values, v) } return values } // Min returns the minimum of two values func Min[T ~int | ~int64 | ~float64](a, b T) T { if a < b { return a } return b } // Max returns the maximum of two values func Max[T ~int | ~int64 | ~float64](a, b T) T { if a > b { return a } return b } // Clamp clamps a value between min and max func Clamp[T ~int | ~int64 | ~float64](value, min, max T) T { if value < min { return min } if value > max { return max } return value } // ContextWithTimeout creates a context with timeout func ContextWithTimeout(timeout time.Duration) (context.Context, context.CancelFunc) { return context.WithTimeout(context.Background(), timeout) } // MaskString masks a string showing only first and last n characters func MaskString(s string, showChars int) string { if len(s) <= showChars*2 { return strings.Repeat("*", len(s)) } return s[:showChars] + strings.Repeat("*", len(s)-showChars*2) + s[len(s)-showChars:] } // Retry executes a function with retries func Retry(attempts int, sleep time.Duration, f func() error) error { var err error for i := 0; i < attempts; i++ { if err = f(); err == nil { return nil } if i < attempts-1 { time.Sleep(sleep) sleep *= 2 // Exponential backoff } } return err }