xnlogic-transit-ruby 0.8.572-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ module Transit
16
+ # @api private
17
+ module DateTimeUtil
18
+ def to_millis(v)
19
+ case v
20
+ when DateTime
21
+ t = v.new_offset(0).to_time
22
+ when Date
23
+ t = Time.gm(v.year, v.month, v.day)
24
+ when Time
25
+ t = v
26
+ else
27
+ raise "Don't know how to get millis from #{t.inspect}"
28
+ end
29
+ (t.to_i * 1000) + (t.usec / 1000.0).round
30
+ end
31
+
32
+ def from_millis(millis)
33
+ t = Time.at(millis / 1000).utc
34
+ DateTime.new(t.year, t.month, t.day, t.hour, t.min, t.sec + (millis % 1000 * 0.001))
35
+ end
36
+
37
+ module_function :to_millis, :from_millis
38
+ end
39
+ end
@@ -0,0 +1,123 @@
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
+ module Transit
16
+ # Converts a transit value to an instance of a type
17
+ # @api private
18
+ class Decoder
19
+ MUTEX = Mutex.new
20
+ HANDLER_CACHE = {}
21
+
22
+ ESC_ESC = "#{ESC}#{ESC}"
23
+ ESC_SUB = "#{ESC}#{SUB}"
24
+ ESC_RES = "#{ESC}#{RES}"
25
+
26
+ IDENTITY = ->(v){v}
27
+
28
+ GROUND_TAGS = %w[_ s ? i d b ' array map]
29
+
30
+ def initialize(options={})
31
+ custom_handlers = options[:handlers] || {}
32
+ custom_handlers.each {|k,v| validate_handler(k,v)}
33
+ MUTEX.synchronize do
34
+ if HANDLER_CACHE.has_key?(custom_handlers)
35
+ @handlers = HANDLER_CACHE[custom_handlers]
36
+ else
37
+ @handlers = ReadHandlers::DEFAULT_READ_HANDLERS.merge(custom_handlers)
38
+ end
39
+
40
+ end
41
+ @default_handler = options[:default_handler] || ReadHandlers::DEFAULT_READ_HANDLER
42
+ end
43
+
44
+ # @api private
45
+ class Tag < String; end
46
+
47
+ # Decodes a transit value to a corresponding object
48
+ #
49
+ # @param node a transit value to be decoded
50
+ # @param cache
51
+ # @param as_map_key
52
+ # @return decoded object
53
+ def decode(node, cache=RollingCache.new, as_map_key=false)
54
+ case node
55
+ when String
56
+ if cache.has_key?(node)
57
+ cache.read(node)
58
+ else
59
+ parsed = if !node.start_with?(ESC)
60
+ node
61
+ elsif node.start_with?(TAG)
62
+ Tag.new(node[2..-1])
63
+ elsif handler = @handlers[node[1]]
64
+ handler.from_rep(node[2..-1])
65
+ elsif node.start_with?(ESC_ESC, ESC_SUB, ESC_RES)
66
+ node[1..-1]
67
+ else
68
+ @default_handler.from_rep(node[1], node[2..-1])
69
+ end
70
+ if cache.cacheable?(node, as_map_key)
71
+ cache.write(parsed)
72
+ end
73
+ parsed
74
+ end
75
+ when Array
76
+ return node if node.empty?
77
+ e0 = decode(node.shift, cache, false)
78
+ if e0 == MAP_AS_ARRAY
79
+ decode(Hash[*node], cache)
80
+ elsif Tag === e0
81
+ v = decode(node.shift, cache)
82
+ if handler = @handlers[e0]
83
+ handler.from_rep(v)
84
+ else
85
+ @default_handler.from_rep(e0,v)
86
+ end
87
+ else
88
+ [e0] + node.map {|e| decode(e, cache, as_map_key)}
89
+ end
90
+ when Hash
91
+ if node.size == 1
92
+ k = decode(node.keys.first, cache, true)
93
+ v = decode(node.values.first, cache, false)
94
+ if Tag === k
95
+ if handler = @handlers[k]
96
+ handler.from_rep(v)
97
+ else
98
+ @default_handler.from_rep(k,v)
99
+ end
100
+ else
101
+ {k => v}
102
+ end
103
+ else
104
+ node.keys.each do |k|
105
+ node.store(decode(k, cache, true), decode(node.delete(k), cache))
106
+ end
107
+ node
108
+ end
109
+ else
110
+ node
111
+ end
112
+ end
113
+
114
+ def validate_handler(key, handler)
115
+ raise ArgumentError.new(CAN_NOT_OVERRIDE_GROUND_TYPES_MESSAGE) if GROUND_TAGS.include?(key)
116
+ end
117
+
118
+ CAN_NOT_OVERRIDE_GROUND_TYPES_MESSAGE = <<-MSG
119
+ You can not supply custom read handlers for ground types.
120
+ MSG
121
+
122
+ end
123
+ end
@@ -0,0 +1,193 @@
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
+ module Transit
16
+ # Transit::Writer marshals Ruby objects as transit values to an output stream.
17
+ # @see https://github.com/cognitect/transit-format
18
+ module Marshaler
19
+
20
+ HANDLER_CACHE = {}
21
+ VERBOSE_HANDLER_CACHE = {}
22
+ MUTEX = Mutex.new
23
+
24
+ # @api private
25
+ # Included in VerboseJson subclasses. Defined here to make it
26
+ # available in CRuby and JRuby environments.
27
+ module VerboseHandlers
28
+ def build_handlers(custom_handlers)
29
+ if VERBOSE_HANDLER_CACHE.has_key?(custom_handlers)
30
+ VERBOSE_HANDLER_CACHE[custom_handlers]
31
+ else
32
+ handlers = super(custom_handlers).reduce({}) do |h, (k,v)|
33
+ if v.respond_to?(:verbose_handler) && vh = v.verbose_handler
34
+ h.store(k, vh)
35
+ else
36
+ h.store(k, v)
37
+ end
38
+ h
39
+ end
40
+ VERBOSE_HANDLER_CACHE[custom_handlers] = handlers
41
+ handlers
42
+ end
43
+ end
44
+ end
45
+
46
+ # @api private
47
+ module Base
48
+ def parse_options(opts)
49
+ MUTEX.synchronize do
50
+ @handlers = build_handlers(opts[:handlers])
51
+ end
52
+ @handlers.values.each { |h| h.handlers=(@handlers) if h.respond_to?(:handlers=) }
53
+ end
54
+
55
+ def build_handlers(custom_handlers)
56
+ if HANDLER_CACHE.has_key?(custom_handlers)
57
+ HANDLER_CACHE[custom_handlers]
58
+ else
59
+ handlers = WriteHandlers::DEFAULT_WRITE_HANDLERS.dup
60
+ handlers.merge!(custom_handlers) if custom_handlers
61
+ HANDLER_CACHE[custom_handlers] = handlers
62
+ handlers
63
+ end
64
+ end
65
+
66
+ def find_handler(obj)
67
+ obj.class.ancestors.each do |a|
68
+ if handler = @handlers[a]
69
+ return handler
70
+ end
71
+ end
72
+ nil
73
+ end
74
+
75
+ def escape(s)
76
+ if s.start_with?(SUB,ESC,RES) && s != "#{SUB} "
77
+ "#{ESC}#{s}"
78
+ else
79
+ s
80
+ end
81
+ end
82
+
83
+ def emit_nil(as_map_key, cache)
84
+ as_map_key ? emit_string(ESC, "_", nil, true, cache) : emit_value(nil)
85
+ end
86
+
87
+ def emit_string(prefix, tag, value, as_map_key, cache)
88
+ encoded = "#{prefix}#{tag}#{value}"
89
+ if cache.cacheable?(encoded, as_map_key)
90
+ emit_value(cache.write(encoded), as_map_key)
91
+ else
92
+ emit_value(encoded, as_map_key)
93
+ end
94
+ end
95
+
96
+ def emit_boolean(handler, b, as_map_key, cache)
97
+ as_map_key ? emit_string(ESC, "?", handler.string_rep(b), true, cache) : emit_value(b)
98
+ end
99
+
100
+ def emit_double(d, as_map_key, cache)
101
+ as_map_key ? emit_string(ESC, "d", d, true, cache) : emit_value(d)
102
+ end
103
+
104
+ def emit_array(a, cache)
105
+ emit_array_start(a.size)
106
+ a.each {|e| marshal(e, false, cache)}
107
+ emit_array_end
108
+ end
109
+
110
+ def emit_map(m, cache)
111
+ emit_map_start(m.size)
112
+ m.each do |k,v|
113
+ marshal(k, true, cache)
114
+ marshal(v, false, cache)
115
+ end
116
+ emit_map_end
117
+ end
118
+
119
+ def emit_tagged_value(tag, rep, cache)
120
+ emit_array_start(2)
121
+ emit_string(ESC, "#", tag, false, cache)
122
+ marshal(rep, false, cache)
123
+ emit_array_end
124
+ end
125
+
126
+ def emit_encoded(handler, tag, obj, as_map_key, cache)
127
+ if tag.length == 1
128
+ rep = handler.rep(obj)
129
+ if String === rep
130
+ emit_string(ESC, tag, rep, as_map_key, cache)
131
+ elsif as_map_key || @prefer_strings
132
+ if str_rep = handler.string_rep(obj)
133
+ emit_string(ESC, tag, str_rep, as_map_key, cache)
134
+ else
135
+ raise "Cannot be encoded as String: " + {:tag => tag, :rep => rep, :obj => obj}.to_s
136
+ end
137
+ else
138
+ emit_tagged_value(tag, handler.rep(obj), cache)
139
+ end
140
+ elsif as_map_key
141
+ raise "Cannot be used as a map key: " + {:tag => tag, :rep => rep, :obj => obj}.to_s
142
+ else
143
+ emit_tagged_value(tag, handler.rep(obj), cache)
144
+ end
145
+ end
146
+
147
+ def marshal(obj, as_map_key, cache)
148
+ if handler = find_handler(obj)
149
+ tag = handler.tag(obj)
150
+ case tag
151
+ when "_"
152
+ emit_nil(as_map_key, cache)
153
+ when "?"
154
+ emit_boolean(handler, obj, as_map_key, cache)
155
+ when "s"
156
+ emit_string(nil, nil, escape(handler.rep(obj)), as_map_key, cache)
157
+ when "i"
158
+ emit_int(tag, handler.rep(obj), as_map_key, cache)
159
+ when "d"
160
+ emit_double(handler.rep(obj), as_map_key, cache)
161
+ when "'"
162
+ emit_tagged_value(tag, handler.rep(obj), cache)
163
+ when "array"
164
+ emit_array(handler.rep(obj), cache)
165
+ when "map"
166
+ emit_map(handler.rep(obj), cache)
167
+ else
168
+ emit_encoded(handler, tag, obj, as_map_key, cache)
169
+ end
170
+ else
171
+ raise "Can not find a Write Handler for #{obj.inspect}."
172
+ end
173
+ end
174
+
175
+ def marshal_top(obj, cache=RollingCache.new)
176
+ if handler = find_handler(obj)
177
+ if tag = handler.tag(obj)
178
+ if tag.length == 1
179
+ marshal(TaggedValue.new(QUOTE, obj), false, cache)
180
+ else
181
+ marshal(obj, false, cache)
182
+ end
183
+ flush
184
+ else
185
+ raise "Handler must provide a non-nil tag: #{handler.inspect}"
186
+ end
187
+ else
188
+ raise "Can not find a Write Handler for #{obj.inspect}."
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,38 @@
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
+ module Transit
16
+ module Marshaler
17
+
18
+ # @api private
19
+ module JsonBase
20
+ def initialize(io, opts)
21
+ parse_options(opts)
22
+ end
23
+ end
24
+
25
+ # @api private
26
+ class Json
27
+ include Transit::Marshaler::Base
28
+ include Transit::Marshaler::JsonBase
29
+ end
30
+
31
+ # @api private
32
+ class VerboseJson
33
+ include Transit::Marshaler::Base
34
+ include Transit::Marshaler::JsonBase
35
+ include Transit::Marshaler::VerboseHandlers
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,25 @@
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
+ module Transit
16
+ module Marshaler
17
+ class MessagePack
18
+ include Transit::Marshaler::Base
19
+
20
+ def initialize(io, opts)
21
+ parse_options(opts)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,113 @@
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
+ module Transit
16
+ # @see Transit::WriteHandlers
17
+ module ReadHandlers
18
+ class Default
19
+ def from_rep(tag,val) TaggedValue.new(tag, val) end
20
+ end
21
+ class NilHandler
22
+ def from_rep(_) nil end
23
+ end
24
+ class KeywordHandler
25
+ def from_rep(v) v.to_sym end
26
+ end
27
+ class BooleanHandler
28
+ def from_rep(v) v == "t" end
29
+ end
30
+ class ByteArrayHandler
31
+ def from_rep(v) ByteArray.from_base64(v) end
32
+ end
33
+ class FloatHandler
34
+ def from_rep(v) Float(v) end
35
+ end
36
+ class IntegerHandler
37
+ def from_rep(v) v.to_i end
38
+ end
39
+ class BigIntegerHandler
40
+ def from_rep(v) v.to_i end
41
+ end
42
+ class BigDecimalHandler
43
+ def from_rep(v) BigDecimal.new(v) end
44
+ end
45
+ class SpecialNumbersHandler
46
+ def from_rep(v)
47
+ case v
48
+ when "NaN" then Float::NAN
49
+ when "INF" then Float::INFINITY
50
+ when "-INF" then -Float::INFINITY
51
+ else raise ArgumentError.new("Don't know how to handle #{v.inspect} for the \"z\" tag")
52
+ end
53
+ end
54
+ end
55
+ class IdentityHandler
56
+ def from_rep(v) v end
57
+ end
58
+ class SymbolHandler
59
+ def from_rep(v) Transit::Symbol.new(v) end
60
+ end
61
+ class TimeStringHandler
62
+ def from_rep(v) DateTime.iso8601(v) end
63
+ end
64
+ class TimeIntHandler
65
+ def from_rep(v) DateTimeUtil.from_millis(v.to_i) end
66
+ end
67
+ class UuidHandler
68
+ def from_rep(v) UUID.new(v) end
69
+ end
70
+ class UriHandler
71
+ def from_rep(v) Addressable::URI.parse(v) end
72
+ end
73
+ class SetHandler
74
+ def from_rep(v) Set.new(v) end
75
+ end
76
+ class LinkHandler
77
+ def from_rep(v) Link.new(v) end
78
+ end
79
+ class CmapHandler
80
+ def from_rep(v) Hash[*v] end
81
+ end
82
+ class RatioHandler
83
+ def from_rep(v) Rational(v[0], v[1]) end
84
+ end
85
+
86
+ DEFAULT_READ_HANDLERS = {
87
+ "_" => NilHandler.new,
88
+ ":" => KeywordHandler.new,
89
+ "?" => BooleanHandler.new,
90
+ "b" => ByteArrayHandler.new,
91
+ "d" => FloatHandler.new,
92
+ "i" => IntegerHandler.new,
93
+ "n" => BigIntegerHandler.new,
94
+ "f" => BigDecimalHandler.new,
95
+ "c" => IdentityHandler.new,
96
+ "$" => SymbolHandler.new,
97
+ "t" => TimeStringHandler.new,
98
+ "m" => TimeIntHandler.new,
99
+ "u" => UuidHandler.new,
100
+ "r" => UriHandler.new,
101
+ "'" => IdentityHandler.new,
102
+ "z" => SpecialNumbersHandler.new,
103
+ "set" => SetHandler.new,
104
+ "link" => LinkHandler.new,
105
+ "list" => IdentityHandler.new,
106
+ "cmap" => CmapHandler.new,
107
+ "ratio" => RatioHandler.new
108
+ }.freeze
109
+
110
+ DEFAULT_READ_HANDLER = Default.new
111
+
112
+ end
113
+ end