File: builder.rb

package info (click to toggle)
ruby-dry-types 1.2.2-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 504 kB
  • sloc: ruby: 3,059; makefile: 4
file content (140 lines) | stat: -rw-r--r-- 3,433 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# frozen_string_literal: true

require 'dry/core/deprecations'

module Dry
  module Types
    # Common API for building types and composition
    #
    # @api public
    module Builder
      include Dry::Core::Constants

      # @return [Class]
      #
      # @api private
      def constrained_type
        Constrained
      end

      # @return [Class]
      #
      # @api private
      def constructor_type
        Constructor
      end

      # Compose two types into a Sum type
      #
      # @param [Type] other
      #
      # @return [Sum, Sum::Constrained]
      #
      # @api private
      def |(other)
        klass = constrained? && other.constrained? ? Sum::Constrained : Sum
        klass.new(self, other)
      end

      # Turn a type into an optional type
      #
      # @return [Sum]
      #
      # @api public
      def optional
        Types['strict.nil'] | self
      end

      # Turn a type into a constrained type
      #
      # @param [Hash] options constraining rule (see {Types.Rule})
      #
      # @return [Constrained]
      #
      # @api public
      def constrained(options)
        constrained_type.new(self, rule: Types.Rule(options))
      end

      # Turn a type into a type with a default value
      #
      # @param [Object] input
      # @param [Hash] options
      # @param [#call,nil] block
      #
      # @raise [ConstraintError]
      #
      # @return [Default]
      #
      # @api public
      def default(input = Undefined, options = EMPTY_HASH, &block)
        unless input.frozen? || options[:shared]
          where = Dry::Core::Deprecations::STACK.()
          Dry::Core::Deprecations.warn(
            "#{input.inspect} is mutable."\
            ' Be careful: types will return the same instance of the default'\
            ' value every time. Call `.freeze` when setting the default'\
            ' or pass `shared: true` to discard this warning.'\
            "\n#{where}",
            tag: :'dry-types'
          )
        end

        value = input.equal?(Undefined) ? block : input

        if value.respond_to?(:call) || valid?(value)
          Default[value].new(self, value)
        else
          raise ConstraintError.new("default value #{value.inspect} violates constraints", value)
        end
      end

      # Define an enum on top of the existing type
      #
      # @param [Array] values
      #
      # @return [Enum]
      #
      # @api public
      def enum(*values)
        mapping =
          if values.length == 1 && values[0].is_a?(::Hash)
            values[0]
          else
            ::Hash[values.zip(values)]
          end

        Enum.new(constrained(included_in: mapping.keys), mapping: mapping)
      end

      # Turn a type into a lax type that will rescue from type-errors and
      # return the original input
      #
      # @return [Lax]
      #
      # @api public
      def lax
        Lax.new(self)
      end

      # Define a constructor for the type
      #
      # @param [#call,nil] constructor
      # @param [Hash] options
      # @param [#call,nil] block
      #
      # @return [Constructor]
      #
      # @api public
      def constructor(constructor = nil, **options, &block)
        constructor_type.new(with(**options), fn: constructor || block)
      end
    end
  end
end

require 'dry/types/default'
require 'dry/types/constrained'
require 'dry/types/enum'
require 'dry/types/lax'
require 'dry/types/sum'