Skip to content

feat: implement strict merge option and update related tests#11

Merged
techouse merged 2 commits into
mainfrom
chore/more-upstream-fixes
May 22, 2026
Merged

feat: implement strict merge option and update related tests#11
techouse merged 2 commits into
mainfrom
chore/more-upstream-fixes

Conversation

@techouse
Copy link
Copy Markdown
Owner

@techouse techouse commented May 22, 2026

This pull request refactors how duplicate key handling is implemented during query string decoding. The main change is to ensure that bracketed array syntax (e.g., b[]=1&b[]=2) always uses the "combine" duplicate strategy, regardless of the global setting, while also making the duplicate handling logic more explicit and testable. Several helper functions are renamed or extended to accept the duplicate strategy as a parameter, and tests and documentation are updated accordingly.

Duplicate handling improvements:

  • Introduced the effective_duplicates_for_part function to select the correct duplicate handling strategy for each key, ensuring bracketed keys always use Duplicates::Combine even if the global option is different.
  • Updated all relevant insertion functions (e.g., insert_value, insert_occupied_value, insert_default_value) to take an explicit Duplicates parameter, and refactored their usage throughout the codebase. [1] [2] [3] [4] [5] [6]

Test and documentation updates:

  • Updated unit tests to use the new explicit duplicate strategy parameter, ensuring correct behavior for all duplicate handling strategies. [1] [2] [3] [4] [5] [6] [7]
  • Added new examples to the README.md demonstrating the behavior of duplicate handling for bracketed and legacy merge syntax.

Internal code cleanup:

  • Updated imports and function calls to use the new function names and signatures. [1] [2] [3]
  • Refactored code in process.rs to consistently use the new duplicate strategy logic and explicit parameters. [1] [2] [3] [4] [5] [6] [7]

These changes make the handling of duplicate keys more robust, predictable, and easier to maintain.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added configurable duplicate key handling with Last, First, and Combine strategies.
    • Added strict_merge option to enable legacy object/scalar merge behavior (defaults to strict mode).
  • Documentation

    • Extended README examples demonstrating duplicate-key handling and legacy merge behavior.

Review Change Stack

@techouse techouse requested a review from Copilot May 22, 2026 09:23
@techouse techouse self-assigned this May 22, 2026
@techouse techouse added the enhancement New feature or request label May 22, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Warning

Rate limit exceeded

@techouse has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 36 minutes and 19 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6adede59-311a-4cdd-9d02-aeedb6a6422d

📥 Commits

Reviewing files that changed from the base of the PR and between 8ba636b and 94bf559.

📒 Files selected for processing (1)
  • README.md
📝 Walkthrough

Walkthrough

This PR extends the query string decoder with two features: explicit handling of bracket-notation duplicate parameters (always combining them into arrays regardless of the Duplicates strategy) and a legacy merge mode (strict_merge option) that conditionally merges scalar/object conflicts rather than wrapping them into arrays.

Changes

Duplicate-Aware Bracket Parsing and Legacy Merge Behavior

Layer / File(s) Summary
DecodeOptions API: strict_merge flag
src/options/decode.rs
Added strict_merge: bool field (defaults true), with public getter strict_merge() and builder setter with_strict_merge(...) to control scalar/object merge conflict resolution.
Insert Helpers: Duplicate-aware refactoring
src/decode/accumulate/insert.rs, src/decode/accumulate/insert/tests.rs
Refactored insert_value, insert_occupied_value, and insert_default_value to accept explicit duplicates: Duplicates parameter; occupied insertions apply the policy (Combine, Last, First) directly; default-value insertions branch on storage type and policy. Tests updated to pass duplicate strategies explicitly.
Bracket-Suffix Override: effective_duplicates_for_part
src/decode/accumulate/process.rs
Introduced effective_duplicates_for_part helper that forces Duplicates::Combine when a parameter uses bracket-suffix syntax (e.g., b[]); integrated throughout accumulation paths (default, PreferConcrete fast path, custom part processing) so effective policy drives all insert/merge operations.
Bracket-Notation Test Coverage
src/decode/tests/duplicates.rs
Added tests verifying bracket-notation array parameters (b[]=...) combine into arrays regardless of duplicate strategy (First vs Last).
Legacy Merge Behavior: scalar/object fallback
src/merge.rs
When strict_merge is disabled, object/scalar merge conflicts are handled via legacy behavior: non-empty scalar strings extracted as keys are inserted into the object with boolean-true values; empty strings are skipped; unqualified non-empty strings fall back to array wrapping.
Merge Behavior Tests: strict vs legacy
src/merge/tests.rs
Added tests validating strict merge (wraps conflicts into arrays) and legacy merge (inserts scalar as object key or ignores empty values).
Documentation and Integration Tests
README.md, tests/comparison/js/case.js, tests/porting_ledger.md, tests/regressions.rs, tests/support/cases/node_parse.rs, tests/support/mod.rs
Updated README with examples of bracket-notation and legacy merge behavior; added Node.js parity test cases for bracket duplicates and merge modes; updated regression tests; integrated strict_merge option into JS comparison harness.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Bracketed arrays now combine with force,
Their duplicates merge on their course,
And when strict mode bows down,
Scalars wear object crowns,
Legacy blends with modern source!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description provides comprehensive details about duplicate handling improvements, test updates, and internal cleanup, but does not follow the provided template structure with sections like 'Fixes', 'Type of change', 'How Has This Been Tested', and 'Checklist'. Restructure the description to follow the template: add 'Fixes #(issue)' section, mark the type of change (New feature), describe how changes were tested, and complete the checklist items.
Docstring Coverage ⚠️ Warning Docstring coverage is 63.16% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main feature being implemented: adding a strict merge option and updating related tests.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/more-upstream-fixes

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented May 22, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 2 duplication

Metric Results
Duplication 2

View in Codacy

🟢 Coverage 93.42% diff coverage · -0.08% coverage variation

Metric Results
Coverage variation -0.08% coverage variation (-1.00%)
Diff coverage 93.42% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (9ccd566) 4997 4891 97.88%
Head commit (94bf559) 5053 (+56) 4942 (+51) 97.80% (-0.08%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#11) 76 71 93.42%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 22, 2026

Codecov Report

❌ Patch coverage is 93.42105% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.80%. Comparing base (9ccd566) to head (94bf559).

Files with missing lines Patch % Lines
src/merge.rs 81.48% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #11      +/-   ##
==========================================
- Coverage   97.87%   97.80%   -0.08%     
==========================================
  Files          37       37              
  Lines        4997     5053      +56     
==========================================
+ Hits         4891     4942      +51     
- Misses        106      111       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Around line 211-225: The README legacy-merge example violates the decode
contract by expecting Value::Bool(true); update the example so decode (called as
decode(..., &DecodeOptions::new().with_strict_merge(false))) only yields
permitted types — replace the Value::Bool(true) expectation with a String
variant (e.g., Value::String("").to_owned() or the appropriate string
representation your decoder emits for flags) so the asserted result for
legacy_merge.get("a") uses only Null, String, Array, or Object types.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6072467e-b9a8-4d84-bb19-cfa99e41b553

📥 Commits

Reviewing files that changed from the base of the PR and between 9ccd566 and 8ba636b.

📒 Files selected for processing (13)
  • README.md
  • src/decode/accumulate/insert.rs
  • src/decode/accumulate/insert/tests.rs
  • src/decode/accumulate/process.rs
  • src/decode/tests/duplicates.rs
  • src/merge.rs
  • src/merge/tests.rs
  • src/options/decode.rs
  • tests/comparison/js/case.js
  • tests/porting_ledger.md
  • tests/regressions.rs
  • tests/support/cases/node_parse.rs
  • tests/support/mod.rs

Comment thread README.md
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors decode-time duplicate handling and merge conflict behavior to better match Node qs, adding a strict_merge decode option and making per-key duplicate strategy selection explicit (notably forcing bracketed array syntax to always combine duplicates).

Changes:

  • Added DecodeOptions::strict_merge (default true) and threaded it into the merge pipeline to support legacy object/scalar conflict behavior when disabled.
  • Introduced per-part duplicate strategy selection during decode accumulation (bracketed [] keys force Duplicates::Combine) and updated insertion helpers to accept an explicit Duplicates.
  • Expanded Node-backed parity coverage and updated README examples to document bracketed-duplicate and legacy-merge behavior.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/support/mod.rs Passes strictMerge into the Node parity harness options JSON.
tests/support/cases/node_parse.rs Adds new Node parity cases for bracket-notation duplicates and strictMerge behavior.
tests/regressions.rs Locks in strict_merge default and builder toggling behavior.
tests/porting_ledger.md Updates the ledger to reflect ported duplicates + strictMerge parse coverage.
tests/comparison/js/case.js Normalizes strictMerge defaulting on the JS side for parity runs.
src/options/decode.rs Introduces the strict_merge option field + public getter/builder and default true.
src/merge/tests.rs Adds unit tests validating strict vs legacy merge behavior.
src/merge.rs Implements legacy merge handling when strict_merge is disabled (including boolean true key insertion).
src/decode/tests/duplicates.rs Adds regression tests ensuring bracket notation combines regardless of global duplicates strategy.
src/decode/accumulate/process.rs Selects “effective duplicates” per-part and threads explicit Duplicates through insertion paths.
src/decode/accumulate/insert/tests.rs Updates tests to use the new insertion helpers that accept explicit Duplicates.
src/decode/accumulate/insert.rs Adds *_with_duplicates insertion helpers and keeps old wrappers for default behavior.
README.md Adds examples for bracketed-duplicate behavior and legacy merge via strict_merge(false).

Comment thread src/decode/accumulate/process.rs
Comment thread README.md
@techouse techouse merged commit 4fdc8d3 into main May 22, 2026
20 of 22 checks passed
@techouse techouse deleted the chore/more-upstream-fixes branch May 22, 2026 09:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants