Add new NumberStyles option to stop parsing on invalid characte#130210
Open
tannergooding wants to merge 4 commits into
Open
Add new NumberStyles option to stop parsing on invalid characte#130210tannergooding wants to merge 4 commits into
tannergooding wants to merge 4 commits into
Conversation
) ## Description Added comprehensive test coverage for the `NumberStyles.AllowTrailingInvalidCharacters` mode across all numeric types. This style allows Parse/TryParse APIs to parse up to the first invalid character and return the number of characters consumed, similar to Utf8Parser behavior. ## Changes **Test Coverage Added:** - All integer types: Int32, Int64, Int16, SByte, UInt32, UInt64, UInt16, Byte - All floating point types: Double, Single, Half, Decimal - Arbitrary precision: BigInteger **Test Scenarios:** - Basic parsing with trailing invalid characters (e.g., `"123abc"` → value: 123, consumed: 3) - Combined with NumberStyles: Integer, HexNumber, BinaryNumber, Currency, Float - Edge cases: max/min values, empty strings, overflow, special values (Infinity, NaN) - All API surface: string, ReadOnlySpan\<char\>, ReadOnlySpan\<byte\> overloads - Both success and failure paths with proper validation of characters/bytes consumed Tests follow existing patterns in System.Runtime.Tests and mirror the ValidateParser approach used in System.Memory Utf8Parser tests. ## Testing Tests build successfully. Full baseline build required for test execution would exceed time constraints. <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: tannergooding <10487869+tannergooding@users.noreply.github.com>
- Reset elementsConsumed to 0 on the integer and decimal overflow paths so a failed parse never reports a nonzero consumed count. - Restrict floating-point special-value (Infinity/NaN) matching to the non-hex path and honor AllowTrailingInvalidCharacters via prefix matching, reporting leading whitespace plus the matched symbol as consumed. - Apply the same special-value consistency fix to the IEEE-754 decimal path (Decimal32/64/128) and share the matching logic via a helper. - Add AllowTrailingInvalidCharacters to the hex and binary allowed styles. - Remove redundant string null guards from TryParse overloads and rely on ReadOnlySpan null-tolerance; relax internal asserts to tolerate empty spans. - Restore the UTF-8 BOM inadvertently stripped from Double/Single and the IEEE-754 decimal source files. - Add and correct AllowTrailingInvalidCharacters tests, using CultureInfo.InvariantCulture for culture-dependent special values. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds support for parsing numeric prefixes (stopping at the first invalid character) via a new NumberStyles.AllowTrailingInvalidCharacters flag, and introduces TryParse overloads that report how many UTF-16 chars / UTF-8 bytes were consumed. The change updates the CoreLib parsing pipelines and extends coverage across built-in numeric types plus BigInteger and Complex, with broad new tests.
Changes:
- Add
NumberStyles.AllowTrailingInvalidCharactersand plumb “consumed count” (charsConsumed/bytesConsumed) through numeric parsing implementations. - Add/override new
TryParse(..., out int consumed)APIs across numeric types (CoreLib, Numerics) and update ref assemblies accordingly. - Add extensive tests validating consumed counts and behavior for trailing invalid characters (including UTF-8 overloads in many cases).
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt64Tests.cs | Adds tests for AllowTrailingInvalidCharacters including consumed-count validation. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt32Tests.cs | Adds tests for AllowTrailingInvalidCharacters including consumed-count validation. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt16Tests.cs | Adds tests for AllowTrailingInvalidCharacters including UTF-8 cases. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs | Adds tests for float parsing with trailing invalid characters and consumed counts. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SByteTests.cs | Adds tests for sbyte parsing with trailing invalid characters and consumed counts. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int64Tests.cs | Adds tests for long parsing with trailing invalid characters and consumed counts. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int32Tests.cs | Adds broad tests for int parsing behavior/consumption across styles/cultures. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int16Tests.cs | Adds tests for short parsing with trailing invalid characters and consumed counts. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/HalfTests.cs | Adds tests for Half parsing with trailing invalid characters and consumed counts. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs | Adds tests for double parsing with trailing invalid characters and consumed counts. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DecimalTests.cs | Adds tests for decimal parsing with trailing invalid characters and consumed counts. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Decimal64Tests.cs | Adds tests for Decimal64 parsing with trailing invalid characters and consumed counts. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Decimal32Tests.cs | Adds tests for Decimal32 parsing with trailing invalid characters and consumed counts. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Decimal128Tests.cs | Adds tests for Decimal128 parsing with trailing invalid characters and consumed counts. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ByteTests.cs | Adds tests for byte parsing with trailing invalid characters and consumed counts. |
| src/libraries/System.Runtime/ref/System.Runtime.cs | Updates public surface: new NumberStyles flag + new TryParse(..., out int consumed) APIs (including on primitives and INumberBase<TSelf>). |
| src/libraries/System.Runtime.Numerics/tests/ComplexTests.cs | Adds tests validating Complex.TryParse consumed-count behavior under the new flag. |
| src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs | Adds tests validating BigInteger.TryParse consumed-count behavior under the new flag. |
| src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs | Extends Complex.TryParse to support consumed counts and trailing invalid characters after the closing bracket. |
| src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs | Adds consumed-count TryParse overloads; wires into updated Number.TryParseBigInteger parsing entry points. |
| src/libraries/System.Runtime.Numerics/src/System/Number.Polyfill.cs | Changes whitespace helper to report how many elements were consumed (for generic UTF parsing). |
| src/libraries/System.Runtime.Numerics/src/System/Number.BigInteger.cs | Adds AllowTrailingInvalidCharacters support to BigInteger parsing (including hex/binary) and tracks consumed counts. |
| src/libraries/System.Runtime.Numerics/src/Resources/Strings.resx | Updates error string for invalid hex/binary style combinations to include the new flag. |
| src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs | Updates Numerics ref surface for BigInteger/Complex new TryParse(..., out int consumed) overloads. |
| src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs | Updates ref surface for NFloat new TryParse(..., out int consumed) overloads. |
| src/libraries/System.Private.CoreLib/src/System/Version.cs | Updates to new TryParseBinaryIntegerStyle(..., out int consumed) signature. |
| src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs | Adds TryParse(..., out int consumed) overloads for nuint. |
| src/libraries/System.Private.CoreLib/src/System/UInt64.cs | Adds TryParse(..., out int consumed) overloads and threads through new parsing entry points. |
| src/libraries/System.Private.CoreLib/src/System/UInt32.cs | Adds TryParse(..., out int consumed) overloads and threads through new parsing entry points. |
| src/libraries/System.Private.CoreLib/src/System/UInt16.cs | Adds TryParse(..., out int consumed) overloads and threads through new parsing entry points. |
| src/libraries/System.Private.CoreLib/src/System/UInt128.cs | Adds TryParse(..., out int consumed) overloads and threads through new parsing entry points. |
| src/libraries/System.Private.CoreLib/src/System/Single.cs | Adds TryParse(..., out int consumed) overloads; updates float parser callsites to new signature. |
| src/libraries/System.Private.CoreLib/src/System/SByte.cs | Adds TryParse(..., out int consumed) overloads and threads through new parsing entry points. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs | Adds TryParse(..., out int consumed) overloads for NFloat. |
| src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs | Adds DIM overloads TryParse(..., out int consumed) for string/span/utf8. |
| src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal64.cs | Adds TryParse(..., out int consumed) overloads; updates decimal IEEE754 parser calls. |
| src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal32.cs | Adds TryParse(..., out int consumed) overloads; updates decimal IEEE754 parser calls. |
| src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal128.cs | Adds TryParse(..., out int consumed) overloads; updates decimal IEEE754 parser calls. |
| src/libraries/System.Private.CoreLib/src/System/Numerics/BFloat16.cs | Adds TryParse(..., out int consumed) overloads; updates float parser calls. |
| src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs | Core parsing changes: plumb elementsConsumed through integer/float/decimal parsing and implement stop-on-invalid behavior. |
| src/libraries/System.Private.CoreLib/src/System/IntPtr.cs | Adds TryParse(..., out int consumed) overloads for nint. |
| src/libraries/System.Private.CoreLib/src/System/Int64.cs | Adds TryParse(..., out int consumed) overloads and threads through new parsing entry points. |
| src/libraries/System.Private.CoreLib/src/System/Int32.cs | Adds TryParse(..., out int consumed) overloads and threads through new parsing entry points. |
| src/libraries/System.Private.CoreLib/src/System/Int16.cs | Adds TryParse(..., out int consumed) overloads and threads through new parsing entry points. |
| src/libraries/System.Private.CoreLib/src/System/Int128.cs | Adds TryParse(..., out int consumed) overloads and threads through new parsing entry points. |
| src/libraries/System.Private.CoreLib/src/System/Half.cs | Adds TryParse(..., out int consumed) overloads; updates float parser calls. |
| src/libraries/System.Private.CoreLib/src/System/Guid.cs | Updates GUID parsing helper callsite for new hex/binary parse entry point signature. |
| src/libraries/System.Private.CoreLib/src/System/Globalization/NumberStyles.cs | Adds AllowTrailingInvalidCharacters flag to NumberStyles. |
| src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs | Updates style validation to allow AllowTrailingInvalidCharacters in hex/binary style combinations. |
| src/libraries/System.Private.CoreLib/src/System/Enum.cs | Updates enum parsing numeric path to new TryParseBinaryIntegerStyle(..., out int consumed) signature. |
| src/libraries/System.Private.CoreLib/src/System/Double.cs | Adds TryParse(..., out int consumed) overloads; updates float parser calls. |
| src/libraries/System.Private.CoreLib/src/System/Decimal.cs | Adds TryParse(..., out int consumed) overloads for decimal (and wires into new parsing entry points). |
| src/libraries/System.Private.CoreLib/src/System/Char.cs | Adds explicit INumberBase<char>.TryParse(..., out int consumed) implementations. |
| src/libraries/System.Private.CoreLib/src/System/Byte.cs | Adds TryParse(..., out int consumed) overloads and threads through new parsing entry points. |
| src/libraries/System.Private.CoreLib/src/Resources/Strings.resx | Updates invalid-hex/binary style error text to include the new flag. |
| src/libraries/Common/src/System/Number.Parsing.Common.cs | Common parsing changes: return elementsConsumed from TryStringToNumber / core scanner and support early-stop behavior. |
Copilot's findings
- Files reviewed: 56/56 changed files
- Comments generated: 5
…acters - Decimal.cs: the new consumed-count TryParse overloads now use ValidateParseStyleDecimal instead of ValidateParseStyleFloatingPoint, matching the rest of decimal parsing (which rejects hex/binary specifiers). - INumberBase.cs: the default consumed-count TryParse implementations no longer strip NumberStyles.AllowTrailingInvalidCharacters before delegating. Per the approved design, the style is passed through unmodified so a type that does not understand the flag throws as expected, rather than silently succeeding with a masked style. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This was referenced Jul 5, 2026
Comment on lines
+281
to
+282
| // including trailing nulls (zeros). Otherwise, for compatibility we still need to | ||
| // process any trailing nulls that exist and report them as having been consumed. |
Member
There was a problem hiding this comment.
The comment seems wrong here. Trailing nulls aren't incrementing index/elementsConsumed so they aren't being counted as consumed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a continuation of #123944, now that I had a chance to finish getting copilot to respond to the feedback, which was namely just tests. The original commit (product code) is still the original which was done by hand.
This resolves #87171