sorbet-coerce 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 136d8069b4fcb9d8e819c025f5085ca957ff17b5a620ccb0942d89f406bd8564
4
+ data.tar.gz: 7b2128b6db027094fe762cd378432b9788648bb53c561e8c3dc1a85255214fed
5
+ SHA512:
6
+ metadata.gz: 4d0926cd6be851d127e9cc84be9b1a3c6130eb15f2dd6416bd37fe02dea1296159bc693dc78281148232a23b48d6aae73a9174af8bf95d43f8e7df9c7bae4e4f
7
+ data.tar.gz: 2338760290ceee4329c15ae879bd6c5ec7a27a0e80dfd047abefb7c14f85def8d5a32e2174193f9ac279d1971b1cdc635073d6517ed2b9cfd6f81e04b122f121
@@ -0,0 +1,96 @@
1
+ # typed: strict
2
+ require 'safe_type'
3
+ require 'sorbet-runtime'
4
+
5
+ module T; end
6
+
7
+ module T::Private
8
+ class Converter
9
+ extend T::Sig
10
+
11
+ PRIMITIVE_TYPES = T.let(::Set[
12
+ Date,
13
+ DateTime,
14
+ Float,
15
+ Integer,
16
+ String,
17
+ Symbol,
18
+ Time,
19
+ ], T.untyped)
20
+
21
+ protected
22
+ sig { params(value: T.untyped, type: T.untyped).returns(T.untyped) }
23
+ def _convert(value, type)
24
+ if type.is_a?(T::Types::TypedArray)
25
+ _convert_to_a(value, type.type)
26
+ elsif type.is_a?(T::Types::Simple)
27
+ _convert_simple(value, type.raw_type)
28
+ elsif type.is_a?(T::Types::Union)
29
+ raw_types = type.types.map(&:raw_type)
30
+ raise ArgumentError.new(
31
+ 'the only supported union type is T.nilable',
32
+ ) unless raw_types.length == 2 && raw_types.include?(NilClass)
33
+
34
+ _convert(
35
+ value,
36
+ raw_types.select { |t| t != NilClass }.first,
37
+ )
38
+ elsif type < T::Struct
39
+ args = _build_args(value, type.props)
40
+ begin
41
+ type.new(args)
42
+ rescue T::Props::InvalidValueError, ArgumentError
43
+ nil
44
+ end
45
+ else
46
+ _convert_simple(value, type)
47
+ end
48
+ end
49
+
50
+ sig { params(value: T.untyped, type: T.untyped).returns(T.untyped) }
51
+ def _convert_simple(value, type)
52
+ return nil if value.nil?
53
+ return value if value.is_a?(type)
54
+ safe_type_rule = if type == T::Boolean
55
+ SafeType::Boolean.strict
56
+ elsif PRIMITIVE_TYPES.include?(type)
57
+ SafeType.const_get(type.name).strict
58
+ else
59
+ safe_type_rule = type
60
+ end
61
+ SafeType::coerce(value, safe_type_rule)
62
+ rescue SafeType::EmptyValueError, SafeType::CoercionError
63
+ nil
64
+ rescue SafeType::InvalidRuleError
65
+ begin
66
+ type.new(value)
67
+ rescue
68
+ nil
69
+ end
70
+ end
71
+
72
+ sig { params(ary: T.untyped, type: T.untyped).returns(T.untyped) }
73
+ def _convert_to_a(ary, type)
74
+ ary = [ary] unless ary.respond_to?(:map)
75
+ T.send(
76
+ 'let',
77
+ ary.map { |value| _convert(value, type) },
78
+ T.const_get('Array')[type],
79
+ )
80
+ rescue TypeError
81
+ []
82
+ end
83
+
84
+ sig { params(args: T.untyped, props: T.untyped).returns(T.untyped) }
85
+ def _build_args(args, props)
86
+ args.map { |name, value|
87
+ key = name.to_sym
88
+ [
89
+ key,
90
+ (!props.include?(key) || value.nil?) ?
91
+ nil : _convert(value, props[key][:type]),
92
+ ]
93
+ }.to_h.slice(*props.keys)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,21 @@
1
+ # typed: strict
2
+ require 'private/converter'
3
+ require 'safe_type'
4
+
5
+ module T
6
+ class CoercionError < SafeType::CoercionError; end
7
+
8
+ module Coerce
9
+ define_singleton_method(:[]) do |type|
10
+ Class.new(T::Private::Converter) do
11
+ define_method(:to_s) { "#{name}#[#{type.to_s}]" }
12
+
13
+ define_method(:from) do |args|
14
+ T.send('let', send('_convert', args, type), type)
15
+ rescue TypeError
16
+ raise CoercionError.new(args, type)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ # typed: strong
2
+
3
+ module T
4
+ module Coerce
5
+ extend T::Sig
6
+ extend T::Generic
7
+
8
+ Elem = type_member
9
+
10
+ sig { params(args: T.untyped).returns(Elem) }
11
+ def from(args); end
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sorbet-coerce
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Chan Zuckerberg Initiative
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-10-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sorbet
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.4.4704
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.4.4704
27
+ - !ruby/object:Gem::Dependency
28
+ name: safe_type
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 1.1.1
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '1.1'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.1.1
47
+ - !ruby/object:Gem::Dependency
48
+ name: sorbet-runtime
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 0.4.4704
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 0.4.4704
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '3.8'
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '3.8'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '3.8'
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '3.8'
81
+ - !ruby/object:Gem::Dependency
82
+ name: byebug
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: 11.0.1
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: 11.0.1
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 11.0.1
98
+ - - "~>"
99
+ - !ruby/object:Gem::Version
100
+ version: 11.0.1
101
+ description:
102
+ email: opensource@chanzuckerberg.com
103
+ executables: []
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - lib/private/converter.rb
108
+ - lib/sorbet-coerce.rb
109
+ - lib/sorbet-coerce.rbi
110
+ homepage: https://github.com/chanzuckerberg/sorbet-coerce
111
+ licenses:
112
+ - MIT
113
+ metadata: {}
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: 2.3.0
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 2.7.9
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: Type coercion with Sorbet
134
+ test_files: []