class Dry::Schema::TypesMerger::ValueMerger

@api private

def call

Other tags:
    Api: - private
def call
  handlers.fetch(op_class).call
end

def handle_or

Other tags:
    Api: - private
def handle_or
  old | new
end

def handle_ordered

Other tags:
    Api: - private
def handle_ordered
  return old if old == new
  unwrapped_old, old_rule = unwrap_type(old)
  unwrapped_new, new_rule = unwrap_type(new)
  type = merge_underlying_types(unwrapped_old, unwrapped_new)
  rule = [old_rule, new_rule].compact.reduce { op_class.new(_1, _2) }
  type = Dry::Types::Constrained.new(type, rule: rule) if rule
  type
end

def handlers

Other tags:
    Api: - private
def handlers
  @handlers ||=
    {
      Dry::Logic::Operations::Or => method(:handle_or),
      Dry::Logic::Operations::And => method(:handle_and),
      Dry::Logic::Operations::Implication => method(:handle_implication)
    }
end

def initialize(types_merger, op_class, old, new)

Other tags:
    Api: - private
def initialize(types_merger, op_class, old, new)
  @types_merger = types_merger
  @op_class = op_class
  @old = old
  @new = new
end

def merge_underlying_types(unwrapped_old, unwrapped_new)

Other tags:
    Api: - private
def merge_underlying_types(unwrapped_old, unwrapped_new)
  case [unwrapped_old, unwrapped_new]
  in Dry::Types::Schema, Dry::Types::Schema
    types_merger.type_registry["hash"].schema(
      types_merger.call(
        op_class,
        unwrapped_old.name_key_map,
        unwrapped_new.name_key_map
      )
    )
  in [Dry::Types::AnyClass, _] | [Dry::Types::Hash, Dry::Types::Schema]
    unwrapped_new
  in [Dry::Types::Hash, Dry::Types::Schema] | [_, Dry::Types::AnyClass]
    unwrapped_old
  else
    if unwrapped_old.primitive != unwrapped_new.primitive
      raise ArgumentError, <<~MESSAGE
        Can't merge types, unwrapped_old=#{unwrapped_old.inspect}, unwrapped_new=#{unwrapped_new.inspect}
      MESSAGE
    end
    unwrapped_old
  end
end

def unwrap_type(type)

Other tags:
    Api: - private
def unwrap_type(type)
  rules = []
  while type.is_a?(Dry::Types::Decorator)
    rules << type.rule if type.is_a?(Dry::Types::Constrained)
    if type.meta[:maybe] & type.respond_to?(:right)
      type = type.right
    else
      type = type.type
    end
  end
  [type, rules.reduce(:&)]
end