package conv import ( "encoding/json" "fmt" "strconv" "strings" ) // Uint32 coerces an interface value to a uint32. // It returns the uint32 value and true on success, or 0 and false if coercion fails. func Uint32(v any) (uint32, bool) { if v == nil { return 0, false } switch n := v.(type) { case uint32: return n, true case float64: if n < 0 || n > 4294967295 { return 0, false } return uint32(n), true case float32: if n < 0 || n > 4294967295 { return 0, false } return uint32(n), true case int: if n < 0 || n > 4294967295 { return 0, false } return uint32(n), true case int64: if n < 0 || n > 4294967295 { return 0, false } return uint32(n), true case uint64: if n > 4294967295 { return 0, false } return uint32(n), true case json.Number: u, err := strconv.ParseUint(n.String(), 10, 32) if err != nil { return 0, false } return uint32(u), true case string: s := strings.TrimSpace(n) if s == "" { return 0, false } u, err := strconv.ParseUint(s, 10, 32) if err != nil { return 0, false } return uint32(u), true } return 0, false } // String coerces an interface value to a string. // It handles common numeric types and falls back to fmt.Sprintf. func String(v any) string { if v == nil { return "" } switch n := v.(type) { case string: return n case int: return strconv.Itoa(n) case int64: return strconv.FormatInt(n, 10) case uint32: return strconv.FormatUint(uint64(n), 10) case uint64: return strconv.FormatUint(n, 10) case float64: // If it's a whole number, represent it as an integer to avoid scientific notation if n == float64(int64(n)) { return strconv.FormatInt(int64(n), 10) } return strconv.FormatFloat(n, 'f', -1, 64) case float32: if n == float32(int32(n)) { return strconv.Itoa(int(n)) } return strconv.FormatFloat(float64(n), 'f', -1, 32) case json.Number: return n.String() case bool: if n { return "true" } return "false" default: return fmt.Sprintf("%v", v) } } // Float64 coerces an interface value to a float64. func Float64(v any) (float64, bool) { if v == nil { return 0, false } switch n := v.(type) { case float64: return n, true case float32: return float64(n), true case int: return float64(n), true case int64: return float64(n), true case uint32: return float64(n), true case uint64: return float64(n), true case string: s := strings.TrimSpace(n) if s == "" { return 0, false } f, err := strconv.ParseFloat(s, 64) if err != nil { return 0, false } return f, true case json.Number: f, err := n.Float64() if err != nil { return 0, false } return f, true } return 0, false }