rwadurian/backend/mpc-system/pkg/utils/utils.go

240 lines
5.0 KiB
Go

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
}