transit-ruby 0.8.467 → 0.8.539

Sign up to get free protection for your applications and to get access to all the features.
@@ -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