# frozen_string_literal: true module Dry module Types extend ::Dry::Core::ClassAttributes # @!attribute [r] namespace # @return [Container{String => Nominal}] defines :namespace namespace self # Base class for coercion errors raise by dry-types # class CoercionError < ::StandardError # @api private def self.handle(exception, meta: Undefined) if block_given? yield else raise new( exception.message, meta: meta, backtrace: exception.backtrace ) end end # Metadata associated with the error # # @return [Object] attr_reader :meta # @api private def initialize(message, meta: Undefined, backtrace: Undefined) unless message.is_a?(::String) raise ::ArgumentError, "message must be a string, #{message.class} given" end super(message) @meta = Undefined.default(meta, nil) set_backtrace(backtrace) unless Undefined.equal?(backtrace) end end # Collection of multiple errors # class MultipleError < CoercionError # @return [Array] attr_reader :errors # @param [Array] errors def initialize(errors) @errors = errors end # @return string def message errors.map(&:message).join(', ') end # @return [Array] def meta errors.map(&:meta) end end class SchemaError < CoercionError # @param [String,Symbol] key # @param [Object] value # @param [String, #to_s] result def initialize(key, value, result) super("#{value.inspect} (#{value.class}) has invalid type for :#{key} violates constraints (#{result} failed)") end end MapError = ::Class.new(CoercionError) SchemaKeyError = ::Class.new(CoercionError) private_constant(:SchemaKeyError) class MissingKeyError < SchemaKeyError # @return [Symbol] attr_reader :key # @param [String,Symbol] key def initialize(key) @key = key super("#{key.inspect} is missing in Hash input") end end class UnknownKeysError < SchemaKeyError # @return [Array] attr_reader :keys # @param [] keys def initialize(keys) @keys = keys super("unexpected keys #{keys.inspect} in Hash input") end end class ConstraintError < CoercionError # @return [String, #to_s] attr_reader :result # @return [Object] attr_reader :input # @param [String, #to_s] result # @param [Object] input def initialize(result, input) @result = result @input = input if result.is_a?(String) super(result) else super(to_s) end end # @return [String] def message "#{input.inspect} violates constraints (#{result} failed)" end alias_method :to_s, :message end end end