transit-ruby 0.8.467 → 0.8.539

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.
@@ -17,56 +17,6 @@ module Transit
17
17
  # values/objects in Ruby.
18
18
  # @see https://github.com/cognitect/transit-format
19
19
  class Reader
20
- # @api private
21
- class JsonUnmarshaler
22
- class ParseHandler
23
- def each(&block) @yield_v = block end
24
- def add_value(v) @yield_v[v] if @yield_v end
25
-
26
- def hash_start() {} end
27
- def hash_set(h,k,v) h.store(k,v) end
28
- def array_start() [] end
29
- def array_append(a,v) a << v end
30
-
31
- def error(message, line, column)
32
- raise Exception.new(message, line, column)
33
- end
34
- end
35
-
36
- def initialize(io, opts)
37
- @io = io
38
- @decoder = Transit::Decoder.new(opts)
39
- @parse_handler = ParseHandler.new
40
- end
41
-
42
- # @see Reader#read
43
- def read
44
- if block_given?
45
- @parse_handler.each {|v| yield @decoder.decode(v)}
46
- else
47
- @parse_handler.each {|v| return @decoder.decode(v)}
48
- end
49
- Oj.sc_parse(@parse_handler, @io)
50
- end
51
- end
52
-
53
- # @api private
54
- class MessagePackUnmarshaler
55
- def initialize(io, opts)
56
- @decoder = Transit::Decoder.new(opts)
57
- @unpacker = MessagePack::Unpacker.new(io)
58
- end
59
-
60
- # @see Reader#read
61
- def read
62
- if block_given?
63
- @unpacker.each {|v| yield @decoder.decode(v)}
64
- else
65
- @decoder.decode(@unpacker.read)
66
- end
67
- end
68
- end
69
-
70
20
  extend Forwardable
71
21
 
72
22
  # @!method read
@@ -106,11 +56,9 @@ module Transit
106
56
  def initialize(format, io, opts={})
107
57
  @reader = case format
108
58
  when :json, :json_verbose
109
- require 'oj'
110
- JsonUnmarshaler.new(io, opts)
59
+ Unmarshaler::Json.new(io, opts)
111
60
  else
112
- require 'msgpack'
113
- MessagePackUnmarshaler.new(io, opts)
61
+ Unmarshaler::MessagePack.new(io, opts)
114
62
  end
115
63
  end
116
64
  end
@@ -0,0 +1,55 @@
1
+ # Copyright 2014 Cognitect. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS-IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'oj'
16
+
17
+ module Transit
18
+ module Unmarshaler
19
+ # Transit::Reader::MessagePackUnmarshaler is responsible to read data on CRuby
20
+ # @see https://github.com/cognitect/transit-format
21
+
22
+ # @api private
23
+ class Json
24
+ class ParseHandler
25
+ def each(&block) @yield_v = block end
26
+ def add_value(v) @yield_v[v] if @yield_v end
27
+
28
+ def hash_start() {} end
29
+ def hash_set(h,k,v) h.store(k,v) end
30
+ def array_start() [] end
31
+ def array_append(a,v) a << v end
32
+
33
+ def error(message, line, column)
34
+ raise Exception.new(message, line, column)
35
+ end
36
+ end
37
+
38
+ def initialize(io, opts)
39
+ @io = io
40
+ @decoder = Transit::Decoder.new(opts)
41
+ @parse_handler = ParseHandler.new
42
+ end
43
+
44
+ # @see Reader#read
45
+ def read
46
+ if block_given?
47
+ @parse_handler.each {|v| yield @decoder.decode(v)}
48
+ else
49
+ @parse_handler.each {|v| return @decoder.decode(v)}
50
+ end
51
+ Oj.sc_parse(@parse_handler, @io)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,39 @@
1
+ # Copyright 2014 Cognitect. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS-IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'msgpack'
16
+
17
+ module Transit
18
+ module Unmarshaler
19
+ # Transit::Reader::MessagePackUnmarshaler is responsible to read data on CRuby
20
+ # @see https://github.com/cognitect/transit-format
21
+
22
+ # @api private
23
+ class MessagePack
24
+ def initialize(io, opts)
25
+ @decoder = Transit::Decoder.new(opts)
26
+ @unpacker = ::MessagePack::Unpacker.new(io)
27
+ end
28
+
29
+ # @see Reader#read
30
+ def read
31
+ if block_given?
32
+ @unpacker.each {|v| yield @decoder.decode(v)}
33
+ else
34
+ @decoder.decode(@unpacker.read)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -237,9 +237,26 @@ module Transit
237
237
  end
238
238
 
239
239
  class FloatHandler
240
- def tag(_) "d" end
241
- def rep(f) f end
242
- def string_rep(f) f.to_s end
240
+ def tag(f)
241
+ return "z" if f.nan?
242
+ case f
243
+ when Float::INFINITY, -Float::INFINITY
244
+ "z"
245
+ else
246
+ "d"
247
+ end
248
+ end
249
+
250
+ def rep(f)
251
+ return "NaN" if f.nan?
252
+ case f
253
+ when Float::INFINITY then "INF"
254
+ when -Float::INFINITY then "-INF"
255
+ else f
256
+ end
257
+ end
258
+
259
+ def string_rep(f) rep(f).to_s end
243
260
  end
244
261
 
245
262
  class BigDecimalHandler
@@ -248,6 +265,12 @@ module Transit
248
265
  def string_rep(f) rep(f) end
249
266
  end
250
267
 
268
+ class RationalHandler
269
+ def tag(_) "ratio" end
270
+ def rep(r) [r.numerator, r.denominator] end
271
+ def string_rep(_) nil end
272
+ end
273
+
251
274
  # TimeHandler, DateTimeHandler, and DateHandler all have different
252
275
  # implementations of string_rep. Here is the rationale:
253
276
  #
@@ -330,7 +353,15 @@ module Transit
330
353
 
331
354
  class ByteArrayHandler
332
355
  def tag(_) "b" end
333
- def rep(b) b.to_base64 end
356
+ if Transit::jruby?
357
+ def rep(b)
358
+ b.value.to_java_bytes
359
+ end
360
+ else
361
+ def rep(b)
362
+ b.to_base64
363
+ end
364
+ end
334
365
  def string_rep(b) rep(b) end
335
366
  end
336
367
 
@@ -388,6 +419,7 @@ module Transit
388
419
  Bignum => IntHandler.new,
389
420
  Float => FloatHandler.new,
390
421
  BigDecimal => BigDecimalHandler.new,
422
+ Rational => RationalHandler.new,
391
423
  Time => TimeHandler.new,
392
424
  DateTime => DateTimeHandler.new,
393
425
  Date => DateHandler.new,
@@ -17,279 +17,6 @@ module Transit
17
17
  # @see https://github.com/cognitect/transit-format
18
18
  class Writer
19
19
 
20
- # @api private
21
- class Marshaler
22
- def initialize(opts)
23
- @cache_enabled = !opts[:verbose]
24
- @prefer_strings = opts[:prefer_strings]
25
- @max_int = opts[:max_int]
26
- @min_int = opts[:min_int]
27
-
28
- handlers = WriteHandlers::DEFAULT_WRITE_HANDLERS.dup
29
- handlers = handlers.merge!(opts[:handlers]) if opts[:handlers]
30
- @handlers = (opts[:verbose] ? verbose_handlers(handlers) : handlers)
31
- @handlers.values.each do |h|
32
- if h.respond_to?(:handlers=)
33
- h.handlers=(@handlers)
34
- end
35
- end
36
- end
37
-
38
- def find_handler(obj)
39
- obj.class.ancestors.each do |a|
40
- if handler = @handlers[a]
41
- return handler
42
- end
43
- end
44
- nil
45
- end
46
-
47
- def verbose_handlers(handlers)
48
- handlers.each do |k, v|
49
- if v.respond_to?(:verbose_handler) && vh = v.verbose_handler
50
- handlers.store(k, vh)
51
- end
52
- end
53
- handlers
54
- end
55
-
56
- def escape(s)
57
- if s.start_with?(SUB,ESC,RES) && s != "#{SUB} "
58
- "#{ESC}#{s}"
59
- else
60
- s
61
- end
62
- end
63
-
64
- def emit_nil(as_map_key, cache)
65
- as_map_key ? emit_string(ESC, "_", nil, true, cache) : emit_value(nil)
66
- end
67
-
68
- def emit_string(prefix, tag, value, as_map_key, cache)
69
- encoded = "#{prefix}#{tag}#{value}"
70
- if @cache_enabled && cache.cacheable?(encoded, as_map_key)
71
- emit_value(cache.write(encoded), as_map_key)
72
- else
73
- emit_value(encoded, as_map_key)
74
- end
75
- end
76
-
77
- def emit_boolean(handler, b, as_map_key, cache)
78
- as_map_key ? emit_string(ESC, "?", handler.string_rep(b), true, cache) : emit_value(b)
79
- end
80
-
81
- def emit_int(tag, i, as_map_key, cache)
82
- if as_map_key || i > @max_int || i < @min_int
83
- emit_string(ESC, tag, i, as_map_key, cache)
84
- else
85
- emit_value(i, as_map_key)
86
- end
87
- end
88
-
89
- def emit_double(d, as_map_key, cache)
90
- as_map_key ? emit_string(ESC, "d", d, true, cache) : emit_value(d)
91
- end
92
-
93
- def emit_array(a, cache)
94
- emit_array_start(a.size)
95
- a.each {|e| marshal(e, false, cache)}
96
- emit_array_end
97
- end
98
-
99
- def emit_map(m, cache)
100
- emit_map_start(m.size)
101
- m.each do |k,v|
102
- marshal(k, true, cache)
103
- marshal(v, false, cache)
104
- end
105
- emit_map_end
106
- end
107
-
108
- def emit_tagged_value(tag, rep, cache)
109
- emit_array_start(2)
110
- emit_string(ESC, "#", tag, false, cache)
111
- marshal(rep, false, cache)
112
- emit_array_end
113
- end
114
-
115
- def emit_encoded(handler, tag, obj, as_map_key, cache)
116
- if tag.length == 1
117
- rep = handler.rep(obj)
118
- if String === rep
119
- emit_string(ESC, tag, rep, as_map_key, cache)
120
- elsif as_map_key || @prefer_strings
121
- if str_rep = handler.string_rep(obj)
122
- emit_string(ESC, tag, str_rep, as_map_key, cache)
123
- else
124
- raise "Cannot be encoded as String: " + {:tag => tag, :rep => rep, :obj => obj}.to_s
125
- end
126
- else
127
- emit_tagged_value(tag, handler.rep(obj), cache)
128
- end
129
- elsif as_map_key
130
- raise "Cannot be used as a map key: " + {:tag => tag, :rep => rep, :obj => obj}.to_s
131
- else
132
- emit_tagged_value(tag, handler.rep(obj), cache)
133
- end
134
- end
135
-
136
- def marshal(obj, as_map_key, cache)
137
- handler = find_handler(obj)
138
- tag = handler.tag(obj)
139
- case tag
140
- when "_"
141
- emit_nil(as_map_key, cache)
142
- when "?"
143
- emit_boolean(handler, obj, as_map_key, cache)
144
- when "s"
145
- emit_string(nil, nil, escape(handler.rep(obj)), as_map_key, cache)
146
- when "i"
147
- emit_int(tag, handler.rep(obj), as_map_key, cache)
148
- when "d"
149
- emit_double(handler.rep(obj), as_map_key, cache)
150
- when "'"
151
- emit_tagged_value(tag, handler.rep(obj), cache)
152
- when "array"
153
- emit_array(handler.rep(obj), cache)
154
- when "map"
155
- emit_map(handler.rep(obj), cache)
156
- else
157
- emit_encoded(handler, tag, obj, as_map_key, cache)
158
- end
159
- end
160
-
161
- def marshal_top(obj, cache=RollingCache.new)
162
- if handler = find_handler(obj)
163
- if tag = handler.tag(obj)
164
- if tag.length == 1
165
- marshal(TaggedValue.new(QUOTE, obj), false, cache)
166
- else
167
- marshal(obj, false, cache)
168
- end
169
- flush
170
- else
171
- raise "Handler must provide a non-nil tag: #{handler.inspect}"
172
- end
173
- else
174
- raise "Can not find a Write Handler for #{obj.inspect}."
175
- end
176
- end
177
- end
178
-
179
- # @api private
180
- class BaseJsonMarshaler < Marshaler
181
- def default_opts
182
- {:prefer_strings => true,
183
- :max_int => JSON_MAX_INT,
184
- :min_int => JSON_MIN_INT}
185
- end
186
-
187
- def initialize(io, opts)
188
- @oj = Oj::StreamWriter.new(io)
189
- super(default_opts.merge(opts))
190
- @state = []
191
- end
192
-
193
- def emit_array_start(size)
194
- @state << :array
195
- @oj.push_array
196
- end
197
-
198
- def emit_array_end
199
- @state.pop
200
- @oj.pop
201
- end
202
-
203
- def emit_map_start(size)
204
- @state << :map
205
- @oj.push_object
206
- end
207
-
208
- def emit_map_end
209
- @state.pop
210
- @oj.pop
211
- end
212
-
213
- def emit_value(obj, as_map_key=false)
214
- if @state.last == :array
215
- @oj.push_value(obj)
216
- else
217
- as_map_key ? @oj.push_key(obj) : @oj.push_value(obj)
218
- end
219
- end
220
-
221
- def flush
222
- # no-op
223
- end
224
- end
225
-
226
- # @api private
227
- class JsonMarshaler < BaseJsonMarshaler
228
- def emit_map(m, cache)
229
- emit_array_start(-1)
230
- emit_value("^ ", false)
231
- m.each do |k,v|
232
- marshal(k, true, cache)
233
- marshal(v, false, cache)
234
- end
235
- emit_array_end
236
- end
237
- end
238
-
239
- # @api private
240
- class VerboseJsonMarshaler < BaseJsonMarshaler
241
- def emit_string(prefix, tag, value, as_map_key, cache)
242
- emit_value("#{prefix}#{tag}#{value}", as_map_key)
243
- end
244
-
245
- def emit_tagged_value(tag, rep, cache)
246
- emit_map_start(1)
247
- emit_string(ESC, "#", tag, true, cache)
248
- marshal(rep, false, cache)
249
- emit_map_end
250
- end
251
- end
252
-
253
- # @api private
254
- class MessagePackMarshaler < Marshaler
255
- def default_opts
256
- {:prefer_strings => false,
257
- :max_int => MAX_INT,
258
- :min_int => MIN_INT}
259
- end
260
-
261
- def initialize(io, opts)
262
- @io = io
263
- @packer = MessagePack::Packer.new(io)
264
- super(default_opts.merge(opts))
265
- end
266
-
267
- def emit_array_start(size)
268
- @packer.write_array_header(size)
269
- end
270
-
271
- def emit_array_end
272
- # no-op
273
- end
274
-
275
- def emit_map_start(size)
276
- @packer.write_map_header(size)
277
- end
278
-
279
- def emit_map_end
280
- # no-op
281
- end
282
-
283
- def emit_value(obj, as_map_key=:ignore)
284
- @packer.write(obj)
285
- end
286
-
287
- def flush
288
- @packer.flush
289
- @io.flush
290
- end
291
- end
292
-
293
20
  # @param [Symbol] format required :json, :json_verbose, or :msgpack
294
21
  # @param [IO] io required
295
22
  # @param [Hash] opts optional
@@ -312,23 +39,21 @@ module Transit
312
39
  def initialize(format, io, opts={})
313
40
  @marshaler = case format
314
41
  when :json
315
- require 'oj'
316
- JsonMarshaler.new(io,
42
+ Marshaler::Json.new(io,
317
43
  {:prefer_strings => true,
318
44
  :verbose => false,
319
- :handlers => {}}.merge(opts))
45
+ :handlers => {},
46
+ :oj_opts => {:indent => -1}}.merge(opts))
320
47
  when :json_verbose
321
- require 'oj'
322
- VerboseJsonMarshaler.new(io,
323
- {:prefer_strings => true,
324
- :verbose => true,
325
- :handlers => {}}.merge(opts))
48
+ Marshaler::VerboseJson.new(io,
49
+ {:prefer_strings => true,
50
+ :verbose => true,
51
+ :handlers => {}}.merge(opts))
326
52
  else
327
- require 'msgpack'
328
- MessagePackMarshaler.new(io,
329
- {:prefer_strings => false,
330
- :verbose => false,
331
- :handlers => {}}.merge(opts))
53
+ Marshaler::MessagePack.new(io,
54
+ {:prefer_strings => false,
55
+ :verbose => false,
56
+ :handlers => {}}.merge(opts))
332
57
  end
333
58
  end
334
59
 
@@ -339,8 +64,14 @@ module Transit
339
64
  # @example
340
65
  # writer = Transit::Writer.new(:json, io)
341
66
  # writer.write(Date.new(2014,7,22))
342
- def write(obj)
343
- @marshaler.marshal_top(obj)
67
+ if Transit::jruby?
68
+ def write(obj)
69
+ @marshaler.write(obj)
70
+ end
71
+ else
72
+ def write(obj)
73
+ @marshaler.marshal_top(obj)
74
+ end
344
75
  end
345
76
  end
346
77
  end