module JSI
module Util::Hashlike
SAFE_KEY_ONLY_METHODS = %w(each_key empty? has_key? include? key? keys length member? size).map(&:freeze).freeze
SAFE_KEY_VALUE_METHODS = %w(< <= > >= any? assoc compact dig each_pair each_value fetch fetch_values has_value? invert key merge rassoc reject select to_h to_proc transform_values value? values values_at).map(&:freeze).freeze
DESTRUCTIVE_METHODS = %w(clear delete delete_if keep_if reject! replace select! shift).map(&:freeze).freeze
safe_modified_copy_methods = %w(compact)
safe_kv_block_modified_copy_methods = %w(select reject)
SAFE_METHODS = SAFE_KEY_ONLY_METHODS | SAFE_KEY_VALUE_METHODS
custom_methods = %w(merge) safe_to_hash_methods = SAFE_METHODS -
safe_modified_copy_methods -
safe_kv_block_modified_copy_methods -
custom_methods
safe_to_hash_methods.each do |method_name|
if Util::LAST_ARGUMENT_AS_KEYWORD_PARAMETERS
define_method(method_name) { |*a, &b| to_hash.public_send(method_name, *a, &b) }
else
define_method(method_name) { |*a, **kw, &b| to_hash.public_send(method_name, *a, **kw, &b) }
end
end
safe_modified_copy_methods.each do |method_name|
if Util::LAST_ARGUMENT_AS_KEYWORD_PARAMETERS
define_method(method_name) do |*a, &b|
jsi_modified_copy do |object_to_modify|
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_hash
responsive_object.public_send(method_name, *a, &b)
end
end
else
define_method(method_name) do |*a, **kw, &b|
jsi_modified_copy do |object_to_modify|
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_hash
responsive_object.public_send(method_name, *a, **kw, &b)
end
end
end
end
safe_kv_block_modified_copy_methods.each do |method_name|
define_method(method_name) do |**kw, &b|
jsi_modified_copy do |object_to_modify|
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_hash
responsive_object.public_send(method_name) do |k, _v|
b.call(k, self[k, **kw])
end
end
end
end
def update(other, &block)
unless other.respond_to?(:to_hash)
raise(TypeError, "cannot update with argument that does not respond to #to_hash: #{other.pretty_inspect.chomp}")
end
other.to_hash.each_pair do |key, value|
if block && key?(key)
value = yield(key, self[key], value)
end
self[key] = value
end
self
end
alias_method :merge!, :update
def merge(other, &block)
jsi_modified_copy do |instance|
instance.merge(other.is_a?(Base) ? other.jsi_node_content : other, &block)
end
end
def inspect
object_group_str = (respond_to?(:jsi_object_group_text, true) ? jsi_object_group_text : [self.class]).join(' ')
-"\#{<#{object_group_str}>#{map { |k, v| " #{k.inspect} => #{v.inspect}" }.join(',')}}"
end
alias_method :to_s, :inspect
def pretty_print(q)
object_group_str = (respond_to?(:jsi_object_group_text, true) ? jsi_object_group_text : [self.class]).join(' ')
q.text "\#{<#{object_group_str}>"
q.group_sub {
q.nest(2) {
q.breakable ' ' if !empty?
q.seplist(self, nil, :each_pair) { |k, v|
q.group {
q.pp k
q.text ' => '
q.pp v
}
}
}
}
q.breakable '' if !empty?
q.text '}'
end
end
module Util::Arraylike
SAFE_INDEX_ONLY_METHODS = %w(each_index empty? length size).map(&:freeze).freeze
SAFE_INDEX_ELEMENT_METHODS = %w(| & * + - <=> abbrev at bsearch bsearch_index combination compact count cycle dig drop drop_while fetch find_index first include? index join last pack permutation product reject repeated_combination repeated_permutation reverse reverse_each rindex rotate sample select shelljoin shuffle slice sort take take_while transpose uniq values_at zip).map(&:freeze).freeze
DESTRUCTIVE_METHODS = %w(<< clear collect! compact! concat delete delete_at delete_if fill flatten! insert keep_if map! pop push reject! replace reverse! rotate! select! shift shuffle! slice! sort! sort_by! uniq! unshift).map(&:freeze).freeze
safe_modified_copy_methods = %w(compact)
safe_el_block_methods = %w(reject select)
SAFE_METHODS = SAFE_INDEX_ONLY_METHODS | SAFE_INDEX_ELEMENT_METHODS
safe_to_ary_methods = SAFE_METHODS - safe_modified_copy_methods - safe_el_block_methods
safe_to_ary_methods.each do |method_name|
if Util::LAST_ARGUMENT_AS_KEYWORD_PARAMETERS
define_method(method_name) { |*a, &b| to_ary.public_send(method_name, *a, &b) }
else
define_method(method_name) { |*a, **kw, &b| to_ary.public_send(method_name, *a, **kw, &b) }
end
end
safe_modified_copy_methods.each do |method_name|
if Util::LAST_ARGUMENT_AS_KEYWORD_PARAMETERS
define_method(method_name) do |*a, &b|
jsi_modified_copy do |object_to_modify|
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_ary
responsive_object.public_send(method_name, *a, &b)
end
end
else
define_method(method_name) do |*a, **kw, &b|
jsi_modified_copy do |object_to_modify|
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_ary
responsive_object.public_send(method_name, *a, **kw, &b)
end
end
end
end
safe_el_block_methods.each do |method_name|
define_method(method_name) do |**kw, &b|
jsi_modified_copy do |object_to_modify|
i = 0
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_ary
responsive_object.public_send(method_name) do |_e|
b.call(self[i, **kw]).tap { i += 1 }
end
end
end
end
def assoc(obj)
detect { |e| e.respond_to?(:to_ary) and e[0] == obj }
end
def rassoc(obj)
detect { |e| e.respond_to?(:to_ary) and e[1] == obj }
end
def inspect
object_group_str = (respond_to?(:jsi_object_group_text, true) ? jsi_object_group_text : [self.class]).join(' ')
-"\#[<#{object_group_str}>#{map { |e| ' ' + e.inspect }.join(',')}]"
end
alias_method :to_s, :inspect
def pretty_print(q)
object_group_str = (respond_to?(:jsi_object_group_text, true) ? jsi_object_group_text : [self.class]).join(' ')
q.text "\#[<#{object_group_str}>"
q.group_sub {
q.nest(2) {
q.breakable ' ' if !empty?
q.seplist(self, nil, :each) { |e|
q.pp e
}
}
}
q.breakable '' if !empty?
q.text ']'
end
end
end