Skip to content

Add opt-in ignoreWhitespace decoding for Base-16/32/64#22

Closed
dipu-bd wants to merge 3 commits into
masterfrom
claude/issue-20-ignore-whitespace
Closed

Add opt-in ignoreWhitespace decoding for Base-16/32/64#22
dipu-bd wants to merge 3 commits into
masterfrom
claude/issue-20-ignore-whitespace

Conversation

@dipu-bd

@dipu-bd dipu-bd commented Jul 22, 2026

Copy link
Copy Markdown
Member

Summary

Adds an opt-in ignoreWhitespace parameter (default false) to the public decode functions and their non-throwing counterparts:

  • fromHex / tryFromHex
  • fromBase32 / tryFromBase32
  • fromBase64 / tryFromBase64

When true, ASCII whitespace (space, \t, \n, \v, \f, \r) in the input is skipped instead of rejected, so line-wrapped payloads such as PEM and MIME decode without pre-processing. The default is false, so existing decode behavior is unchanged and byte-identical.

Design

Whitespace is stripped in the public functions via a shared internal helper, lib/src/core/whitespace.dart, rather than by adding a field to the exported AlphabetDecoder. Rationale:

  • The default path is byte-identical — the strip branch is skipped entirely, so there is no change to the hot decode loop.
  • No doubling of the static const codec instances (a decoder-level flag would need a relaxed twin of every Base-64/Base-32 variant).
  • No new public API surface beyond the bool parameters.

The helper returns a plain List<int> (never a Uint8List) so code units wider than a byte are preserved exactly and cannot be truncated into a valid character — guarding against the truncating-buffer failure mode.

Tests

test/whitespace_test.dart covers:

  • The stripWhitespace helper: each of the six whitespace characters removed, wide-code-unit preservation (0x141 survives, does not become 'A'), no-whitespace passthrough, all-whitespace → empty, and near-whitespace controls left intact.
  • Base-64: a differential check against dart:convert on a 64-column CRLF-wrapped PEM-style block, a known-answer vector, roundtrips with injected whitespace at every length 0..99, strict-still-rejects, and non-whitespace-invalid-still-throws.
  • Base-32 and Base-16: roundtrips with injected whitespace at every length, strict-still-rejects, and tryFrom* honouring the flag.

Checklist

  • dart format --output=none --set-exit-if-changed . — clean
  • dart analyze --fatal-infos — No issues found
  • dart test — 1359 pass on VM and Node
  • test_integration runs
  • No new dependencies; no SDK floor change
  • CHANGELOG (_next_), README recipe + example/whitespace_example.dart updated

Generated by Claude Code

Add an `ignoreWhitespace` parameter (default `false`) to `fromHex`,
`fromBase32`, `fromBase64`, and their `tryFrom` counterparts. When `true`,
ASCII whitespace (space, tab, line feed, vertical tab, form feed, carriage
return) is skipped before decoding, so line-wrapped PEM/MIME payloads decode
without pre-processing. The default path is unchanged and byte-identical.

Stripping is done by a shared internal `stripWhitespace` helper that returns a
plain `List<int>` so wide code units are preserved and cannot be truncated into
valid characters.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015JBrb6sTw7442YbCzkxrxu
@dipu-bd
dipu-bd force-pushed the claude/issue-20-ignore-whitespace branch from d40c0a4 to cd43ee3 Compare July 22, 2026 18:37
claude added 2 commits July 22, 2026 18:52
Count whitespace in a first pass and return the input unchanged when there
is none, so passing `ignoreWhitespace: true` over an unfolded payload copies
nothing. When whitespace is present, allocate a single exactly-sized buffer
instead of a full-length buffer followed by a `sublist`. Output is unchanged,
and the buffer stays a plain `List<int>` so wide code units are not truncated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YZrBRgz54K7qhuKKxebaxu
Instead of pre-stripping whitespace into an intermediate list, `fromBase32`
and `fromBase64` now pass `ignoreWhitespace` straight to the decoder. The
specialized decoders keep their fixed-group fast paths unchanged for the
strict default and defer only the whitespace case to the generic
`AlphabetDecoder` accumulator, which skips ASCII whitespace in a single pass
with no intermediate buffer. Output is unchanged, and wide code units are
still rejected rather than truncated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YZrBRgz54K7qhuKKxebaxu
@dipu-bd

dipu-bd commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

not good enough

@dipu-bd dipu-bd closed this Jul 22, 2026
@dipu-bd
dipu-bd deleted the claude/issue-20-ignore-whitespace branch July 22, 2026 19:15
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
lib/src/base16.dart 100.00% <100.00%> (ø)
lib/src/base32.dart 100.00% <100.00%> (ø)
lib/src/base64.dart 100.00% <100.00%> (ø)
lib/src/codecs/base32.dart 100.00% <100.00%> (ø)
lib/src/codecs/base64.dart 100.00% <100.00%> (ø)
lib/src/core/alphabet.dart 100.00% <100.00%> (ø)
lib/src/core/whitespace.dart 100.00% <100.00%> (ø)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants