From 95c0baf18d3b11d265ada0ab5c867b36ac65219a Mon Sep 17 00:00:00 2001 From: wuyangfan Date: Wed, 27 May 2026 00:33:31 +0800 Subject: [PATCH] fix: parse bare hex strings as uint64 Fixes #334 When ParseUint with base 0 fails, retry with base 16 if the string looks like a hexadecimal value (contains a-f/A-F). Co-authored-by: Cursor --- number.go | 34 ++++++++++++++++++++++++++++++---- number_test.go | 15 +++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/number.go b/number.go index a58dc4d..51e09ed 100644 --- a/number.go +++ b/number.go @@ -414,12 +414,38 @@ func parseInt[T integer](s string) (T, error) { } func parseUint[T unsigned](s string) (T, error) { - v, err := strconv.ParseUint(strings.TrimLeft(trimDecimal(s), "+"), 0, 0) - if err != nil { - return 0, err + s = strings.TrimLeft(trimDecimal(s), "+") + v, err := strconv.ParseUint(s, 0, 0) + if err == nil { + return T(v), nil + } + if isLikelyHexString(s) { + v, err = strconv.ParseUint(s, 16, 0) + if err == nil { + return T(v), nil + } } - return T(v), nil + return 0, err +} + +func isLikelyHexString(s string) bool { + if s == "" { + return false + } + hasLetter := false + for _, r := range s { + switch { + case r >= '0' && r <= '9': + case r >= 'a' && r <= 'f': + hasLetter = true + case r >= 'A' && r <= 'F': + hasLetter = true + default: + return false + } + } + return hasLetter } func parseFloat[T float](s string) (T, error) { diff --git a/number_test.go b/number_test.go index 9d84d18..8c62a34 100644 --- a/number_test.go +++ b/number_test.go @@ -390,6 +390,21 @@ func TestNumber(t *testing.T) { } } +func TestIssue334_HexStringToUint64(t *testing.T) { + c := qt.New(t) + + const hex = "882d5422d5fffff" + const want uint64 = 613286979481632767 + + c.Assert(cast.ToUint64(hex), qt.Equals, want) + + got, err := cast.ToUint64E(hex) + c.Assert(err, qt.IsNil) + c.Assert(got, qt.Equals, want) + + c.Assert(cast.ToUint64("0x"+hex), qt.Equals, want) +} + func BenchmarkNumber(b *testing.B) { type testCase struct { name string