onebusaway-sdk 0.1.0.pre.alpha.205 → 0.1.0.pre.alpha.207
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/README.md +32 -20
- data/lib/onebusaway-sdk/base_client.rb +63 -91
- data/lib/onebusaway-sdk/base_model.rb +489 -514
- data/lib/onebusaway-sdk/base_page.rb +35 -15
- data/lib/onebusaway-sdk/client.rb +1 -3
- data/lib/onebusaway-sdk/errors.rb +15 -19
- data/lib/onebusaway-sdk/extern.rb +1 -4
- data/lib/onebusaway-sdk/models/references.rb +0 -21
- data/lib/onebusaway-sdk/models/report_problem_with_stop_retrieve_params.rb +0 -21
- data/lib/onebusaway-sdk/models/report_problem_with_trip_retrieve_params.rb +0 -23
- data/lib/onebusaway-sdk/pooled_net_requester.rb +53 -54
- data/lib/onebusaway-sdk/request_options.rb +4 -11
- data/lib/onebusaway-sdk/resources/agencies_with_coverage.rb +0 -2
- data/lib/onebusaway-sdk/resources/agency.rb +0 -2
- data/lib/onebusaway-sdk/resources/arrival_and_departure.rb +0 -3
- data/lib/onebusaway-sdk/resources/block.rb +0 -2
- data/lib/onebusaway-sdk/resources/config.rb +0 -2
- data/lib/onebusaway-sdk/resources/current_time.rb +0 -2
- data/lib/onebusaway-sdk/resources/report_problem_with_stop.rb +0 -2
- data/lib/onebusaway-sdk/resources/report_problem_with_trip.rb +0 -2
- data/lib/onebusaway-sdk/resources/route.rb +0 -2
- data/lib/onebusaway-sdk/resources/route_ids_for_agency.rb +0 -2
- data/lib/onebusaway-sdk/resources/routes_for_agency.rb +0 -2
- data/lib/onebusaway-sdk/resources/routes_for_location.rb +0 -2
- data/lib/onebusaway-sdk/resources/schedule_for_route.rb +0 -2
- data/lib/onebusaway-sdk/resources/schedule_for_stop.rb +0 -2
- data/lib/onebusaway-sdk/resources/search_for_route.rb +0 -2
- data/lib/onebusaway-sdk/resources/search_for_stop.rb +0 -2
- data/lib/onebusaway-sdk/resources/shape.rb +0 -2
- data/lib/onebusaway-sdk/resources/stop.rb +0 -2
- data/lib/onebusaway-sdk/resources/stop_ids_for_agency.rb +0 -2
- data/lib/onebusaway-sdk/resources/stops_for_agency.rb +0 -2
- data/lib/onebusaway-sdk/resources/stops_for_location.rb +0 -2
- data/lib/onebusaway-sdk/resources/stops_for_route.rb +0 -2
- data/lib/onebusaway-sdk/resources/trip.rb +0 -2
- data/lib/onebusaway-sdk/resources/trip_details.rb +0 -2
- data/lib/onebusaway-sdk/resources/trip_for_vehicle.rb +0 -2
- data/lib/onebusaway-sdk/resources/trips_for_location.rb +0 -2
- data/lib/onebusaway-sdk/resources/trips_for_route.rb +0 -2
- data/lib/onebusaway-sdk/resources/vehicles_for_agency.rb +0 -2
- data/lib/onebusaway-sdk/util.rb +297 -96
- data/lib/onebusaway-sdk/version.rb +1 -1
- data/lib/onebusaway-sdk.rb +1 -0
- data/manifest.yaml +1 -0
- data/rbi/lib/onebusaway-sdk/base_client.rbi +52 -35
- data/rbi/lib/onebusaway-sdk/base_model.rbi +400 -256
- data/rbi/lib/onebusaway-sdk/base_page.rbi +3 -4
- data/rbi/lib/onebusaway-sdk/client.rbi +7 -2
- data/rbi/lib/onebusaway-sdk/errors.rbi +44 -10
- data/rbi/lib/onebusaway-sdk/extern.rbi +1 -1
- data/rbi/lib/onebusaway-sdk/models/agencies_with_coverage_list_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/agencies_with_coverage_list_response.rbi +9 -6
- data/rbi/lib/onebusaway-sdk/models/agency_retrieve_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/agency_retrieve_response.rbi +6 -6
- data/rbi/lib/onebusaway-sdk/models/arrival_and_departure_list_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/arrival_and_departure_list_response.rbi +95 -14
- data/rbi/lib/onebusaway-sdk/models/arrival_and_departure_retrieve_params.rbi +2 -9
- data/rbi/lib/onebusaway-sdk/models/arrival_and_departure_retrieve_response.rbi +93 -12
- data/rbi/lib/onebusaway-sdk/models/block_retrieve_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/block_retrieve_response.rbi +14 -20
- data/rbi/lib/onebusaway-sdk/models/config_retrieve_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/config_retrieve_response.rbi +8 -14
- data/rbi/lib/onebusaway-sdk/models/current_time_retrieve_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/current_time_retrieve_response.rbi +6 -6
- data/rbi/lib/onebusaway-sdk/models/references.rbi +60 -43
- data/rbi/lib/onebusaway-sdk/models/report_problem_with_stop_retrieve_params.rbi +10 -6
- data/rbi/lib/onebusaway-sdk/models/report_problem_with_trip_retrieve_params.rbi +15 -6
- data/rbi/lib/onebusaway-sdk/models/response_wrapper.rbi +4 -2
- data/rbi/lib/onebusaway-sdk/models/route_ids_for_agency_list_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/route_ids_for_agency_list_response.rbi +4 -4
- data/rbi/lib/onebusaway-sdk/models/route_retrieve_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/route_retrieve_response.rbi +6 -6
- data/rbi/lib/onebusaway-sdk/models/routes_for_agency_list_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/routes_for_agency_list_response.rbi +6 -6
- data/rbi/lib/onebusaway-sdk/models/routes_for_location_list_params.rbi +2 -2
- data/rbi/lib/onebusaway-sdk/models/routes_for_location_list_response.rbi +6 -6
- data/rbi/lib/onebusaway-sdk/models/schedule_for_route_retrieve_params.rbi +5 -8
- data/rbi/lib/onebusaway-sdk/models/schedule_for_route_retrieve_response.rbi +19 -16
- data/rbi/lib/onebusaway-sdk/models/schedule_for_stop_retrieve_params.rbi +5 -8
- data/rbi/lib/onebusaway-sdk/models/schedule_for_stop_retrieve_response.rbi +14 -14
- data/rbi/lib/onebusaway-sdk/models/search_for_route_list_params.rbi +4 -2
- data/rbi/lib/onebusaway-sdk/models/search_for_route_list_response.rbi +6 -6
- data/rbi/lib/onebusaway-sdk/models/search_for_stop_list_params.rbi +4 -2
- data/rbi/lib/onebusaway-sdk/models/search_for_stop_list_response.rbi +6 -6
- data/rbi/lib/onebusaway-sdk/models/shape_retrieve_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/shape_retrieve_response.rbi +7 -6
- data/rbi/lib/onebusaway-sdk/models/stop_ids_for_agency_list_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/stop_ids_for_agency_list_response.rbi +4 -4
- data/rbi/lib/onebusaway-sdk/models/stop_retrieve_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/stop_retrieve_response.rbi +6 -6
- data/rbi/lib/onebusaway-sdk/models/stops_for_agency_list_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/stops_for_agency_list_response.rbi +4 -4
- data/rbi/lib/onebusaway-sdk/models/stops_for_location_list_params.rbi +6 -2
- data/rbi/lib/onebusaway-sdk/models/stops_for_location_list_response.rbi +6 -6
- data/rbi/lib/onebusaway-sdk/models/stops_for_route_list_params.rbi +4 -2
- data/rbi/lib/onebusaway-sdk/models/stops_for_route_list_response.rbi +14 -14
- data/rbi/lib/onebusaway-sdk/models/trip_detail_retrieve_params.rbi +10 -2
- data/rbi/lib/onebusaway-sdk/models/trip_detail_retrieve_response.rbi +54 -23
- data/rbi/lib/onebusaway-sdk/models/trip_for_vehicle_retrieve_params.rbi +9 -8
- data/rbi/lib/onebusaway-sdk/models/trip_for_vehicle_retrieve_response.rbi +54 -23
- data/rbi/lib/onebusaway-sdk/models/trip_retrieve_params.rbi +5 -2
- data/rbi/lib/onebusaway-sdk/models/trip_retrieve_response.rbi +6 -6
- data/rbi/lib/onebusaway-sdk/models/trips_for_location_list_params.rbi +12 -12
- data/rbi/lib/onebusaway-sdk/models/trips_for_location_list_response.rbi +56 -16
- data/rbi/lib/onebusaway-sdk/models/trips_for_route_list_params.rbi +6 -2
- data/rbi/lib/onebusaway-sdk/models/trips_for_route_list_response.rbi +54 -16
- data/rbi/lib/onebusaway-sdk/models/vehicles_for_agency_list_params.rbi +3 -2
- data/rbi/lib/onebusaway-sdk/models/vehicles_for_agency_list_response.rbi +52 -14
- data/rbi/lib/onebusaway-sdk/pooled_net_requester.rbi +28 -13
- data/rbi/lib/onebusaway-sdk/request_options.rbi +25 -2
- data/rbi/lib/onebusaway-sdk/resources/agencies_with_coverage.rbi +4 -2
- data/rbi/lib/onebusaway-sdk/resources/agency.rbi +8 -3
- data/rbi/lib/onebusaway-sdk/resources/arrival_and_departure.rbi +14 -3
- data/rbi/lib/onebusaway-sdk/resources/block.rbi +8 -3
- data/rbi/lib/onebusaway-sdk/resources/config.rbi +3 -2
- data/rbi/lib/onebusaway-sdk/resources/current_time.rbi +3 -2
- data/rbi/lib/onebusaway-sdk/resources/report_problem_with_stop.rbi +9 -2
- data/rbi/lib/onebusaway-sdk/resources/report_problem_with_trip.rbi +14 -2
- data/rbi/lib/onebusaway-sdk/resources/route.rbi +8 -3
- data/rbi/lib/onebusaway-sdk/resources/route_ids_for_agency.rbi +8 -3
- data/rbi/lib/onebusaway-sdk/resources/routes_for_agency.rbi +8 -3
- data/rbi/lib/onebusaway-sdk/resources/routes_for_location.rbi +3 -2
- data/rbi/lib/onebusaway-sdk/resources/schedule_for_route.rbi +11 -3
- data/rbi/lib/onebusaway-sdk/resources/schedule_for_stop.rbi +11 -3
- data/rbi/lib/onebusaway-sdk/resources/search_for_route.rbi +10 -3
- data/rbi/lib/onebusaway-sdk/resources/search_for_stop.rbi +10 -3
- data/rbi/lib/onebusaway-sdk/resources/shape.rbi +8 -3
- data/rbi/lib/onebusaway-sdk/resources/stop.rbi +8 -3
- data/rbi/lib/onebusaway-sdk/resources/stop_ids_for_agency.rbi +8 -3
- data/rbi/lib/onebusaway-sdk/resources/stops_for_agency.rbi +8 -3
- data/rbi/lib/onebusaway-sdk/resources/stops_for_location.rbi +16 -3
- data/rbi/lib/onebusaway-sdk/resources/stops_for_route.rbi +12 -3
- data/rbi/lib/onebusaway-sdk/resources/trip.rbi +8 -3
- data/rbi/lib/onebusaway-sdk/resources/trip_details.rbi +12 -2
- data/rbi/lib/onebusaway-sdk/resources/trip_for_vehicle.rbi +11 -2
- data/rbi/lib/onebusaway-sdk/resources/trips_for_location.rbi +12 -2
- data/rbi/lib/onebusaway-sdk/resources/trips_for_route.rbi +15 -3
- data/rbi/lib/onebusaway-sdk/resources/vehicles_for_agency.rbi +10 -3
- data/rbi/lib/onebusaway-sdk/util.rbi +214 -83
- data/rbi/lib/onebusaway-sdk/version.rbi +1 -1
- data/sig/onebusaway-sdk/base_client.rbs +9 -8
- data/sig/onebusaway-sdk/base_model.rbs +8 -6
- data/sig/onebusaway-sdk/base_page.rbs +1 -1
- data/sig/onebusaway-sdk/errors.rbs +6 -5
- data/sig/onebusaway-sdk/pooled_net_requester.rbs +11 -4
- data/sig/onebusaway-sdk/request_options.rbs +4 -0
- data/sig/onebusaway-sdk/util.rbs +46 -2
- data/sig/onebusaway-sdk/version.rbs +1 -1
- metadata +4 -4
data/lib/onebusaway-sdk/util.rb
CHANGED
@@ -3,20 +3,17 @@
|
|
3
3
|
module OnebusawaySDK
|
4
4
|
# rubocop:disable Metrics/ModuleLength
|
5
5
|
|
6
|
-
# @private
|
7
|
-
#
|
6
|
+
# @api private
|
8
7
|
module Util
|
9
|
-
# @private
|
8
|
+
# @api private
|
10
9
|
#
|
11
10
|
# @return [Float]
|
12
|
-
#
|
13
11
|
def self.monotonic_secs = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
14
12
|
|
15
13
|
class << self
|
16
|
-
# @private
|
14
|
+
# @api private
|
17
15
|
#
|
18
16
|
# @return [String]
|
19
|
-
#
|
20
17
|
def arch
|
21
18
|
case (arch = RbConfig::CONFIG["arch"])&.downcase
|
22
19
|
in nil
|
@@ -32,10 +29,9 @@ module OnebusawaySDK
|
|
32
29
|
end
|
33
30
|
end
|
34
31
|
|
35
|
-
# @private
|
32
|
+
# @api private
|
36
33
|
#
|
37
34
|
# @return [String]
|
38
|
-
#
|
39
35
|
def os
|
40
36
|
case (host = RbConfig::CONFIG["host_os"])&.downcase
|
41
37
|
in nil
|
@@ -57,12 +53,11 @@ module OnebusawaySDK
|
|
57
53
|
end
|
58
54
|
|
59
55
|
class << self
|
60
|
-
# @private
|
56
|
+
# @api private
|
61
57
|
#
|
62
58
|
# @param input [Object]
|
63
59
|
#
|
64
|
-
# @return [Boolean
|
65
|
-
#
|
60
|
+
# @return [Boolean]
|
66
61
|
def primitive?(input)
|
67
62
|
case input
|
68
63
|
in true | false | Integer | Float | Symbol | String
|
@@ -72,12 +67,11 @@ module OnebusawaySDK
|
|
72
67
|
end
|
73
68
|
end
|
74
69
|
|
75
|
-
# @private
|
70
|
+
# @api private
|
76
71
|
#
|
77
72
|
# @param input [Object]
|
78
73
|
#
|
79
74
|
# @return [Boolean, Object]
|
80
|
-
#
|
81
75
|
def coerce_boolean(input)
|
82
76
|
case input.is_a?(String) ? input.downcase : input
|
83
77
|
in Numeric
|
@@ -91,13 +85,12 @@ module OnebusawaySDK
|
|
91
85
|
end
|
92
86
|
end
|
93
87
|
|
94
|
-
# @private
|
88
|
+
# @api private
|
95
89
|
#
|
96
90
|
# @param input [Object]
|
97
91
|
#
|
98
92
|
# @raise [ArgumentError]
|
99
93
|
# @return [Boolean, nil]
|
100
|
-
#
|
101
94
|
def coerce_boolean!(input)
|
102
95
|
case coerce_boolean(input)
|
103
96
|
in true | false | nil => coerced
|
@@ -107,12 +100,11 @@ module OnebusawaySDK
|
|
107
100
|
end
|
108
101
|
end
|
109
102
|
|
110
|
-
# @private
|
103
|
+
# @api private
|
111
104
|
#
|
112
105
|
# @param input [Object]
|
113
106
|
#
|
114
107
|
# @return [Integer, Object]
|
115
|
-
#
|
116
108
|
def coerce_integer(input)
|
117
109
|
case input
|
118
110
|
in true
|
@@ -124,12 +116,11 @@ module OnebusawaySDK
|
|
124
116
|
end
|
125
117
|
end
|
126
118
|
|
127
|
-
# @private
|
119
|
+
# @api private
|
128
120
|
#
|
129
121
|
# @param input [Object]
|
130
122
|
#
|
131
123
|
# @return [Float, Object]
|
132
|
-
#
|
133
124
|
def coerce_float(input)
|
134
125
|
case input
|
135
126
|
in true
|
@@ -141,12 +132,11 @@ module OnebusawaySDK
|
|
141
132
|
end
|
142
133
|
end
|
143
134
|
|
144
|
-
# @private
|
135
|
+
# @api private
|
145
136
|
#
|
146
137
|
# @param input [Object]
|
147
138
|
#
|
148
139
|
# @return [Hash{Object=>Object}, Object]
|
149
|
-
#
|
150
140
|
def coerce_hash(input)
|
151
141
|
case input
|
152
142
|
in NilClass | Array | Set | Enumerator
|
@@ -165,14 +155,13 @@ module OnebusawaySDK
|
|
165
155
|
OMIT = Object.new.freeze
|
166
156
|
|
167
157
|
class << self
|
168
|
-
# @private
|
158
|
+
# @api private
|
169
159
|
#
|
170
160
|
# @param lhs [Object]
|
171
161
|
# @param rhs [Object]
|
172
162
|
# @param concat [Boolean]
|
173
163
|
#
|
174
164
|
# @return [Object]
|
175
|
-
#
|
176
165
|
private def deep_merge_lr(lhs, rhs, concat: false)
|
177
166
|
case [lhs, rhs, concat]
|
178
167
|
in [Hash, Hash, _]
|
@@ -191,7 +180,7 @@ module OnebusawaySDK
|
|
191
180
|
end
|
192
181
|
end
|
193
182
|
|
194
|
-
# @private
|
183
|
+
# @api private
|
195
184
|
#
|
196
185
|
# Recursively merge one hash with another. If the values at a given key are not
|
197
186
|
# both hashes, just take the new value.
|
@@ -203,7 +192,6 @@ module OnebusawaySDK
|
|
203
192
|
# @param concat [Boolean] whether to merge sequences by concatenation.
|
204
193
|
#
|
205
194
|
# @return [Object]
|
206
|
-
#
|
207
195
|
def deep_merge(*values, sentinel: nil, concat: false)
|
208
196
|
case values
|
209
197
|
in [value, *values]
|
@@ -215,7 +203,7 @@ module OnebusawaySDK
|
|
215
203
|
end
|
216
204
|
end
|
217
205
|
|
218
|
-
# @private
|
206
|
+
# @api private
|
219
207
|
#
|
220
208
|
# @param data [Hash{Symbol=>Object}, Array<Object>, Object]
|
221
209
|
# @param pick [Symbol, Integer, Array<Symbol, Integer>, nil]
|
@@ -223,7 +211,6 @@ module OnebusawaySDK
|
|
223
211
|
# @param blk [Proc, nil]
|
224
212
|
#
|
225
213
|
# @return [Object, nil]
|
226
|
-
#
|
227
214
|
def dig(data, pick, sentinel = nil, &blk)
|
228
215
|
case [data, pick, blk]
|
229
216
|
in [_, nil, nil]
|
@@ -248,22 +235,20 @@ module OnebusawaySDK
|
|
248
235
|
end
|
249
236
|
|
250
237
|
class << self
|
251
|
-
# @private
|
238
|
+
# @api private
|
252
239
|
#
|
253
240
|
# @param uri [URI::Generic]
|
254
241
|
#
|
255
242
|
# @return [String]
|
256
|
-
#
|
257
243
|
def uri_origin(uri)
|
258
244
|
"#{uri.scheme}://#{uri.host}#{uri.port == uri.default_port ? '' : ":#{uri.port}"}"
|
259
245
|
end
|
260
246
|
|
261
|
-
# @private
|
247
|
+
# @api private
|
262
248
|
#
|
263
249
|
# @param path [String, Array<String>]
|
264
250
|
#
|
265
251
|
# @return [String]
|
266
|
-
#
|
267
252
|
def interpolate_path(path)
|
268
253
|
case path
|
269
254
|
in String
|
@@ -278,40 +263,37 @@ module OnebusawaySDK
|
|
278
263
|
end
|
279
264
|
|
280
265
|
class << self
|
281
|
-
# @private
|
266
|
+
# @api private
|
282
267
|
#
|
283
268
|
# @param query [String, nil]
|
284
269
|
#
|
285
270
|
# @return [Hash{String=>Array<String>}]
|
286
|
-
#
|
287
271
|
def decode_query(query)
|
288
272
|
CGI.parse(query.to_s)
|
289
273
|
end
|
290
274
|
|
291
|
-
# @private
|
275
|
+
# @api private
|
292
276
|
#
|
293
277
|
# @param query [Hash{String=>Array<String>, String, nil}, nil]
|
294
278
|
#
|
295
279
|
# @return [String, nil]
|
296
|
-
#
|
297
280
|
def encode_query(query)
|
298
281
|
query.to_h.empty? ? nil : URI.encode_www_form(query)
|
299
282
|
end
|
300
283
|
end
|
301
284
|
|
302
285
|
class << self
|
303
|
-
# @private
|
286
|
+
# @api private
|
304
287
|
#
|
305
288
|
# @param url [URI::Generic, String]
|
306
289
|
#
|
307
290
|
# @return [Hash{Symbol=>String, Integer, nil}]
|
308
|
-
#
|
309
291
|
def parse_uri(url)
|
310
292
|
parsed = URI::Generic.component.zip(URI.split(url)).to_h
|
311
293
|
{**parsed, query: decode_query(parsed.fetch(:query))}
|
312
294
|
end
|
313
295
|
|
314
|
-
# @private
|
296
|
+
# @api private
|
315
297
|
#
|
316
298
|
# @param parsed [Hash{Symbol=>String, Integer, nil}] .
|
317
299
|
#
|
@@ -326,12 +308,11 @@ module OnebusawaySDK
|
|
326
308
|
# @option parsed [Hash{String=>Array<String>}] :query
|
327
309
|
#
|
328
310
|
# @return [URI::Generic]
|
329
|
-
#
|
330
311
|
def unparse_uri(parsed)
|
331
312
|
URI::Generic.build(**parsed, query: encode_query(parsed.fetch(:query)))
|
332
313
|
end
|
333
314
|
|
334
|
-
# @private
|
315
|
+
# @api private
|
335
316
|
#
|
336
317
|
# @param lhs [Hash{Symbol=>String, Integer, nil}] .
|
337
318
|
#
|
@@ -358,7 +339,6 @@ module OnebusawaySDK
|
|
358
339
|
# @option rhs [Hash{String=>Array<String>}] :query
|
359
340
|
#
|
360
341
|
# @return [URI::Generic]
|
361
|
-
#
|
362
342
|
def join_parsed_uri(lhs, rhs)
|
363
343
|
base_path, base_query = lhs.fetch_values(:path, :query)
|
364
344
|
slashed = base_path.end_with?("/") ? base_path : "#{base_path}/"
|
@@ -380,12 +360,11 @@ module OnebusawaySDK
|
|
380
360
|
end
|
381
361
|
|
382
362
|
class << self
|
383
|
-
# @private
|
363
|
+
# @api private
|
384
364
|
#
|
385
365
|
# @param headers [Hash{String=>String, Integer, Array<String, Integer, nil>, nil}]
|
386
366
|
#
|
387
367
|
# @return [Hash{String=>String}]
|
388
|
-
#
|
389
368
|
def normalized_headers(*headers)
|
390
369
|
{}.merge(*headers.compact).to_h do |key, val|
|
391
370
|
case val
|
@@ -399,93 +378,173 @@ module OnebusawaySDK
|
|
399
378
|
end
|
400
379
|
end
|
401
380
|
|
381
|
+
# @api private
|
382
|
+
#
|
383
|
+
# An adapter that satisfies the IO interface required by `::IO.copy_stream`
|
384
|
+
class ReadIOAdapter
|
385
|
+
# @api private
|
386
|
+
#
|
387
|
+
# @param max_len [Integer, nil]
|
388
|
+
#
|
389
|
+
# @return [String]
|
390
|
+
private def read_enum(max_len)
|
391
|
+
case max_len
|
392
|
+
in nil
|
393
|
+
@stream.to_a.join
|
394
|
+
in Integer
|
395
|
+
@buf << @stream.next while @buf.length < max_len
|
396
|
+
@buf.slice!(..max_len)
|
397
|
+
end
|
398
|
+
rescue StopIteration
|
399
|
+
@stream = nil
|
400
|
+
@buf.slice!(0..)
|
401
|
+
end
|
402
|
+
|
403
|
+
# @api private
|
404
|
+
#
|
405
|
+
# @param max_len [Integer, nil]
|
406
|
+
# @param out_string [String, nil]
|
407
|
+
#
|
408
|
+
# @return [String, nil]
|
409
|
+
def read(max_len = nil, out_string = nil)
|
410
|
+
case @stream
|
411
|
+
in nil
|
412
|
+
nil
|
413
|
+
in IO | StringIO
|
414
|
+
@stream.read(max_len, out_string)
|
415
|
+
in Enumerator
|
416
|
+
read = read_enum(max_len)
|
417
|
+
case out_string
|
418
|
+
in String
|
419
|
+
out_string.replace(read)
|
420
|
+
in nil
|
421
|
+
read
|
422
|
+
end
|
423
|
+
end
|
424
|
+
.tap(&@blk)
|
425
|
+
end
|
426
|
+
|
427
|
+
# @api private
|
428
|
+
#
|
429
|
+
# @param stream [String, IO, StringIO, Enumerable]
|
430
|
+
# @param blk [Proc]
|
431
|
+
def initialize(stream, &blk)
|
432
|
+
@stream = stream.is_a?(String) ? StringIO.new(stream) : stream
|
433
|
+
@buf = String.new.b
|
434
|
+
@blk = blk
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
402
438
|
class << self
|
403
|
-
# @
|
439
|
+
# @param blk [Proc]
|
440
|
+
#
|
441
|
+
# @return [Enumerable]
|
442
|
+
def string_io(&blk)
|
443
|
+
Enumerator.new do |y|
|
444
|
+
y.define_singleton_method(:write) do
|
445
|
+
self << _1.clone
|
446
|
+
_1.bytesize
|
447
|
+
end
|
448
|
+
|
449
|
+
blk.call(y)
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
class << self
|
455
|
+
# @api private
|
404
456
|
#
|
405
|
-
# @param
|
457
|
+
# @param y [Enumerator::Yielder]
|
406
458
|
# @param boundary [String]
|
407
459
|
# @param key [Symbol, String]
|
408
460
|
# @param val [Object]
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
io << "Content-Disposition: form-data"
|
461
|
+
private def encode_multipart_formdata(y, boundary:, key:, val:)
|
462
|
+
y << "--#{boundary}\r\n"
|
463
|
+
y << "Content-Disposition: form-data"
|
413
464
|
unless key.nil?
|
414
465
|
name = ERB::Util.url_encode(key.to_s)
|
415
|
-
|
466
|
+
y << "; name=\"#{name}\""
|
416
467
|
end
|
417
468
|
if val.is_a?(IO)
|
418
469
|
filename = ERB::Util.url_encode(File.basename(val.to_path))
|
419
|
-
|
470
|
+
y << "; filename=\"#{filename}\""
|
420
471
|
end
|
421
|
-
|
472
|
+
y << "\r\n"
|
422
473
|
case val
|
423
|
-
in IO
|
424
|
-
|
425
|
-
IO.copy_stream(val,
|
474
|
+
in IO
|
475
|
+
y << "Content-Type: application/octet-stream\r\n\r\n"
|
476
|
+
IO.copy_stream(val, y)
|
477
|
+
in StringIO
|
478
|
+
y << "Content-Type: application/octet-stream\r\n\r\n"
|
479
|
+
y << val.string
|
426
480
|
in String
|
427
|
-
|
428
|
-
|
481
|
+
y << "Content-Type: application/octet-stream\r\n\r\n"
|
482
|
+
y << val.to_s
|
429
483
|
in true | false | Integer | Float | Symbol
|
430
|
-
|
431
|
-
|
484
|
+
y << "Content-Type: text/plain\r\n\r\n"
|
485
|
+
y << val.to_s
|
432
486
|
else
|
433
|
-
|
434
|
-
|
487
|
+
y << "Content-Type: application/json\r\n\r\n"
|
488
|
+
y << JSON.fast_generate(val)
|
435
489
|
end
|
436
|
-
|
490
|
+
y << "\r\n"
|
437
491
|
end
|
438
492
|
|
439
|
-
# @private
|
493
|
+
# @api private
|
494
|
+
#
|
495
|
+
# @param body [Object]
|
496
|
+
#
|
497
|
+
# @return [Array(String, Enumerable)]
|
498
|
+
private def encode_multipart_streaming(body)
|
499
|
+
boundary = SecureRandom.urlsafe_base64(60)
|
500
|
+
|
501
|
+
strio = string_io do |y|
|
502
|
+
case body
|
503
|
+
in Hash
|
504
|
+
body.each do |key, val|
|
505
|
+
case val
|
506
|
+
in Array if val.all? { primitive?(_1) }
|
507
|
+
val.each do |v|
|
508
|
+
encode_multipart_formdata(y, boundary: boundary, key: key, val: v)
|
509
|
+
end
|
510
|
+
else
|
511
|
+
encode_multipart_formdata(y, boundary: boundary, key: key, val: val)
|
512
|
+
end
|
513
|
+
end
|
514
|
+
else
|
515
|
+
encode_multipart_formdata(y, boundary: boundary, key: nil, val: body)
|
516
|
+
end
|
517
|
+
y << "--#{boundary}--\r\n"
|
518
|
+
end
|
519
|
+
|
520
|
+
[boundary, strio]
|
521
|
+
end
|
522
|
+
|
523
|
+
# @api private
|
440
524
|
#
|
441
525
|
# @param headers [Hash{String=>String}]
|
442
526
|
# @param body [Object]
|
443
527
|
#
|
444
528
|
# @return [Object]
|
445
|
-
#
|
446
529
|
def encode_content(headers, body)
|
447
530
|
content_type = headers["content-type"]
|
448
531
|
case [content_type, body]
|
449
|
-
in [
|
532
|
+
in [%r{^application/(?:vnd\.api\+)?json}, Hash | Array]
|
450
533
|
[headers, JSON.fast_generate(body)]
|
534
|
+
in [%r{^application/(?:x-)?jsonl}, Enumerable]
|
535
|
+
[headers, body.lazy.map { JSON.fast_generate(_1) }]
|
451
536
|
in [%r{^multipart/form-data}, Hash | IO | StringIO]
|
452
|
-
boundary =
|
453
|
-
|
454
|
-
case body
|
455
|
-
in Hash
|
456
|
-
body.each do |key, val|
|
457
|
-
case val
|
458
|
-
in Array if val.all? { primitive?(_1) }
|
459
|
-
val.each do |v|
|
460
|
-
encode_multipart_formdata(io, boundary: boundary, key: key, val: v)
|
461
|
-
end
|
462
|
-
else
|
463
|
-
encode_multipart_formdata(io, boundary: boundary, key: key, val: val)
|
464
|
-
end
|
465
|
-
end
|
466
|
-
else
|
467
|
-
encode_multipart_formdata(io, boundary: boundary, key: nil, val: body)
|
468
|
-
end
|
469
|
-
io << "--#{boundary}--\r\n"
|
470
|
-
io.rewind
|
471
|
-
end
|
472
|
-
headers = {
|
473
|
-
**headers,
|
474
|
-
"content-type" => "#{content_type}; boundary=#{boundary}",
|
475
|
-
"transfer-encoding" => "chunked"
|
476
|
-
}
|
537
|
+
boundary, strio = encode_multipart_streaming(body)
|
538
|
+
headers = {**headers, "content-type" => "#{content_type}; boundary=#{boundary}"}
|
477
539
|
[headers, strio]
|
478
540
|
in [_, StringIO]
|
479
541
|
[headers, body.string]
|
480
|
-
in [_, IO]
|
481
|
-
headers = {**headers, "transfer-encoding" => "chunked"}
|
482
|
-
[headers, body]
|
483
542
|
else
|
484
543
|
[headers, body]
|
485
544
|
end
|
486
545
|
end
|
487
546
|
|
488
|
-
# @private
|
547
|
+
# @api private
|
489
548
|
#
|
490
549
|
# @param headers [Hash{String=>String}, Net::HTTPHeader]
|
491
550
|
# @param stream [Enumerable]
|
@@ -493,10 +552,9 @@ module OnebusawaySDK
|
|
493
552
|
#
|
494
553
|
# @raise [JSON::ParserError]
|
495
554
|
# @return [Object]
|
496
|
-
#
|
497
555
|
def decode_content(headers, stream:, suppress_error: false)
|
498
556
|
case headers["content-type"]
|
499
|
-
in %r{^application/json}
|
557
|
+
in %r{^application/(?:vnd\.api\+)?json}
|
500
558
|
json = stream.to_a.join
|
501
559
|
begin
|
502
560
|
JSON.parse(json, symbolize_names: true)
|
@@ -504,6 +562,14 @@ module OnebusawaySDK
|
|
504
562
|
raise e unless suppress_error
|
505
563
|
json
|
506
564
|
end
|
565
|
+
in %r{^application/(?:x-)?jsonl}
|
566
|
+
lines = decode_lines(stream)
|
567
|
+
chain_fused(lines) do |y|
|
568
|
+
lines.each { y << JSON.parse(_1, symbolize_names: true) }
|
569
|
+
end
|
570
|
+
in %r{^text/event-stream}
|
571
|
+
lines = decode_lines(stream)
|
572
|
+
decode_sse(lines)
|
507
573
|
in %r{^text/}
|
508
574
|
stream.to_a.join
|
509
575
|
else
|
@@ -512,6 +578,141 @@ module OnebusawaySDK
|
|
512
578
|
end
|
513
579
|
end
|
514
580
|
end
|
581
|
+
|
582
|
+
class << self
|
583
|
+
# @api private
|
584
|
+
#
|
585
|
+
# https://doc.rust-lang.org/std/iter/trait.FusedIterator.html
|
586
|
+
#
|
587
|
+
# @param enum [Enumerable]
|
588
|
+
# @param external [Boolean]
|
589
|
+
# @param close [Proc]
|
590
|
+
#
|
591
|
+
# @return [Enumerable]
|
592
|
+
def fused_enum(enum, external: false, &close)
|
593
|
+
fused = false
|
594
|
+
iter = Enumerator.new do |y|
|
595
|
+
next if fused
|
596
|
+
|
597
|
+
fused = true
|
598
|
+
if external
|
599
|
+
loop { y << enum.next }
|
600
|
+
else
|
601
|
+
enum.each(&y)
|
602
|
+
end
|
603
|
+
ensure
|
604
|
+
close&.call
|
605
|
+
close = nil
|
606
|
+
end
|
607
|
+
|
608
|
+
iter.define_singleton_method(:rewind) do
|
609
|
+
fused = true
|
610
|
+
self
|
611
|
+
end
|
612
|
+
iter
|
613
|
+
end
|
614
|
+
|
615
|
+
# @api private
|
616
|
+
#
|
617
|
+
# @param enum [Enumerable, nil]
|
618
|
+
def close_fused!(enum)
|
619
|
+
return unless enum.is_a?(Enumerator)
|
620
|
+
|
621
|
+
# rubocop:disable Lint/UnreachableLoop
|
622
|
+
enum.rewind.each { break }
|
623
|
+
# rubocop:enable Lint/UnreachableLoop
|
624
|
+
end
|
625
|
+
|
626
|
+
# @api private
|
627
|
+
#
|
628
|
+
# @param enum [Enumerable, nil]
|
629
|
+
# @param blk [Proc]
|
630
|
+
#
|
631
|
+
# @return [Enumerable]
|
632
|
+
def chain_fused(enum, &blk)
|
633
|
+
iter = Enumerator.new { blk.call(_1) }
|
634
|
+
fused_enum(iter) { close_fused!(enum) }
|
635
|
+
end
|
636
|
+
end
|
637
|
+
|
638
|
+
class << self
|
639
|
+
# @api private
|
640
|
+
#
|
641
|
+
# @param enum [Enumerable]
|
642
|
+
#
|
643
|
+
# @return [Enumerable]
|
644
|
+
def decode_lines(enum)
|
645
|
+
re = /(\r\n|\r|\n)/
|
646
|
+
buffer = String.new.b
|
647
|
+
cr_seen = nil
|
648
|
+
|
649
|
+
chain_fused(enum) do |y|
|
650
|
+
enum.each do |row|
|
651
|
+
offset = buffer.bytesize
|
652
|
+
buffer << row
|
653
|
+
while (match = re.match(buffer, cr_seen&.to_i || offset))
|
654
|
+
case [match.captures.first, cr_seen]
|
655
|
+
in ["\r", nil]
|
656
|
+
cr_seen = match.end(1)
|
657
|
+
next
|
658
|
+
in ["\r" | "\r\n", Integer]
|
659
|
+
y << buffer.slice!(..(cr_seen.pred))
|
660
|
+
else
|
661
|
+
y << buffer.slice!(..(match.end(1).pred))
|
662
|
+
end
|
663
|
+
offset = 0
|
664
|
+
cr_seen = nil
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
668
|
+
y << buffer.slice!(..(cr_seen.pred)) unless cr_seen.nil?
|
669
|
+
y << buffer unless buffer.empty?
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
# @api private
|
674
|
+
#
|
675
|
+
# https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream
|
676
|
+
#
|
677
|
+
# @param lines [Enumerable]
|
678
|
+
#
|
679
|
+
# @return [Hash{Symbol=>Object}]
|
680
|
+
def decode_sse(lines)
|
681
|
+
# rubocop:disable Metrics/BlockLength
|
682
|
+
chain_fused(lines) do |y|
|
683
|
+
blank = {event: nil, data: nil, id: nil, retry: nil}
|
684
|
+
current = {}
|
685
|
+
|
686
|
+
lines.each do |line|
|
687
|
+
case line.sub(/\R$/, "")
|
688
|
+
in ""
|
689
|
+
next if current.empty?
|
690
|
+
y << {**blank, **current}
|
691
|
+
current = {}
|
692
|
+
in /^:/
|
693
|
+
next
|
694
|
+
in /^([^:]+):\s?(.*)$/
|
695
|
+
field, value = Regexp.last_match.captures
|
696
|
+
case field
|
697
|
+
in "event"
|
698
|
+
current.merge!(event: value)
|
699
|
+
in "data"
|
700
|
+
(current[:data] ||= String.new.b) << (value << "\n")
|
701
|
+
in "id" unless value.include?("\0")
|
702
|
+
current.merge!(id: value)
|
703
|
+
in "retry" if /^\d+$/ =~ value
|
704
|
+
current.merge!(retry: Integer(value))
|
705
|
+
else
|
706
|
+
end
|
707
|
+
else
|
708
|
+
end
|
709
|
+
end
|
710
|
+
# rubocop:enable Metrics/BlockLength
|
711
|
+
|
712
|
+
y << {**blank, **current} unless current.empty?
|
713
|
+
end
|
714
|
+
end
|
715
|
+
end
|
515
716
|
end
|
516
717
|
|
517
718
|
# rubocop:enable Metrics/ModuleLength
|
data/lib/onebusaway-sdk.rb
CHANGED