From 0cb820b90e9f584564d18dd06b834c0d3b0596e5 Mon Sep 17 00:00:00 2001 From: Linus Oleander Date: Thu, 16 Dec 2021 10:27:02 +0100 Subject: [PATCH] improve performence --- lib/remap/selector.rb | 10 -------- lib/remap/selector/all.rb | 18 +++++++------- lib/remap/selector/index.rb | 18 +++++++------- lib/remap/selector/key.rb | 18 +++++++------- .../remap/failures/each_failure_spec.rb | 11 +++++++-- spec/feature/remap/failures/embed_spec.rb | 16 +++++++++++-- spec/feature/remap/failures/index_map_spec.rb | 24 +++++++++++-------- .../remap/failures/map_all_selector_spec.rb | 5 ++-- .../feature/remap/failures/nested_map_spec.rb | 13 ++++------ spec/integration/remap/compiler_spec.rb | 4 ++-- spec/unit/remap/path/input_spec.rb | 4 ++-- spec/unit/remap/selector/index_spec.rb | 6 ++--- 12 files changed, 77 insertions(+), 70 deletions(-) diff --git a/lib/remap/selector.rb b/lib/remap/selector.rb index b71dcfbc8..955c08df4 100644 --- a/lib/remap/selector.rb +++ b/lib/remap/selector.rb @@ -4,9 +4,6 @@ module Remap # Defines how a path element, or selector # Specifies how a value is extracted from a state class Selector < Dry::Interface - defines :requirement, type: Types::Any.constrained(type: Dry::Types::Type) - requirement Types::Any - # Selects value from state, package it as a state and passes it to block # # @param state [State] @@ -20,12 +17,5 @@ class Selector < Dry::Interface def call(state) raise NotImplementedError, "#{self.class}#call not implemented" end - - private - - # @return [Dry::Types::Type] - def requirement - self.class.requirement - end end end diff --git a/lib/remap/selector/all.rb b/lib/remap/selector/all.rb index 2740d1b9c..8d1df9937 100644 --- a/lib/remap/selector/all.rb +++ b/lib/remap/selector/all.rb @@ -15,28 +15,28 @@ class Selector # end # result.fetch(:value) # => [Hash, Hash] class All < Concrete - requirement Types::Enumerable - # Iterates over state and passes each value to block # - # @param outer_state [State>] + # @param state [State>] # # @yieldparam [State] # @yieldreturn [State] # # @return [State] - def call(outer_state, &block) + def call(state, &block) unless block raise ArgumentError, "All selector requires an iteration block" end - outer_state.bind(quantifier: "*") do |enum, state| - requirement[enum] do - state.fatal!("Expected enumerable") - end + value = state.fetch(:value) do + return state + end - state.map(&block) + unless value.is_a?(Enumerable) + state.fatal!("Not an enumerator") end + + state.map(&block) end end end diff --git a/lib/remap/selector/index.rb b/lib/remap/selector/index.rb index 90a644394..07a47db94 100644 --- a/lib/remap/selector/index.rb +++ b/lib/remap/selector/index.rb @@ -20,8 +20,6 @@ class Index < Unit # @return [Integer] attribute :index, Integer - requirement Types::Array - # Selects the {#index}th element from state and passes it to block # # @param state [State>] @@ -35,17 +33,17 @@ def call(state, &block) raise ArgumentError, "The index selector requires an iteration block" end - state.bind(index: index) do |array, s| - requirement[array] do - s.fatal!("Expected an array") - end + array = state.fetch(:value) { return state } - element = array.fetch(index) do - s.ignore!("Index not found") - end + unless array.is_a?(Array) + state.fatal!("Expected an array got %s", array.class) + end - state.set(element, index: index).then(&block) + value = array.fetch(index) do + state.ignore!("Index [%s] (%s) not found", index, index.class) end + + state.set(value, index: index).then(&block) end end end diff --git a/lib/remap/selector/key.rb b/lib/remap/selector/key.rb index 7019d15dd..54343699e 100644 --- a/lib/remap/selector/key.rb +++ b/lib/remap/selector/key.rb @@ -17,8 +17,6 @@ class Key < Unit # @return [#hash attribute :key, Types::Key - requirement Types::Hash - # Selects {#key} from state and passes it to block # # @param state [State>] @@ -32,17 +30,17 @@ def call(state, &block) raise ArgumentError, "The key selector requires an iteration block" end - state.bind(key: key) do |hash, s| - requirement[hash] do - s.fatal!("Expected hash") - end + hash = state.fetch(:value) { return state } - value = hash.fetch(key) do - s.ignore!("Key not found") - end + unless hash.is_a?(Hash) + state.fatal!("Expected hash got %s", hash.class) + end - state.set(value, key: key).then(&block) + value = hash.fetch(key) do + state.ignore!("Key [%s] (%s) not found", key, key.class) end + + state.set(value, key: key).then(&block) end end end diff --git a/spec/feature/remap/failures/each_failure_spec.rb b/spec/feature/remap/failures/each_failure_spec.rb index 9cbbf9c0a..95d83d255 100644 --- a/spec/feature/remap/failures/each_failure_spec.rb +++ b/spec/feature/remap/failures/each_failure_spec.rb @@ -25,7 +25,8 @@ failures: contain_exactly( have_attributes( value: { does_not_match: "with John" }, - path: [:people, 0, :name] + reason: include("name"), + path: [:people, 0] ) ) ) @@ -43,7 +44,13 @@ expect { |b| mapper.call(input, &b) }.to yield_with_args( an_instance_of(Remap::Failure).and( have_attributes( - failures: contain_exactly(have_attributes(value: input, path: [:people])) + failures: contain_exactly( + have_attributes( + reason: include("people"), + value: input, + path: [] + ) + ) ) ) ) diff --git a/spec/feature/remap/failures/embed_spec.rb b/spec/feature/remap/failures/embed_spec.rb index 6889fdfe3..ce688215b 100644 --- a/spec/feature/remap/failures/embed_spec.rb +++ b/spec/feature/remap/failures/embed_spec.rb @@ -27,7 +27,13 @@ expect { |b| mapper.call(input, &b) }.to yield_with_args( an_instance_of(Remap::Failure).and( have_attributes( - failures: contain_exactly(have_attributes(value: input, path: [:name])) + failures: contain_exactly( + have_attributes( + reason: include("name"), + path: be_empty, + value: input + ) + ) ) ) ) @@ -41,7 +47,13 @@ expect { |b| mapper.call(input, &b) }.to yield_with_args( an_instance_of(Remap::Failure).and( have_attributes( - failures: contain_exactly(have_attributes(value: input, path: [:car])) + failures: contain_exactly( + have_attributes( + reason: include("car"), + path: be_empty, + value: input + ) + ) ) ) ) diff --git a/spec/feature/remap/failures/index_map_spec.rb b/spec/feature/remap/failures/index_map_spec.rb index 93fadd692..9ba509526 100644 --- a/spec/feature/remap/failures/index_map_spec.rb +++ b/spec/feature/remap/failures/index_map_spec.rb @@ -23,7 +23,8 @@ failures: contain_exactly( have_attributes( value: { not_a_match: "Lisa" }, - path: [:people, 1, :name] + reason: include("name"), + path: [:people, 1] ) ) ) @@ -41,7 +42,7 @@ expect { |b| mapper.call(input, &b) }.to yield_with_args( be_an_instance_of(Remap::Failure).and( have_attributes( - failures: contain_exactly(have_attributes(path: [:people, 1])) + failures: contain_exactly(have_attributes(path: [:people])) ) ) ) @@ -57,7 +58,13 @@ expect { |b| mapper.call(input, &b) }.to yield_with_args( an_instance_of(Remap::Failure).and( have_attributes( - failures: contain_exactly(have_attributes(value: input, path: [:people])) + failures: contain_exactly( + have_attributes( + reason: include("people"), + path: be_empty, + value: input + ) + ) ) ) ) @@ -65,20 +72,17 @@ end context "when key points to the wrong data type" do + let(:string) { "not a hash" } + let(:input) do - { people: [{ name: "John" }, "this is not a hash"] } + { people: [{ name: "John" }, string] } end it "raises an exception" do expect { mapper.call(input, &error) }.to raise_error( an_instance_of(Remap::Failure::Error).and( having_attributes( - failures: contain_exactly( - having_attributes( - value: "this is not a hash", - path: [:people, 1, :name] - ) - ) + failures: contain_exactly(having_attributes(path: [:people, 1], value: string)) ) ) ) diff --git a/spec/feature/remap/failures/map_all_selector_spec.rb b/spec/feature/remap/failures/map_all_selector_spec.rb index 64647946e..7599201b4 100644 --- a/spec/feature/remap/failures/map_all_selector_spec.rb +++ b/spec/feature/remap/failures/map_all_selector_spec.rb @@ -21,7 +21,8 @@ failures: contain_exactly( have_attributes( value: { does_not_match: "with John" }, - path: [:people, 0, :name] + reason: include("name"), + path: [:people, 0] ) ) ) @@ -39,7 +40,7 @@ expect { |b| mapper.call(input, &b) }.to yield_with_args( an_instance_of(Remap::Failure).and( have_attributes( - failures: contain_exactly(have_attributes(value: input, path: [:people])) + failures: contain_exactly(have_attributes(value: input, path: [])) ) ) ) diff --git a/spec/feature/remap/failures/nested_map_spec.rb b/spec/feature/remap/failures/nested_map_spec.rb index 6965b5f42..8594979a5 100644 --- a/spec/feature/remap/failures/nested_map_spec.rb +++ b/spec/feature/remap/failures/nested_map_spec.rb @@ -19,27 +19,24 @@ it "invokes block with failure" do expect { |b| mapper.call(input, &b) }.to yield_with_args( have_attributes( - failures: contain_exactly(have_attributes(value: { age: 50 }, path: [:person, :name])) + failures: contain_exactly(have_attributes(value: { age: 50 }, path: [:person], reason: include("name"))) ) ) end end context "when key points to the wrong data type" do + let(:string) { "not a hash" } + let(:input) do - { person: "hes 50 years old" } + { person: string } end it "raises an exception" do expect { mapper.call(input, &error) }.to raise_error( an_instance_of(Remap::Failure::Error).and( having_attributes( - failures: contain_exactly( - having_attributes( - value: "hes 50 years old", - path: [:person, :name] - ) - ) + failures: contain_exactly(having_attributes(path: [:person], value: string)) ) ) ) diff --git a/spec/integration/remap/compiler_spec.rb b/spec/integration/remap/compiler_spec.rb index f914f2e45..5bb68bc9b 100644 --- a/spec/integration/remap/compiler_spec.rb +++ b/spec/integration/remap/compiler_spec.rb @@ -109,7 +109,7 @@ end let(:attributes) do - { value: { mismatch: "John" }, path: [:person, :name] } + { value: { mismatch: "John" }, path: [:person], reason: include("name") } end end end @@ -137,7 +137,7 @@ end let(:attributes) do - { value: { mismatch: "John" }, path: [:name] } + { value: { mismatch: "John" }, path: [], reason: include("name") } end end end diff --git a/spec/unit/remap/path/input_spec.rb b/spec/unit/remap/path/input_spec.rb index 5ac8c40a8..6ecc9bbac 100644 --- a/spec/unit/remap/path/input_spec.rb +++ b/spec/unit/remap/path/input_spec.rb @@ -39,7 +39,7 @@ end let(:attributes) do - { value: input, path: selectors } + { value: input, path: be_empty, reason: include("key") } end end end @@ -164,7 +164,7 @@ end let(:attributes) do - { path: [1], value: input } + { path: [], value: input, reason: include("1") } end end end diff --git a/spec/unit/remap/selector/index_spec.rb b/spec/unit/remap/selector/index_spec.rb index ab96a5f90..0872fecc3 100644 --- a/spec/unit/remap/selector/index_spec.rb +++ b/spec/unit/remap/selector/index_spec.rb @@ -31,7 +31,7 @@ it_behaves_like "a fatal exception" do let(:attributes) do { - path: [index], + path: be_empty, value: input } end @@ -61,7 +61,7 @@ it_behaves_like "an ignored exception" do let(:attributes) do - { path: [index], value: input } + { path: [], value: input, reason: include("4") } end end end @@ -79,7 +79,7 @@ it_behaves_like "an ignored exception" do let(:attributes) do - { path: [index], value: input } + { path: [], value: input, reason: include("0") } end end end