fix: align float parsing with strconv and harden helper functions#229
Conversation
ParseFloat64/ParseFloat32 diverged from strconv.ParseFloat in three ways:
digit-less inputs (".", "e5", "+.") returned 0 without an error, integer
parts larger than uint64 returned ErrRange although float64 can represent
them, and more than 16 fractional digits returned ErrRange. The parser now
collects digits into a single mantissa with a decimal exponent, fixing all
three cases while staying allocation-free.
Further improvements:
- ConvertToBytes: return 0 for negative sizes, support binary units
(42KiB = 43008), document decimal vs binary semantics
- GetMIME: case-insensitive extension lookup via internal ToLower,
avoiding the platform-dependent mime fallback for upper-case input
- Start/StopTimeStampUpdater: guard with a mutex to prevent double-close
panics and races on concurrent use
- ToString: handle error before fmt.Stringer, matching fmt precedence
- Trim/TrimLeft/TrimRight: correct doc comments (single byte cutset)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Re-measured on the same environment (Apple M2 Pro, darwin/arm64). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #229 +/- ##
==========================================
- Coverage 84.02% 83.94% -0.09%
==========================================
Files 14 14
Lines 1158 1177 +19
==========================================
+ Hits 973 988 +15
- Misses 154 156 +2
- Partials 31 33 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR brings several utility helpers in this repository closer to Go stdlib behavior (notably float parsing vs strconv.ParseFloat) and hardens a few frequently-used helpers, while updating published benchmark numbers.
Changes:
- Reworked
parseFloatto handle digit-less inputs as syntax errors and to better matchstrconvbehavior for large integer parts and long fractional parts. - Improved helper robustness: case-insensitive MIME lookups, binary-unit support + negative handling in
ConvertToBytes, safer timestamp updater start/stop, andToStringprecedence adjustments. - Updated README benchmark outputs to reflect newly re-measured results.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| time.go | Replaces sync.Once with a mutex/chan lifecycle to make timestamp updater start/stop safe for concurrent callers. |
| README.md | Refreshes benchmark output numbers. |
| parse.go | Updates float parsing to be more strconv-compatible (syntax handling, large integer parts, long fractional parts). |
| parse_test.go | Adjusts/extends float parsing expectations to match the new parseFloat behavior. |
| http.go | Makes extension lookup case-insensitive by normalizing keys before map lookup. |
| http_test.go | Adds coverage for upper-case extension inputs. |
| convert.go | Ensures error is handled before fmt.Stringer in ToString. |
| convert_test.go | Adds tests for ToString(error) behavior. |
| common.go | Enhances ConvertToBytes to reject negatives and support binary KiB-style units. |
| common_test.go | Adds tests for binary units, negative sizes, and strengthens UUIDv4 format validation. |
| byteseq.go | Corrects Trim* doc comments to clarify cutset is a single byte. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Warning Review limit reached
Next review available in: 49 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR updates ChangesUtility fixes and benchmark refresh
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant StartTimeStampUpdater
participant StopTimeStampUpdater
participant TickerGoroutine
Caller->>StartTimeStampUpdater: call
StartTimeStampUpdater->>StartTimeStampUpdater: lock updaterMu, check stopUpdater
StartTimeStampUpdater->>TickerGoroutine: start goroutine
Caller->>StopTimeStampUpdater: call
StopTimeStampUpdater->>StopTimeStampUpdater: lock updaterMu, close stopUpdater
TickerGoroutine->>StopTimeStampUpdater: close updaterDone
StopTimeStampUpdater->>StopTimeStampUpdater: clear channels to nil
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Clamping the parsed exponent to the 309/-325 sentinels before combining it with the mantissa exponent (exp10) corrupted results for long digit strings: "999...9e-390" (400 nines, true value ~1e10) came back as 1e75 because the parsed -390 was clamped to -325 and then shifted by +381. The parse loop now only saturates the exponent against int64 overflow and the clamp is applied to the combined exponent, which also keeps the int conversion for math.Pow10 safe on 32-bit platforms. Also skip the Pow10 scaling for a zero mantissa: 0 * Pow10(309) is NaN, which turned inputs like "0e400" into a spurious range error. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Fixes two real divergences between
ParseFloat64/ParseFloat32andstrconv.ParseFloat, plus several small hardening improvements across the package, and refreshes the README benchmarks.Float parsing (parse.go)
".","e5"and"+."now returnErrSyntaxinstead of0, nil"18446744073709551616") now parse correctly instead of returningErrRange; strconv parses these fineErrRange; excess digits are ignored, matching strconvImprovements
ConvertToBytes: returns 0 for negative sizes (previously"-5.0k"returned -5000 while"-5k"returned 0); supports binary units (42KiB= 43008, previously silently parsed as decimal 42000); doc comment now explains the decimal vs binary relation toByteSizeGetMIME: extension lookup is now case-insensitive via the internalToLower(no alloc for lower-case input), so upper-case extensions like"PNG"hit the internal table instead of the platform-dependentmimefallbackStartTimeStampUpdater/StopTimeStampUpdater: now safe for concurrent use; previously two parallel stops could panic on double-close and thesync.Oncereset raced with a concurrent startToString: directerrorcase beforefmt.Stringer(matching fmt precedence), avoiding the reflection fallbackTrim/TrimLeft/TrimRight: corrected doc comments; cutset is a single byte, not a character set as in the stdlib counterpartsDocs
Testing
-race: 483 tests passing🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
KiBandMiBwhen converting byte sizes.Bug Fixes
ToStringnow formats error values using their message text.Documentation