sorbet-schema 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +4 -1
- data/benchmarks/helpers.rb +239 -0
- data/benchmarks/many_fields_deserialization.rb +23 -0
- data/benchmarks/many_fields_serialization.rb +27 -0
- data/benchmarks/simple_deserialization.rb +23 -0
- data/benchmarks/simple_serialization.rb +27 -0
- data/lib/sorbet-schema/version.rb +1 -1
- data/lib/typed/coercion/boolean_coercer.rb +2 -2
- data/lib/typed/coercion/coercer.rb +1 -1
- data/lib/typed/coercion/coercer_registry.rb +1 -1
- data/lib/typed/coercion/date_coercer.rb +2 -2
- data/lib/typed/coercion/date_time_coercer.rb +2 -2
- data/lib/typed/coercion/enum_coercer.rb +2 -2
- data/lib/typed/coercion/float_coercer.rb +2 -2
- data/lib/typed/coercion/integer_coercer.rb +2 -2
- data/lib/typed/coercion/string_coercer.rb +2 -2
- data/lib/typed/coercion/struct_coercer.rb +2 -2
- data/lib/typed/coercion/symbol_coercer.rb +2 -2
- data/lib/typed/coercion/typed_array_coercer.rb +2 -2
- data/lib/typed/coercion/typed_hash_coercer.rb +2 -2
- data/lib/typed/schema.rb +16 -2
- data/lib/typed/serializer.rb +39 -20
- data/sorbet/rbi/gems/benchmark-ips@2.14.0.rbi +981 -0
- metadata +12 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d6e96bccc5924a52824327d2d5bc3b8e79b887ac31d13b292581c347c1d43480
|
|
4
|
+
data.tar.gz: 36896e42540d07c714b8075c7c2b89b4d47c5d09d1e098e83ecf050f6c68fa50
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c0a12cf7754d2e13eaebb5a0b042a2abea848dc79aeda84b2887f0c949b523c2aa8a1b3a842562ee053c15dcb3b5a13c6caf1e760bbf9c7f297ea39285c5e1e3
|
|
7
|
+
data.tar.gz: b72bc80795f41444f06b2aa9bc7186f3669993c95cb7e3e500e021fc2c053c2ac5088d2e3a0efae32aa4e1bd0d35c138602de08fba9f31ded554b43ae7aefd4d
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.9.3](https://github.com/maxveldink/sorbet-schema/compare/v0.9.2...v0.9.3) (2025-12-06)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Performance Improvements
|
|
11
|
+
|
|
12
|
+
* add deserialization benchmark ([#135](https://github.com/maxveldink/sorbet-schema/issues/135)) ([21d23bb](https://github.com/maxveldink/sorbet-schema/commit/21d23bb51c40ee199cb79a54f06184bb15634909))
|
|
13
|
+
* add serialization benchmarks, refactor to helpers ([#137](https://github.com/maxveldink/sorbet-schema/issues/137)) ([dc43409](https://github.com/maxveldink/sorbet-schema/commit/dc434094511f26ddc37f853295b2f07586826f00))
|
|
14
|
+
* Implement caching for serializers and coercers to improve performance ([#136](https://github.com/maxveldink/sorbet-schema/issues/136)) ([d980292](https://github.com/maxveldink/sorbet-schema/commit/d980292b64630c9ee93f886b10b3b9334b694879))
|
|
15
|
+
* Improve coercer performance by using class methods ([#134](https://github.com/maxveldink/sorbet-schema/issues/134)) ([0336299](https://github.com/maxveldink/sorbet-schema/commit/033629914c7ac0e19d21a725336ff7b9dbc8fc90))
|
|
16
|
+
|
|
17
|
+
## [0.9.2](https://github.com/maxveldink/sorbet-schema/compare/v0.9.1...v0.9.2) (2024-09-04)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* bug coercing boolean strings ([#126](https://github.com/maxveldink/sorbet-schema/issues/126)) ([8035695](https://github.com/maxveldink/sorbet-schema/commit/8035695ab79af2b9eb03d7f6418409bd3a899084))
|
|
23
|
+
|
|
7
24
|
## [0.9.1](https://github.com/maxveldink/sorbet-schema/compare/v0.9.0...v0.9.1) (2024-08-14)
|
|
8
25
|
|
|
9
26
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
sorbet-schema (0.9.
|
|
4
|
+
sorbet-schema (0.9.3)
|
|
5
5
|
sorbet-result (~> 1.1)
|
|
6
6
|
sorbet-runtime (~> 0.5)
|
|
7
7
|
sorbet-struct-comparable (~> 1.3)
|
|
@@ -12,6 +12,7 @@ GEM
|
|
|
12
12
|
specs:
|
|
13
13
|
ansi (1.5.0)
|
|
14
14
|
ast (2.4.2)
|
|
15
|
+
benchmark-ips (2.14.0)
|
|
15
16
|
bigdecimal (3.1.8)
|
|
16
17
|
builder (3.3.0)
|
|
17
18
|
debug (1.9.2)
|
|
@@ -127,9 +128,11 @@ GEM
|
|
|
127
128
|
PLATFORMS
|
|
128
129
|
arm64-darwin-22
|
|
129
130
|
arm64-darwin-23
|
|
131
|
+
arm64-darwin-25
|
|
130
132
|
x86_64-linux
|
|
131
133
|
|
|
132
134
|
DEPENDENCIES
|
|
135
|
+
benchmark-ips
|
|
133
136
|
bigdecimal
|
|
134
137
|
debug
|
|
135
138
|
minitest
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
|
5
|
+
|
|
6
|
+
require "json"
|
|
7
|
+
require "sorbet-schema"
|
|
8
|
+
|
|
9
|
+
module BenchmarkHelpers
|
|
10
|
+
extend T::Sig
|
|
11
|
+
|
|
12
|
+
class Rank < T::Enum
|
|
13
|
+
enums do
|
|
14
|
+
Ace = new("Ace")
|
|
15
|
+
King = new("King")
|
|
16
|
+
Queen = new("Queen")
|
|
17
|
+
Jack = new("Jack")
|
|
18
|
+
Ten = new("Ten")
|
|
19
|
+
Nine = new("Nine")
|
|
20
|
+
Eight = new("Eight")
|
|
21
|
+
Seven = new("Seven")
|
|
22
|
+
Six = new("Six")
|
|
23
|
+
Five = new("Five")
|
|
24
|
+
Four = new("Four")
|
|
25
|
+
Three = new("Three")
|
|
26
|
+
Two = new("Two")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class Suit < T::Enum
|
|
31
|
+
enums do
|
|
32
|
+
Spades = new("Spades")
|
|
33
|
+
Hearts = new("Hearts")
|
|
34
|
+
Clubs = new("Clubs")
|
|
35
|
+
Diamonds = new("Diamonds")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Define some structs for the benchmark
|
|
40
|
+
class Card < T::Struct
|
|
41
|
+
const :rank, Rank
|
|
42
|
+
const :suit, Suit
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class Player < T::Struct
|
|
46
|
+
const :name, String
|
|
47
|
+
const :hand, T::Array[Card]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class Round < T::Struct
|
|
51
|
+
const :number, Integer
|
|
52
|
+
const :winner, T.nilable(Player)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class Game < T::Struct
|
|
56
|
+
const :name, String
|
|
57
|
+
const :players, T::Array[Player]
|
|
58
|
+
const :rounds, T::Array[Round]
|
|
59
|
+
const :deck_size, Integer
|
|
60
|
+
const :shuffled, T::Boolean
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Define a struct with MANY fields of the same types that require coercion
|
|
64
|
+
# This will stress-test coercer caching by reusing the same coercers many times
|
|
65
|
+
class Humongous < T::Struct
|
|
66
|
+
const :field_1, Integer
|
|
67
|
+
const :field_2, Integer
|
|
68
|
+
const :field_3, Integer
|
|
69
|
+
const :field_4, Integer
|
|
70
|
+
const :field_5, Integer
|
|
71
|
+
const :field_6, Integer
|
|
72
|
+
const :field_7, Integer
|
|
73
|
+
const :field_8, Integer
|
|
74
|
+
const :field_9, Integer
|
|
75
|
+
const :field_10, Integer
|
|
76
|
+
const :field_11, Integer
|
|
77
|
+
const :field_12, Integer
|
|
78
|
+
const :field_13, Integer
|
|
79
|
+
const :field_14, Integer
|
|
80
|
+
const :field_15, Integer
|
|
81
|
+
const :field_16, Integer
|
|
82
|
+
const :field_17, Integer
|
|
83
|
+
const :field_18, Integer
|
|
84
|
+
const :field_19, Integer
|
|
85
|
+
const :field_20, Integer
|
|
86
|
+
const :field_21, Integer
|
|
87
|
+
const :field_22, Integer
|
|
88
|
+
const :field_23, Integer
|
|
89
|
+
const :field_24, Integer
|
|
90
|
+
const :field_25, Integer
|
|
91
|
+
const :field_26, Integer
|
|
92
|
+
const :field_27, Integer
|
|
93
|
+
const :field_28, Integer
|
|
94
|
+
const :field_29, Integer
|
|
95
|
+
const :field_30, Integer
|
|
96
|
+
const :field_31, Integer
|
|
97
|
+
const :field_32, Integer
|
|
98
|
+
const :field_33, Integer
|
|
99
|
+
const :field_34, Integer
|
|
100
|
+
const :field_35, Integer
|
|
101
|
+
const :field_36, Integer
|
|
102
|
+
const :field_37, Integer
|
|
103
|
+
const :field_38, Integer
|
|
104
|
+
const :field_39, Integer
|
|
105
|
+
const :field_40, Integer
|
|
106
|
+
const :field_41, Integer
|
|
107
|
+
const :field_42, Integer
|
|
108
|
+
const :field_43, Integer
|
|
109
|
+
const :field_44, Integer
|
|
110
|
+
const :field_45, Integer
|
|
111
|
+
const :field_46, Integer
|
|
112
|
+
const :field_47, Integer
|
|
113
|
+
const :field_48, Integer
|
|
114
|
+
const :field_49, Integer
|
|
115
|
+
const :field_50, Integer
|
|
116
|
+
|
|
117
|
+
const :float_1, Float
|
|
118
|
+
const :float_2, Float
|
|
119
|
+
const :float_3, Float
|
|
120
|
+
const :float_4, Float
|
|
121
|
+
const :float_5, Float
|
|
122
|
+
const :float_6, Float
|
|
123
|
+
const :float_7, Float
|
|
124
|
+
const :float_8, Float
|
|
125
|
+
const :float_9, Float
|
|
126
|
+
const :float_10, Float
|
|
127
|
+
const :float_11, Float
|
|
128
|
+
const :float_12, Float
|
|
129
|
+
const :float_13, Float
|
|
130
|
+
const :float_14, Float
|
|
131
|
+
const :float_15, Float
|
|
132
|
+
const :float_16, Float
|
|
133
|
+
const :float_17, Float
|
|
134
|
+
const :float_18, Float
|
|
135
|
+
const :float_19, Float
|
|
136
|
+
const :float_20, Float
|
|
137
|
+
|
|
138
|
+
const :bool_1, T::Boolean
|
|
139
|
+
const :bool_2, T::Boolean
|
|
140
|
+
const :bool_3, T::Boolean
|
|
141
|
+
const :bool_4, T::Boolean
|
|
142
|
+
const :bool_5, T::Boolean
|
|
143
|
+
const :bool_6, T::Boolean
|
|
144
|
+
const :bool_7, T::Boolean
|
|
145
|
+
const :bool_8, T::Boolean
|
|
146
|
+
const :bool_9, T::Boolean
|
|
147
|
+
const :bool_10, T::Boolean
|
|
148
|
+
const :bool_11, T::Boolean
|
|
149
|
+
const :bool_12, T::Boolean
|
|
150
|
+
const :bool_13, T::Boolean
|
|
151
|
+
const :bool_14, T::Boolean
|
|
152
|
+
const :bool_15, T::Boolean
|
|
153
|
+
const :bool_16, T::Boolean
|
|
154
|
+
const :bool_17, T::Boolean
|
|
155
|
+
const :bool_18, T::Boolean
|
|
156
|
+
const :bool_19, T::Boolean
|
|
157
|
+
const :bool_20, T::Boolean
|
|
158
|
+
|
|
159
|
+
const :sym_1, Symbol
|
|
160
|
+
const :sym_2, Symbol
|
|
161
|
+
const :sym_3, Symbol
|
|
162
|
+
const :sym_4, Symbol
|
|
163
|
+
const :sym_5, Symbol
|
|
164
|
+
const :sym_6, Symbol
|
|
165
|
+
const :sym_7, Symbol
|
|
166
|
+
const :sym_8, Symbol
|
|
167
|
+
const :sym_9, Symbol
|
|
168
|
+
const :sym_10, Symbol
|
|
169
|
+
const :sym_11, Symbol
|
|
170
|
+
const :sym_12, Symbol
|
|
171
|
+
const :sym_13, Symbol
|
|
172
|
+
const :sym_14, Symbol
|
|
173
|
+
const :sym_15, Symbol
|
|
174
|
+
const :sym_16, Symbol
|
|
175
|
+
const :sym_17, Symbol
|
|
176
|
+
const :sym_18, Symbol
|
|
177
|
+
const :sym_19, Symbol
|
|
178
|
+
const :sym_20, Symbol
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
sig { returns(T::Hash[Symbol, T.untyped]) }
|
|
182
|
+
def self.game_data
|
|
183
|
+
{
|
|
184
|
+
name: "Poker",
|
|
185
|
+
players: Array.new(10) do |i|
|
|
186
|
+
{
|
|
187
|
+
name: "Player #{i}",
|
|
188
|
+
hand: [
|
|
189
|
+
{rank: "Ace", suit: "Spades"},
|
|
190
|
+
{rank: "King", suit: "Spades"}
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
end,
|
|
194
|
+
rounds: Array.new(5) do |i|
|
|
195
|
+
{
|
|
196
|
+
number: i + 1,
|
|
197
|
+
winner: {
|
|
198
|
+
name: "Player #{i % 2}",
|
|
199
|
+
hand: [
|
|
200
|
+
{rank: "Queen", suit: "Hearts"},
|
|
201
|
+
{rank: "Jack", suit: "Hearts"}
|
|
202
|
+
]
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
end,
|
|
206
|
+
deck_size: 52,
|
|
207
|
+
shuffled: true
|
|
208
|
+
}
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
sig { returns(T::Hash[Symbol, T.untyped]) }
|
|
212
|
+
def self.humongous_data
|
|
213
|
+
{
|
|
214
|
+
field_1: "1", field_2: "2", field_3: "3", field_4: "4", field_5: "5",
|
|
215
|
+
field_6: "6", field_7: "7", field_8: "8", field_9: "9", field_10: "10",
|
|
216
|
+
field_11: "11", field_12: "12", field_13: "13", field_14: "14", field_15: "15",
|
|
217
|
+
field_16: "16", field_17: "17", field_18: "18", field_19: "19", field_20: "20",
|
|
218
|
+
field_21: "21", field_22: "22", field_23: "23", field_24: "24", field_25: "25",
|
|
219
|
+
field_26: "26", field_27: "27", field_28: "28", field_29: "29", field_30: "30",
|
|
220
|
+
field_31: "31", field_32: "32", field_33: "33", field_34: "34", field_35: "35",
|
|
221
|
+
field_36: "36", field_37: "37", field_38: "38", field_39: "39", field_40: "40",
|
|
222
|
+
field_41: "41", field_42: "42", field_43: "43", field_44: "44", field_45: "45",
|
|
223
|
+
field_46: "46", field_47: "47", field_48: "48", field_49: "49", field_50: "50",
|
|
224
|
+
float_1: "1.1", float_2: "2.2", float_3: "3.3", float_4: "4.4", float_5: "5.5",
|
|
225
|
+
float_6: "6.6", float_7: "7.7", float_8: "8.8", float_9: "9.9", float_10: "10.1",
|
|
226
|
+
float_11: "11.1", float_12: "12.2", float_13: "13.3", float_14: "14.4", float_15: "15.5",
|
|
227
|
+
float_16: "16.6", float_17: "17.7", float_18: "18.8", float_19: "19.9", float_20: "20.1",
|
|
228
|
+
bool_1: "true", bool_2: "false", bool_3: "true", bool_4: "false", bool_5: "true",
|
|
229
|
+
bool_6: "false", bool_7: "true", bool_8: "false", bool_9: "true", bool_10: "false",
|
|
230
|
+
bool_11: "true", bool_12: "false", bool_13: "true", bool_14: "false", bool_15: "true",
|
|
231
|
+
bool_16: "false", bool_17: "true", bool_18: "false", bool_19: "true", bool_20: "false",
|
|
232
|
+
sym_1: "sym1", sym_2: "sym2", sym_3: "sym3", sym_4: "sym4", sym_5: "sym5",
|
|
233
|
+
sym_6: "sym6", sym_7: "sym7", sym_8: "sym8", sym_9: "sym9", sym_10: "sym10",
|
|
234
|
+
sym_11: "sym11", sym_12: "sym12", sym_13: "sym13", sym_14: "sym14", sym_15: "sym15",
|
|
235
|
+
sym_16: "sym16", sym_17: "sym17", sym_18: "sym18", sym_19: "sym19", sym_20: "sym20"
|
|
236
|
+
}
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
|
5
|
+
|
|
6
|
+
require "benchmark/ips"
|
|
7
|
+
require_relative "helpers"
|
|
8
|
+
|
|
9
|
+
humongous_schema = Typed::Schema.from_struct(BenchmarkHelpers::Humongous)
|
|
10
|
+
humongous_data = BenchmarkHelpers.humongous_data
|
|
11
|
+
humongous_json = JSON.generate(humongous_data)
|
|
12
|
+
|
|
13
|
+
Benchmark.ips do |x|
|
|
14
|
+
x.report("hash deserialization with many fields") do
|
|
15
|
+
humongous_schema.from_hash(humongous_data)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
x.report("json deserialization with many fields") do
|
|
19
|
+
humongous_schema.from_json(humongous_json)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
x.compare!
|
|
23
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
|
5
|
+
|
|
6
|
+
require "benchmark/ips"
|
|
7
|
+
require_relative "helpers"
|
|
8
|
+
|
|
9
|
+
humongous_schema = Typed::Schema.from_struct(BenchmarkHelpers::Humongous)
|
|
10
|
+
humongous_data = BenchmarkHelpers.humongous_data
|
|
11
|
+
humongous_struct = humongous_schema.from_hash(humongous_data).payload
|
|
12
|
+
|
|
13
|
+
hash_serializer = Typed::HashSerializer.new(schema: humongous_schema)
|
|
14
|
+
json_serializer = Typed::JSONSerializer.new(schema: humongous_schema)
|
|
15
|
+
|
|
16
|
+
Benchmark.ips do |x|
|
|
17
|
+
x.report("hash serialization with many fields") do
|
|
18
|
+
hash_serializer.serialize(humongous_struct)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
x.report("json serialization with many fields") do
|
|
22
|
+
json_serializer.serialize(humongous_struct)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
x.compare!
|
|
26
|
+
end
|
|
27
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
|
5
|
+
|
|
6
|
+
require "benchmark/ips"
|
|
7
|
+
require_relative "helpers"
|
|
8
|
+
|
|
9
|
+
game_schema = Typed::Schema.from_struct(BenchmarkHelpers::Game)
|
|
10
|
+
game_data = BenchmarkHelpers.game_data
|
|
11
|
+
game_json = JSON.generate(game_data)
|
|
12
|
+
|
|
13
|
+
Benchmark.ips do |x|
|
|
14
|
+
x.report("simple hash deserialization") do
|
|
15
|
+
game_schema.from_hash(game_data)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
x.report("simple json deserialization") do
|
|
19
|
+
game_schema.from_json(game_json)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
x.compare!
|
|
23
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
|
5
|
+
|
|
6
|
+
require "benchmark/ips"
|
|
7
|
+
require_relative "helpers"
|
|
8
|
+
|
|
9
|
+
game_schema = Typed::Schema.from_struct(BenchmarkHelpers::Game)
|
|
10
|
+
game_data = BenchmarkHelpers.game_data
|
|
11
|
+
game_struct = game_schema.from_hash(game_data).payload
|
|
12
|
+
|
|
13
|
+
hash_serializer = Typed::HashSerializer.new(schema: game_schema)
|
|
14
|
+
json_serializer = Typed::JSONSerializer.new(schema: game_schema)
|
|
15
|
+
|
|
16
|
+
Benchmark.ips do |x|
|
|
17
|
+
x.report("simple hash serialization") do
|
|
18
|
+
hash_serializer.serialize(game_struct)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
x.report("simple json serialization") do
|
|
22
|
+
json_serializer.serialize(game_struct)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
x.compare!
|
|
26
|
+
end
|
|
27
|
+
|
|
@@ -8,13 +8,13 @@ module Typed
|
|
|
8
8
|
Target = type_member { {fixed: T::Boolean} }
|
|
9
9
|
|
|
10
10
|
sig { override.params(type: T::Types::Base).returns(T::Boolean) }
|
|
11
|
-
def used_for_type?(type)
|
|
11
|
+
def self.used_for_type?(type)
|
|
12
12
|
type == T::Utils.coerce(T::Boolean)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
sig { override.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
16
16
|
def coerce(type:, value:)
|
|
17
|
-
return Failure.new(CoercionError.new("Type must be a T::Boolean.")) unless used_for_type?(type)
|
|
17
|
+
return Failure.new(CoercionError.new("Type must be a T::Boolean.")) unless self.class.used_for_type?(type)
|
|
18
18
|
|
|
19
19
|
if type.recursively_valid?(value)
|
|
20
20
|
Success.new(value)
|
|
@@ -11,7 +11,7 @@ module Typed
|
|
|
11
11
|
Target = type_member(:out)
|
|
12
12
|
|
|
13
13
|
sig { abstract.params(type: T::Types::Base).returns(T::Boolean) }
|
|
14
|
-
def used_for_type?(type)
|
|
14
|
+
def self.used_for_type?(type)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
sig { abstract.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
@@ -45,7 +45,7 @@ module Typed
|
|
|
45
45
|
|
|
46
46
|
sig { params(type: T::Types::Base).returns(T.nilable(T.class_of(Coercer))) }
|
|
47
47
|
def select_coercer_by(type:)
|
|
48
|
-
@available.find { |coercer| coercer.
|
|
48
|
+
@available.find { |coercer| coercer.used_for_type?(type) }
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
end
|
|
@@ -10,13 +10,13 @@ module Typed
|
|
|
10
10
|
Target = type_member { {fixed: Date} }
|
|
11
11
|
|
|
12
12
|
sig { override.params(type: T::Types::Base).returns(T::Boolean) }
|
|
13
|
-
def used_for_type?(type)
|
|
13
|
+
def self.used_for_type?(type)
|
|
14
14
|
T::Utils.coerce(type) == T::Utils.coerce(Date)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
sig { override.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
18
18
|
def coerce(type:, value:)
|
|
19
|
-
return Failure.new(CoercionError.new("Type must be a Date.")) unless used_for_type?(type)
|
|
19
|
+
return Failure.new(CoercionError.new("Type must be a Date.")) unless self.class.used_for_type?(type)
|
|
20
20
|
|
|
21
21
|
return Success.new(value) if value.is_a?(Date)
|
|
22
22
|
|
|
@@ -10,13 +10,13 @@ module Typed
|
|
|
10
10
|
Target = type_member { {fixed: DateTime} }
|
|
11
11
|
|
|
12
12
|
sig { override.params(type: T::Types::Base).returns(T::Boolean) }
|
|
13
|
-
def used_for_type?(type)
|
|
13
|
+
def self.used_for_type?(type)
|
|
14
14
|
T::Utils.coerce(type) == T::Utils.coerce(DateTime)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
sig { override.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
18
18
|
def coerce(type:, value:)
|
|
19
|
-
return Failure.new(CoercionError.new("Type must be a DateTime.")) unless used_for_type?(type)
|
|
19
|
+
return Failure.new(CoercionError.new("Type must be a DateTime.")) unless self.class.used_for_type?(type)
|
|
20
20
|
|
|
21
21
|
return Success.new(value) if value.is_a?(DateTime)
|
|
22
22
|
|
|
@@ -8,7 +8,7 @@ module Typed
|
|
|
8
8
|
Target = type_member { {fixed: T::Enum} }
|
|
9
9
|
|
|
10
10
|
sig { override.params(type: T::Types::Base).returns(T::Boolean) }
|
|
11
|
-
def used_for_type?(type)
|
|
11
|
+
def self.used_for_type?(type)
|
|
12
12
|
return false unless type.respond_to?(:raw_type)
|
|
13
13
|
|
|
14
14
|
!!(T.cast(type, T::Types::Simple).raw_type < T::Enum)
|
|
@@ -16,7 +16,7 @@ module Typed
|
|
|
16
16
|
|
|
17
17
|
sig { override.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
18
18
|
def coerce(type:, value:)
|
|
19
|
-
return Failure.new(CoercionError.new("Field type must inherit from T::Enum for Enum coercion.")) unless used_for_type?(type)
|
|
19
|
+
return Failure.new(CoercionError.new("Field type must inherit from T::Enum for Enum coercion.")) unless self.class.used_for_type?(type)
|
|
20
20
|
|
|
21
21
|
Success.new(T.cast(type, T::Types::Simple).raw_type.from_serialized(value))
|
|
22
22
|
rescue KeyError => e
|
|
@@ -8,13 +8,13 @@ module Typed
|
|
|
8
8
|
Target = type_member { {fixed: Float} }
|
|
9
9
|
|
|
10
10
|
sig { override.params(type: T::Types::Base).returns(T::Boolean) }
|
|
11
|
-
def used_for_type?(type)
|
|
11
|
+
def self.used_for_type?(type)
|
|
12
12
|
T::Utils.coerce(type) == T::Utils.coerce(Float)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
sig { override.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
16
16
|
def coerce(type:, value:)
|
|
17
|
-
return Failure.new(CoercionError.new("Type must be a Float.")) unless used_for_type?(type)
|
|
17
|
+
return Failure.new(CoercionError.new("Type must be a Float.")) unless self.class.used_for_type?(type)
|
|
18
18
|
|
|
19
19
|
Success.new(Float(value))
|
|
20
20
|
rescue ArgumentError, TypeError
|
|
@@ -8,13 +8,13 @@ module Typed
|
|
|
8
8
|
Target = type_member { {fixed: Integer} }
|
|
9
9
|
|
|
10
10
|
sig { override.params(type: T::Types::Base).returns(T::Boolean) }
|
|
11
|
-
def used_for_type?(type)
|
|
11
|
+
def self.used_for_type?(type)
|
|
12
12
|
type == T::Utils.coerce(Integer)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
sig { override.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
16
16
|
def coerce(type:, value:)
|
|
17
|
-
return Failure.new(CoercionError.new("Type must be a Integer.")) unless used_for_type?(type)
|
|
17
|
+
return Failure.new(CoercionError.new("Type must be a Integer.")) unless self.class.used_for_type?(type)
|
|
18
18
|
|
|
19
19
|
Success.new(Integer(value))
|
|
20
20
|
rescue ArgumentError, TypeError
|
|
@@ -8,13 +8,13 @@ module Typed
|
|
|
8
8
|
Target = type_member { {fixed: String} }
|
|
9
9
|
|
|
10
10
|
sig { override.params(type: T::Types::Base).returns(T::Boolean) }
|
|
11
|
-
def used_for_type?(type)
|
|
11
|
+
def self.used_for_type?(type)
|
|
12
12
|
type == T::Utils.coerce(String)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
sig { override.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
16
16
|
def coerce(type:, value:)
|
|
17
|
-
return Failure.new(CoercionError.new("Type must be a String.")) unless used_for_type?(type)
|
|
17
|
+
return Failure.new(CoercionError.new("Type must be a String.")) unless self.class.used_for_type?(type)
|
|
18
18
|
|
|
19
19
|
Success.new(String(value))
|
|
20
20
|
end
|
|
@@ -8,7 +8,7 @@ module Typed
|
|
|
8
8
|
Target = type_member { {fixed: T::Struct} }
|
|
9
9
|
|
|
10
10
|
sig { override.params(type: T::Types::Base).returns(T::Boolean) }
|
|
11
|
-
def used_for_type?(type)
|
|
11
|
+
def self.used_for_type?(type)
|
|
12
12
|
return false unless type.respond_to?(:raw_type)
|
|
13
13
|
|
|
14
14
|
!!(T.cast(type, T::Types::Simple).raw_type < T::Struct)
|
|
@@ -16,7 +16,7 @@ module Typed
|
|
|
16
16
|
|
|
17
17
|
sig { override.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
18
18
|
def coerce(type:, value:)
|
|
19
|
-
return Failure.new(CoercionError.new("Field type must inherit from T::Struct for Struct coercion.")) unless used_for_type?(type)
|
|
19
|
+
return Failure.new(CoercionError.new("Field type must inherit from T::Struct for Struct coercion.")) unless self.class.used_for_type?(type)
|
|
20
20
|
return Success.new(value) if type.recursively_valid?(value)
|
|
21
21
|
|
|
22
22
|
return Failure.new(CoercionError.new("Value of type '#{value.class}' cannot be coerced to #{type} Struct.")) unless value.is_a?(Hash)
|
|
@@ -8,13 +8,13 @@ module Typed
|
|
|
8
8
|
Target = type_member { {fixed: Symbol} }
|
|
9
9
|
|
|
10
10
|
sig { override.params(type: T::Types::Base).returns(T::Boolean) }
|
|
11
|
-
def used_for_type?(type)
|
|
11
|
+
def self.used_for_type?(type)
|
|
12
12
|
type == T::Utils.coerce(Symbol)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
sig { override.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
16
16
|
def coerce(type:, value:)
|
|
17
|
-
return Failure.new(CoercionError.new("Type must be a Symbol.")) unless used_for_type?(type)
|
|
17
|
+
return Failure.new(CoercionError.new("Type must be a Symbol.")) unless self.class.used_for_type?(type)
|
|
18
18
|
|
|
19
19
|
if value.respond_to?(:to_sym)
|
|
20
20
|
Success.new(value.to_sym)
|
|
@@ -8,13 +8,13 @@ module Typed
|
|
|
8
8
|
Target = type_member { {fixed: T::Array[T.untyped]} }
|
|
9
9
|
|
|
10
10
|
sig { override.params(type: T::Types::Base).returns(T::Boolean) }
|
|
11
|
-
def used_for_type?(type)
|
|
11
|
+
def self.used_for_type?(type)
|
|
12
12
|
type.is_a?(T::Types::TypedArray)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
sig { override.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
16
16
|
def coerce(type:, value:)
|
|
17
|
-
return Failure.new(CoercionError.new("Field type must be a T::Array.")) unless used_for_type?(type)
|
|
17
|
+
return Failure.new(CoercionError.new("Field type must be a T::Array.")) unless self.class.used_for_type?(type)
|
|
18
18
|
return Failure.new(CoercionError.new("Value must be an Array.")) unless value.is_a?(Array)
|
|
19
19
|
|
|
20
20
|
return Success.new(value) if type.recursively_valid?(value)
|
|
@@ -8,13 +8,13 @@ module Typed
|
|
|
8
8
|
Target = type_member { {fixed: T::Hash[T.untyped, T.untyped]} }
|
|
9
9
|
|
|
10
10
|
sig { override.params(type: T::Types::Base).returns(T::Boolean) }
|
|
11
|
-
def used_for_type?(type)
|
|
11
|
+
def self.used_for_type?(type)
|
|
12
12
|
type.is_a?(T::Types::TypedHash)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
sig { override.params(type: T::Types::Base, value: Value).returns(Result[Target, CoercionError]) }
|
|
16
16
|
def coerce(type:, value:)
|
|
17
|
-
return Failure.new(CoercionError.new("Field type must be a T::Hash.")) unless used_for_type?(type)
|
|
17
|
+
return Failure.new(CoercionError.new("Field type must be a T::Hash.")) unless self.class.used_for_type?(type)
|
|
18
18
|
return Failure.new(CoercionError.new("Value must be a Hash.")) unless value.is_a?(Hash)
|
|
19
19
|
|
|
20
20
|
return Success.new(value) if type.recursively_valid?(value)
|