212 lines
4.2 KiB
Ruby
212 lines
4.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'dry/core/deprecations'
|
|
require 'dry/types/builder'
|
|
require 'dry/types/result'
|
|
require 'dry/types/options'
|
|
require 'dry/types/meta'
|
|
|
|
module Dry
|
|
module Types
|
|
# Nominal types define a primitive class and do not apply any constructors or constraints
|
|
#
|
|
# Use these types for annotations and the base for building more complex types on top of them.
|
|
#
|
|
# @api public
|
|
class Nominal
|
|
include Type
|
|
include Options
|
|
include Meta
|
|
include Builder
|
|
include Printable
|
|
include Dry::Equalizer(:primitive, :options, :meta, inspect: false)
|
|
|
|
# @return [Class]
|
|
attr_reader :primitive
|
|
|
|
# @param [Class] primitive
|
|
#
|
|
# @return [Type]
|
|
#
|
|
# @api private
|
|
def self.[](primitive)
|
|
if primitive == ::Array
|
|
Types::Array
|
|
elsif primitive == ::Hash
|
|
Types::Hash
|
|
else
|
|
self
|
|
end
|
|
end
|
|
|
|
ALWAYS = proc { true }
|
|
|
|
# @param [Type,Class] primitive
|
|
# @param [Hash] options
|
|
#
|
|
# @api private
|
|
def initialize(primitive, **options)
|
|
super
|
|
@primitive = primitive
|
|
freeze
|
|
end
|
|
|
|
# @return [String]
|
|
#
|
|
# @api public
|
|
def name
|
|
primitive.name
|
|
end
|
|
|
|
# @return [false]
|
|
#
|
|
# @api public
|
|
def default?
|
|
false
|
|
end
|
|
|
|
# @return [false]
|
|
#
|
|
# @api public
|
|
def constrained?
|
|
false
|
|
end
|
|
|
|
# @return [false]
|
|
#
|
|
# @api public
|
|
def optional?
|
|
false
|
|
end
|
|
|
|
# @param [BasicObject] input
|
|
#
|
|
# @return [BasicObject]
|
|
#
|
|
# @api private
|
|
def call_unsafe(input)
|
|
input
|
|
end
|
|
|
|
# @param [BasicObject] input
|
|
#
|
|
# @return [BasicObject]
|
|
#
|
|
# @api private
|
|
def call_safe(input)
|
|
input
|
|
end
|
|
|
|
# @param [Object] input
|
|
# @param [#call,nil] block
|
|
#
|
|
# @yieldparam [Failure] failure
|
|
# @yieldreturn [Result]
|
|
#
|
|
# @return [Result,Logic::Result] when a block is not provided
|
|
# @return [nil] otherwise
|
|
#
|
|
# @api public
|
|
def try(input)
|
|
success(input)
|
|
end
|
|
|
|
# @param (see Dry::Types::Success#initialize)
|
|
#
|
|
# @return [Result::Success]
|
|
#
|
|
# @api public
|
|
def success(input)
|
|
Result::Success.new(input)
|
|
end
|
|
|
|
# @param (see Failure#initialize)
|
|
#
|
|
# @return [Result::Failure]
|
|
#
|
|
# @api public
|
|
def failure(input, error)
|
|
unless error.is_a?(CoercionError)
|
|
raise ArgumentError, "error must be a CoercionError"
|
|
end
|
|
Result::Failure.new(input, error)
|
|
end
|
|
|
|
# Checks whether value is of a #primitive class
|
|
#
|
|
# @param [Object] value
|
|
#
|
|
# @return [Boolean]
|
|
#
|
|
# @api public
|
|
def primitive?(value)
|
|
value.is_a?(primitive)
|
|
end
|
|
|
|
# @api private
|
|
def coerce(input, &_block)
|
|
if primitive?(input)
|
|
input
|
|
elsif block_given?
|
|
yield
|
|
else
|
|
raise CoercionError, "#{input.inspect} must be an instance of #{primitive}"
|
|
end
|
|
end
|
|
|
|
# @api private
|
|
def try_coerce(input)
|
|
result = success(input)
|
|
|
|
coerce(input) do
|
|
result = failure(
|
|
input,
|
|
CoercionError.new("#{input.inspect} must be an instance of #{primitive}")
|
|
)
|
|
end
|
|
|
|
if block_given?
|
|
yield(result)
|
|
else
|
|
result
|
|
end
|
|
end
|
|
|
|
# Return AST representation of a type nominal
|
|
#
|
|
# @return [Array]
|
|
#
|
|
# @api public
|
|
def to_ast(meta: true)
|
|
[:nominal, [primitive, meta ? self.meta : EMPTY_HASH]]
|
|
end
|
|
|
|
# Return self. Nominal types are lax by definition
|
|
#
|
|
# @return [Nominal]
|
|
#
|
|
# @api public
|
|
def lax
|
|
self
|
|
end
|
|
|
|
# Wrap the type with a proc
|
|
#
|
|
# @return [Proc]
|
|
#
|
|
# @api public
|
|
def to_proc
|
|
ALWAYS
|
|
end
|
|
end
|
|
|
|
extend Dry::Core::Deprecations[:'dry-types']
|
|
Definition = Nominal
|
|
deprecate_constant(:Definition, message: "Nominal")
|
|
end
|
|
end
|
|
|
|
require 'dry/types/array'
|
|
require 'dry/types/hash'
|
|
require 'dry/types/map'
|