From dbe9540faa55064116b178635acf04769f0bb62e Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 3 Aug 2026 23:21:49 +1200 Subject: [PATCH] Support custom form data results. Assisted-By: devx/e76b566a-41cd-407d-a2fd-c5b79c88879d --- lib/protocol/url/form_data/parser.rb | 13 ++++++++----- releases.md | 4 ++++ test/protocol/url/form_data/parser.rb | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/protocol/url/form_data/parser.rb b/lib/protocol/url/form_data/parser.rb index 3b1db26..0ba9ea3 100644 --- a/lib/protocol/url/form_data/parser.rb +++ b/lib/protocol/url/form_data/parser.rb @@ -34,17 +34,16 @@ def initialize(maximum_total_size: MAXIMUM_TOTAL_SIZE, maximum_pair_count: MAXIM # When a block is given, each decoded value is passed through the block before assignment. The value returned by the block is assigned to the result. # # @parameter body [Object] A readable body which yields chunks from `#read`. + # @parameter result [Object] The result to populate. It must support `#add` and `#to_h`. # @yields {|name, value| ...} Each decoded form pair before assignment. # @returns [Hash] The nested form data. - def parse(body) - nested = Nested.new(maximum_depth: @maximum_depth) - + def parse(body, result = make_result) each(body) do |name, value| value = yield(name, value) if block_given? - nested.add(name, value) + result.add(name, value) end - return nested.to_h + return result.to_h end # Incrementally enumerate URL-encoded form data as ordered name/value pairs. @@ -88,6 +87,10 @@ def each(body) private + def make_result + return Nested.new(maximum_depth: @maximum_depth) + end + def yield_pair(assignment) name, value = assignment.split("=", 2) diff --git a/releases.md b/releases.md index 2197bf3..8b847aa 100644 --- a/releases.md +++ b/releases.md @@ -1,5 +1,9 @@ # Releases +## Unreleased + + - Allow `Protocol::URL::FormData::Parser#parse` to populate a supplied result object. + ## v0.6.0 - Add `Protocol::URL::FormData::Parser` for incremental, limited parsing of `application/x-www-form-urlencoded` form data. diff --git a/test/protocol/url/form_data/parser.rb b/test/protocol/url/form_data/parser.rb index 83452fe..e3ace5a 100644 --- a/test/protocol/url/form_data/parser.rb +++ b/test/protocol/url/form_data/parser.rb @@ -43,6 +43,22 @@ def read } end + it "parses form data into a supplied result" do + result = Struct.new(:pairs) do + def add(name, value) + pairs << [name, value] + end + + def to_h + return pairs.to_h + end + end.new([]) + + parameters = parser.parse(StringIO.new("name=Samuel"), result) + + expect(parameters).to be == {"name" => "Samuel"} + end + it "distinguishes absent and empty values" do parameters = parser.parse(StringIO.new("absent&empty="))