mrpin-rocketamf 1.0.4 → 2.0.0

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +1 -1
  3. data/Rakefile +7 -7
  4. data/benchmark.rb +44 -37
  5. data/ext/rocketamf_ext/class_mapping.c +11 -11
  6. data/ext/rocketamf_ext/remoting.c +1 -1
  7. data/lib/rocketamf.rb +41 -98
  8. data/lib/rocketamf/constants.rb +20 -20
  9. data/lib/rocketamf/errors.rb +2 -0
  10. data/lib/rocketamf/errors/amf_error.rb +5 -0
  11. data/lib/rocketamf/errors/amf_error_incomplete.rb +5 -0
  12. data/lib/rocketamf/ext.rb +0 -6
  13. data/lib/rocketamf/extensions.rb +4 -4
  14. data/lib/rocketamf/{class_mapping.rb → mapping/class_mapping.rb} +70 -103
  15. data/lib/rocketamf/mapping/mapping_set.rb +63 -0
  16. data/lib/rocketamf/pure.rb +1 -9
  17. data/lib/rocketamf/pure/deserializer.rb +234 -262
  18. data/lib/rocketamf/pure/helpers/io_helper_base.rb +19 -0
  19. data/lib/rocketamf/pure/helpers/io_helper_read.rb +67 -0
  20. data/lib/rocketamf/pure/helpers/io_helper_write.rb +48 -0
  21. data/lib/rocketamf/pure/helpers/object_cache.rb +20 -0
  22. data/lib/rocketamf/pure/helpers/string_cache.rb +14 -0
  23. data/lib/rocketamf/pure/serializer.rb +138 -271
  24. data/lib/rocketamf/types.rb +1 -0
  25. data/lib/rocketamf/{values → types}/typed_hash.rb +12 -2
  26. data/mrpin-rocketamf.gemspec +27 -16
  27. data/spec/class_mapping_spec.rb +59 -52
  28. data/spec/deserializer_spec.rb +164 -328
  29. data/spec/fast_class_mapping_spec.rb +52 -46
  30. data/spec/helpers/class_mapping_test.rb +4 -0
  31. data/spec/helpers/class_mapping_test2.rb +3 -0
  32. data/spec/helpers/externalizable_test.rb +24 -0
  33. data/spec/helpers/fixtures.rb +28 -0
  34. data/spec/helpers/other_class.rb +4 -0
  35. data/spec/helpers/ruby_class.rb +4 -0
  36. data/spec/helpers/test_ruby_class.rb +4 -0
  37. data/spec/serializer_spec.rb +248 -339
  38. data/spec/spec_helper.rb +4 -49
  39. metadata +47 -53
  40. data/lib/rocketamf/pure/io_helpers.rb +0 -94
  41. data/lib/rocketamf/pure/remoting.rb +0 -117
  42. data/lib/rocketamf/remoting.rb +0 -196
  43. data/lib/rocketamf/values/messages.rb +0 -214
  44. data/spec/fixtures/objects/amf0-boolean.bin +0 -1
  45. data/spec/fixtures/objects/amf0-complex-encoded-string.bin +0 -0
  46. data/spec/fixtures/objects/amf0-date.bin +0 -0
  47. data/spec/fixtures/objects/amf0-ecma-ordinal-array.bin +0 -0
  48. data/spec/fixtures/objects/amf0-empty-string-key-hash.bin +0 -0
  49. data/spec/fixtures/objects/amf0-hash.bin +0 -0
  50. data/spec/fixtures/objects/amf0-null.bin +0 -1
  51. data/spec/fixtures/objects/amf0-number.bin +0 -0
  52. data/spec/fixtures/objects/amf0-object.bin +0 -0
  53. data/spec/fixtures/objects/amf0-ref-test.bin +0 -0
  54. data/spec/fixtures/objects/amf0-strict-array.bin +0 -0
  55. data/spec/fixtures/objects/amf0-string.bin +0 -0
  56. data/spec/fixtures/objects/amf0-time.bin +0 -0
  57. data/spec/fixtures/objects/amf0-typed-object.bin +0 -0
  58. data/spec/fixtures/objects/amf0-undefined.bin +0 -1
  59. data/spec/fixtures/objects/amf0-untyped-object.bin +0 -0
  60. data/spec/fixtures/objects/amf0-xml-doc.bin +0 -0
  61. data/spec/messages_spec.rb +0 -39
  62. data/spec/remoting_spec.rb +0 -196
@@ -0,0 +1,19 @@
1
+ module RocketAMF
2
+ module Pure
3
+ module IOHelperBase
4
+
5
+ def byte_order
6
+ if [0x12345678].pack('L') == "\x12\x34\x56\x78"
7
+ :BigEndian
8
+ else
9
+ :LittleEndian
10
+ end
11
+ end
12
+
13
+ def byte_order_little?
14
+ byte_order == :LittleEndian
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,67 @@
1
+ require 'rocketamf/pure/helpers/io_helper_base'
2
+
3
+ module RocketAMF
4
+ module Pure
5
+ module IOHelperRead #:nodoc:
6
+
7
+ include IOHelperBase
8
+
9
+ #
10
+ # Methods
11
+ #
12
+
13
+ public
14
+ def read_int8(source)
15
+ raise AMFErrorIncomplete.new if source.eof?
16
+
17
+ source.read(1).unpack('c').first
18
+ end
19
+
20
+ public
21
+ def read_word8(source)
22
+ raise AMFErrorIncomplete.new if source.eof?
23
+
24
+ source.read(1).unpack('C').first
25
+ end
26
+
27
+ public
28
+ def read_double(source)
29
+ bytes_to_read = 8
30
+
31
+ raise AMFErrorIncomplete.new if bytes_to_read > (source.size - source.pos)
32
+
33
+ source.read(bytes_to_read).unpack('G').first
34
+ end
35
+
36
+ public
37
+ def read_word16_network(source)
38
+ bytes_to_read = 2
39
+
40
+ raise AMFErrorIncomplete.new if bytes_to_read > (source.size - source.pos)
41
+
42
+ source.read(2).unpack('n').first
43
+ end
44
+
45
+ public
46
+ def read_int16_network(source)
47
+ bytes_to_read = 2
48
+
49
+ raise AMFErrorIncomplete.new if bytes_to_read > (source.size - source.pos)
50
+
51
+ result = source.read(bytes_to_read)
52
+ result.reverse! if byte_order_little? # swap bytes as native=little (and we want network)
53
+ result.unpack('s').first
54
+ end
55
+
56
+ public
57
+ def read_word32_network(source)
58
+ bytes_to_read = 4
59
+
60
+ raise AMFErrorIncomplete.new if bytes_to_read > (source.size - source.pos)
61
+
62
+ source.read(bytes_to_read).unpack('N').first
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,48 @@
1
+ require 'rocketamf/pure/helpers/io_helper_base'
2
+
3
+ module RocketAMF
4
+ module Pure
5
+ module IOHelperWrite #:nodoc:
6
+
7
+ include IOHelperBase
8
+
9
+ def pack_integer(integer)
10
+ integer = integer & 0x1fffffff
11
+ if integer < 0x80
12
+ [integer].pack('c')
13
+ elsif integer < 0x4000
14
+ [integer >> 7 & 0x7f | 0x80].pack('c')+
15
+ [integer & 0x7f].pack('c')
16
+ elsif integer < 0x200000
17
+ [integer >> 14 & 0x7f | 0x80].pack('c') +
18
+ [integer >> 7 & 0x7f | 0x80].pack('c') +
19
+ [integer & 0x7f].pack('c')
20
+ else
21
+ [integer >> 22 & 0x7f | 0x80].pack('c')+
22
+ [integer >> 15 & 0x7f | 0x80].pack('c')+
23
+ [integer >> 8 & 0x7f | 0x80].pack('c')+
24
+ [integer & 0xff].pack('c')
25
+ end
26
+ end
27
+
28
+ def pack_double(double)
29
+ [double].pack('G')
30
+ end
31
+
32
+ def pack_int8(val)
33
+ [val].pack('c')
34
+ end
35
+
36
+ def pack_int16_network(val)
37
+ [val].pack('n')
38
+ end
39
+
40
+ def pack_word32_network(val)
41
+ result = [val].pack('L')
42
+ result.reverse! if byte_order_little? # swap bytes as native=little (and we want network)
43
+ result
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,20 @@
1
+ module RocketAMF
2
+ module Pure
3
+ class ObjectCache < Hash #:nodoc:
4
+ def initialize
5
+ @cache_index = 0
6
+ @obj_references = []
7
+ end
8
+
9
+ def [](obj)
10
+ super(obj.object_id)
11
+ end
12
+
13
+ def add_obj(obj)
14
+ @obj_references << obj
15
+ self[obj.object_id] = @cache_index
16
+ @cache_index += 1
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ module RocketAMF
2
+ module Pure
3
+ class StringCache < Hash #:nodoc:
4
+ def initialize
5
+ @cache_index = 0
6
+ end
7
+
8
+ def add_obj(str)
9
+ self[str] = @cache_index
10
+ @cache_index += 1
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,195 +1,78 @@
1
- require 'rocketamf/pure/io_helpers'
1
+ require 'rocketamf/pure/helpers/io_helper_write'
2
+ require 'rocketamf/pure/helpers/object_cache'
3
+ require 'rocketamf/pure/helpers/string_cache'
2
4
 
3
5
  module RocketAMF
4
6
  module Pure
5
- # Pure ruby serializer for AMF0 and AMF3
7
+ # Pure ruby serializer for AMF3
6
8
  class Serializer
7
- attr_reader :stream, :version
9
+
10
+ #
11
+ # Modules
12
+ #
13
+
14
+ private
15
+ include RocketAMF::Pure::IOHelperWrite
16
+
17
+ #
18
+ # Properties
19
+ #
20
+
21
+ public
22
+ attr_reader :stream
8
23
 
9
24
  # Pass in the class mapper instance to use when serializing. This enables
10
25
  # better caching behavior in the class mapper and allows one to change
11
26
  # mappings between serialization attempts.
12
- def initialize class_mapper
27
+ public
28
+ def initialize(class_mapper)
13
29
  @class_mapper = class_mapper
14
- @stream = ""
15
- @depth = 0
30
+ @stream = ''
31
+ @depth = 0
16
32
  end
17
33
 
18
- # Serialize the given object using AMF0 or AMF3. Can be called from inside
19
- # encode_amf, but make sure to pass in the proper version or it may not be
20
- # possible to decode. Use the serializer version attribute for this.
21
- def serialize version, obj
22
- raise ArgumentError, "unsupported version #{version}" unless [0,3].include?(version)
23
- @version = version
24
-
34
+ # Serialize the given object using AMF3. Can be called from inside
35
+ # encode_amf.
36
+ def serialize(obj)
25
37
  # Initialize caches
26
38
  if @depth == 0
27
- if @version == 0
28
- @ref_cache = SerializerCache.new :object
29
- else
30
- @string_cache = SerializerCache.new :string
31
- @object_cache = SerializerCache.new :object
32
- @trait_cache = SerializerCache.new :string
33
- end
39
+ @string_cache = StringCache.new
40
+ @object_cache = ObjectCache.new
41
+ @trait_cache = StringCache.new
34
42
  end
35
43
  @depth += 1
36
44
 
37
45
  # Perform serialization
38
- if @version == 0
39
- amf0_serialize(obj)
40
- else
41
- amf3_serialize(obj)
42
- end
46
+ amf3_serialize(obj)
43
47
 
44
48
  # Cleanup
45
49
  @depth -= 1
46
50
  if @depth == 0
47
- @ref_cache = nil
51
+ @ref_cache = nil
48
52
  @string_cache = nil
49
53
  @object_cache = nil
50
- @trait_cache = nil
54
+ @trait_cache = nil
51
55
  end
52
56
 
53
- return @stream
57
+ @stream
54
58
  end
55
59
 
56
- # Helper for writing arrays inside encode_amf. It uses the current AMF
57
- # version to write the array.
58
- def write_array arr
59
- if @version == 0
60
- amf0_write_array arr
61
- else
62
- amf3_write_array arr
63
- end
60
+ # Helper for writing arrays inside encode_amf.
61
+ def write_array(value)
62
+ amf3_write_array value
64
63
  end
65
64
 
66
- # Helper for writing objects inside encode_amf. It uses the current AMF
67
- # version to write the object. If you pass in a property hash, it will use
68
- # it rather than having the class mapper determine properties. For AMF3,
69
- # you can also specify a traits hash, which can be used to reduce serialized
65
+ # Helper for writing objects inside encode_amf. If you pass in a property hash, it will use
66
+ # it rather than having the class mapper determine properties.
67
+ # You can also specify a traits hash, which can be used to reduce serialized
70
68
  # data size or serialize things as externalizable.
71
- def write_object obj, props=nil, traits=nil
72
- if @version == 0
73
- amf0_write_object obj, props
74
- else
75
- amf3_write_object obj, props, traits
76
- end
69
+ def write_object(obj, props = nil, traits = nil)
70
+ amf3_write_object(obj, props, traits)
77
71
  end
78
72
 
79
- private
80
- include RocketAMF::Pure::WriteIOHelpers
81
73
 
82
- def amf0_serialize obj
83
- if @ref_cache[obj] != nil
84
- amf0_write_reference @ref_cache[obj]
85
- elsif obj.respond_to?(:encode_amf)
86
- obj.encode_amf(self)
87
- elsif obj.is_a?(NilClass)
88
- amf0_write_null
89
- elsif obj.is_a?(TrueClass) || obj.is_a?(FalseClass)
90
- amf0_write_boolean obj
91
- elsif obj.is_a?(Numeric)
92
- amf0_write_number obj
93
- elsif obj.is_a?(Symbol) || obj.is_a?(String)
94
- amf0_write_string obj.to_s
95
- elsif obj.is_a?(Time)
96
- amf0_write_time obj
97
- elsif obj.is_a?(Date)
98
- amf0_write_date obj
99
- elsif obj.is_a?(Array)
100
- amf0_write_array obj
101
- elsif obj.is_a?(Hash) ||obj.is_a?(Object)
102
- amf0_write_object obj
103
- end
104
- end
105
-
106
- def amf0_write_null
107
- @stream << AMF0_NULL_MARKER
108
- end
109
-
110
- def amf0_write_boolean bool
111
- @stream << AMF0_BOOLEAN_MARKER
112
- @stream << pack_int8(bool ? 1 : 0)
113
- end
114
-
115
- def amf0_write_number num
116
- @stream << AMF0_NUMBER_MARKER
117
- @stream << pack_double(num)
118
- end
119
-
120
- def amf0_write_string str
121
- str = str.encode("UTF-8").force_encoding("ASCII-8BIT") if str.respond_to?(:encode)
122
- len = str.bytesize
123
- if len > 2**16-1
124
- @stream << AMF0_LONG_STRING_MARKER
125
- @stream << pack_word32_network(len)
126
- else
127
- @stream << AMF0_STRING_MARKER
128
- @stream << pack_int16_network(len)
129
- end
130
- @stream << str
131
- end
132
-
133
- def amf0_write_time time
134
- @stream << AMF0_DATE_MARKER
135
-
136
- time = time.getutc # Dup and convert to UTC
137
- milli = (time.to_f * 1000).to_i
138
- @stream << pack_double(milli)
139
-
140
- @stream << pack_int16_network(0) # Time zone
141
- end
142
-
143
- def amf0_write_date date
144
- @stream << AMF0_DATE_MARKER
145
- @stream << pack_double(date.strftime("%Q").to_i)
146
- @stream << pack_int16_network(0) # Time zone
147
- end
148
-
149
- def amf0_write_reference index
150
- @stream << AMF0_REFERENCE_MARKER
151
- @stream << pack_int16_network(index)
152
- end
153
-
154
- def amf0_write_array array
155
- @ref_cache.add_obj array
156
- @stream << AMF0_STRICT_ARRAY_MARKER
157
- @stream << pack_word32_network(array.length)
158
- array.each do |elem|
159
- amf0_serialize elem
160
- end
161
- end
162
-
163
- def amf0_write_object obj, props=nil
164
- @ref_cache.add_obj obj
165
-
166
- props = @class_mapper.props_for_serialization obj if props.nil?
167
-
168
- # Is it a typed object?
169
- class_name = @class_mapper.get_as_class_name obj
170
- if class_name
171
- class_name = class_name.encode("UTF-8").force_encoding("ASCII-8BIT") if class_name.respond_to?(:encode)
172
- @stream << AMF0_TYPED_OBJECT_MARKER
173
- @stream << pack_int16_network(class_name.bytesize)
174
- @stream << class_name
175
- else
176
- @stream << AMF0_OBJECT_MARKER
177
- end
178
-
179
- # Write prop list
180
- props.sort.each do |key, value| # Sort keys before writing
181
- key = key.encode("UTF-8").force_encoding("ASCII-8BIT") if key.respond_to?(:encode)
182
- @stream << pack_int16_network(key.bytesize)
183
- @stream << key
184
- amf0_serialize value
185
- end
186
-
187
- # Write end
188
- @stream << pack_int16_network(0)
189
- @stream << AMF0_OBJECT_END_MARKER
190
- end
191
-
192
- def amf3_serialize obj
74
+ private
75
+ def amf3_serialize(obj)
193
76
  if obj.respond_to?(:encode_amf)
194
77
  obj.encode_amf(self)
195
78
  elsif obj.is_a?(NilClass)
@@ -199,124 +82,139 @@ module RocketAMF
199
82
  elsif obj.is_a?(FalseClass)
200
83
  amf3_write_false
201
84
  elsif obj.is_a?(Numeric)
202
- amf3_write_numeric obj
85
+ amf3_write_numeric(obj)
203
86
  elsif obj.is_a?(Symbol) || obj.is_a?(String)
204
- amf3_write_string obj.to_s
87
+ amf3_write_string(obj.to_s)
205
88
  elsif obj.is_a?(Time)
206
89
  amf3_write_time obj
207
90
  elsif obj.is_a?(Date)
208
- amf3_write_date obj
91
+ amf3_write_date(obj)
209
92
  elsif obj.is_a?(StringIO)
210
- amf3_write_byte_array obj
93
+ amf3_write_byte_array(obj)
211
94
  elsif obj.is_a?(Array)
212
- amf3_write_array obj
95
+ amf3_write_array(obj)
213
96
  elsif obj.is_a?(Hash) || obj.is_a?(Object)
214
- amf3_write_object obj
97
+ amf3_write_object(obj)
215
98
  end
216
99
  end
217
100
 
218
- def amf3_write_reference index
101
+ private
102
+ def amf3_write_reference(index)
219
103
  header = index << 1 # shift value left to leave a low bit of 0
220
104
  @stream << pack_integer(header)
221
105
  end
222
106
 
107
+ private
223
108
  def amf3_write_null
224
109
  @stream << AMF3_NULL_MARKER
225
110
  end
226
111
 
112
+ private
227
113
  def amf3_write_true
228
114
  @stream << AMF3_TRUE_MARKER
229
115
  end
230
116
 
117
+ private
231
118
  def amf3_write_false
232
119
  @stream << AMF3_FALSE_MARKER
233
120
  end
234
121
 
235
- def amf3_write_numeric num
236
- if !num.integer? || num < MIN_INTEGER || num > MAX_INTEGER # Check valid range for 29 bits
122
+ private
123
+ def amf3_write_numeric(value)
124
+ if !value.integer? || value < MIN_INTEGER || value > MAX_INTEGER # Check valid range for 29 bits
237
125
  @stream << AMF3_DOUBLE_MARKER
238
- @stream << pack_double(num)
126
+ @stream << pack_double(value)
239
127
  else
240
128
  @stream << AMF3_INTEGER_MARKER
241
- @stream << pack_integer(num)
129
+ @stream << pack_integer(value)
242
130
  end
243
131
  end
244
132
 
245
- def amf3_write_string str
133
+ private
134
+ def amf3_write_string(value)
246
135
  @stream << AMF3_STRING_MARKER
247
- amf3_write_utf8_vr str
136
+ amf3_write_utf8_vr value
248
137
  end
249
138
 
250
- def amf3_write_time time
139
+ private
140
+ def amf3_write_time(value)
251
141
  @stream << AMF3_DATE_MARKER
252
- if @object_cache[time] != nil
253
- amf3_write_reference @object_cache[time]
142
+
143
+ if @object_cache[value] != nil
144
+ amf3_write_reference(@object_cache[value])
254
145
  else
255
146
  # Cache time
256
- @object_cache.add_obj time
147
+ @object_cache.add_obj(value)
257
148
 
258
149
  # Build AMF string
259
- time = time.getutc # Dup and convert to UTC
260
- milli = (time.to_f * 1000).to_i
150
+ value = value.getutc # Dup and convert to UTC
151
+ milli = (value.to_f * 1000).to_i
261
152
  @stream << AMF3_NULL_MARKER
262
153
  @stream << pack_double(milli)
263
154
  end
264
155
  end
265
156
 
266
- def amf3_write_date date
157
+ private
158
+ def amf3_write_date(value)
267
159
  @stream << AMF3_DATE_MARKER
268
- if @object_cache[date] != nil
269
- amf3_write_reference @object_cache[date]
160
+
161
+ if @object_cache[value] != nil
162
+ amf3_write_reference(@object_cache[value])
270
163
  else
271
164
  # Cache date
272
- @object_cache.add_obj date
165
+ @object_cache.add_obj(value)
273
166
 
274
167
  # Build AMF string
275
168
  @stream << AMF3_NULL_MARKER
276
- @stream << pack_double(date.strftime("%Q").to_i)
169
+ @stream << pack_double(value.strftime('%Q').to_i)
277
170
  end
278
171
  end
279
172
 
280
- def amf3_write_byte_array array
173
+ private
174
+ def amf3_write_byte_array(value)
281
175
  @stream << AMF3_BYTE_ARRAY_MARKER
282
- if @object_cache[array] != nil
283
- amf3_write_reference @object_cache[array]
176
+
177
+ if @object_cache[value] != nil
178
+ amf3_write_reference(@object_cache[value])
284
179
  else
285
- @object_cache.add_obj array
286
- str = array.string
180
+ @object_cache.add_obj(value)
181
+ str = value.string
287
182
  @stream << pack_integer(str.bytesize << 1 | 1)
288
183
  @stream << str
289
184
  end
290
185
  end
291
186
 
292
- def amf3_write_array array
187
+ private
188
+ def amf3_write_array(value)
293
189
  # Is it an array collection?
294
- is_ac = false
295
- if array.respond_to?(:is_array_collection?)
296
- is_ac = array.is_array_collection?
190
+ is_array_collection = false
191
+
192
+ if value.respond_to?(:is_array_collection?)
193
+ is_array_collection = value.is_array_collection?
297
194
  else
298
- is_ac = @class_mapper.use_array_collection
195
+ is_array_collection = @class_mapper.use_array_collection
299
196
  end
300
197
 
301
198
  # Write type marker
302
- @stream << (is_ac ? AMF3_OBJECT_MARKER : AMF3_ARRAY_MARKER)
199
+ @stream << (is_array_collection ? AMF3_OBJECT_MARKER : AMF3_ARRAY_MARKER)
303
200
 
304
201
  # Write reference or cache array
305
- if @object_cache[array] != nil
306
- amf3_write_reference @object_cache[array]
202
+ if @object_cache[value] != nil
203
+ amf3_write_reference(@object_cache[value])
307
204
  return
308
205
  else
309
- @object_cache.add_obj array
310
- @object_cache.add_obj nil if is_ac # The array collection source array
206
+ @object_cache.add_obj(value)
207
+ @object_cache.add_obj(nil) if is_array_collection # The array collection source array
311
208
  end
312
209
 
313
210
  # Write out traits and array marker if it's an array collection
314
- if is_ac
315
- class_name = "flex.messaging.io.ArrayCollection"
211
+ if is_array_collection
212
+ class_name = 'flex.messaging.io.ArrayCollection'
213
+
316
214
  if @trait_cache[class_name] != nil
317
215
  @stream << pack_integer(@trait_cache[class_name] << 2 | 0x01)
318
216
  else
319
- @trait_cache.add_obj class_name
217
+ @trait_cache.add_obj(class_name)
320
218
  @stream << "\a" # Externalizable, non-dynamic
321
219
  amf3_write_utf8_vr(class_name)
322
220
  end
@@ -324,43 +222,47 @@ module RocketAMF
324
222
  end
325
223
 
326
224
  # Build AMF string for array
327
- header = array.length << 1 # make room for a low bit of 1
225
+ header = value.length << 1 # make room for a low bit of 1
328
226
  header = header | 1 # set the low bit to 1
329
227
  @stream << pack_integer(header)
330
228
  @stream << AMF3_CLOSE_DYNAMIC_ARRAY
331
- array.each do |elem|
229
+ value.each do |elem|
332
230
  amf3_serialize elem
333
231
  end
334
232
  end
335
233
 
336
- def amf3_write_object obj, props=nil, traits=nil
234
+ private
235
+ def amf3_write_object(obj, properties = nil, traits = nil)
337
236
  @stream << AMF3_OBJECT_MARKER
338
237
 
339
238
  # Caching...
340
239
  if @object_cache[obj] != nil
341
- amf3_write_reference @object_cache[obj]
240
+ amf3_write_reference(@object_cache[obj])
342
241
  return
343
242
  end
344
- @object_cache.add_obj obj
243
+
244
+ @object_cache.add_obj(obj)
345
245
 
346
246
  # Calculate traits if not given
347
247
  is_default = false
348
248
  if traits.nil?
349
- traits = {
350
- :class_name => @class_mapper.get_as_class_name(obj),
351
- :members => [],
352
- :externalizable => false,
353
- :dynamic => true
354
- }
249
+ traits =
250
+ {
251
+ class_name: @class_mapper.get_as_class_name(obj),
252
+ members: [],
253
+ externalizable: false,
254
+ dynamic: true
255
+ }
355
256
  is_default = true unless traits[:class_name]
356
257
  end
357
- class_name = is_default ? "__default__" : traits[:class_name]
258
+
259
+ class_name = is_default ? '__default__' : traits[:class_name]
358
260
 
359
261
  # Write out traits
360
262
  if class_name && @trait_cache[class_name] != nil
361
263
  @stream << pack_integer(@trait_cache[class_name] << 2 | 0x01)
362
264
  else
363
- @trait_cache.add_obj class_name if class_name
265
+ @trait_cache.add_obj(class_name) if class_name
364
266
 
365
267
  # Write out trait header
366
268
  header = 0x03 # Not object ref and not trait ref
@@ -377,7 +279,7 @@ module RocketAMF
377
279
  end
378
280
 
379
281
  # Write out members
380
- traits[:members].each {|m| amf3_write_utf8_vr(m)}
282
+ traits[:members].each { |m| amf3_write_utf8_vr(m) }
381
283
  end
382
284
 
383
285
  # If externalizable, take externalized data shortcut
@@ -387,20 +289,20 @@ module RocketAMF
387
289
  end
388
290
 
389
291
  # Extract properties if not given
390
- props = @class_mapper.props_for_serialization(obj) if props.nil?
292
+ properties = @class_mapper.props_for_serialization(obj) if properties.nil?
391
293
 
392
294
  # Write out sealed properties
393
295
  traits[:members].each do |m|
394
- amf3_serialize props[m]
395
- props.delete(m)
296
+ amf3_serialize(properties[m])
297
+ properties.delete(m)
396
298
  end
397
299
 
398
300
  # Write out dynamic properties
399
301
  if traits[:dynamic]
400
302
  # Write out dynamic properties
401
- props.sort.each do |key, val| # Sort props until Ruby 1.9 becomes common
402
- amf3_write_utf8_vr key.to_s
403
- amf3_serialize val
303
+ properties.sort.each do |key, val| # Sort props until Ruby 1.9 becomes common
304
+ amf3_write_utf8_vr(key.to_s)
305
+ amf3_serialize(val)
404
306
  end
405
307
 
406
308
  # Write close
@@ -408,67 +310,32 @@ module RocketAMF
408
310
  end
409
311
  end
410
312
 
411
- def amf3_write_utf8_vr str, encode=true
412
- if str.respond_to?(:encode)
313
+ private
314
+ def amf3_write_utf8_vr(value, encode = true)
315
+ if value.respond_to?(:encode)
413
316
  if encode
414
- str = str.encode("UTF-8")
317
+ value = value.encode('UTF-8')
415
318
  else
416
- str = str.dup if str.frozen?
319
+ value = value.dup if value.frozen?
417
320
  end
418
- str.force_encoding("ASCII-8BIT")
321
+ value.force_encoding('ASCII-8BIT')
419
322
  end
420
323
 
421
- if str == ''
324
+ if value == ''
422
325
  @stream << AMF3_EMPTY_STRING
423
- elsif @string_cache[str] != nil
424
- amf3_write_reference @string_cache[str]
326
+ elsif @string_cache[value] != nil
327
+ amf3_write_reference(@string_cache[value])
425
328
  else
426
329
  # Cache string
427
- @string_cache.add_obj str
330
+ @string_cache.add_obj(value)
428
331
 
429
332
  # Build AMF string
430
- @stream << pack_integer(str.bytesize << 1 | 1)
431
- @stream << str
432
- end
433
- end
434
- end
435
-
436
- class SerializerCache #:nodoc:
437
- def self.new type
438
- if type == :string
439
- StringCache.new
440
- elsif type == :object
441
- ObjectCache.new
333
+ @stream << pack_integer(value.bytesize << 1 | 1)
334
+ @stream << value
442
335
  end
443
336
  end
444
337
 
445
- class StringCache < Hash #:nodoc:
446
- def initialize
447
- @cache_index = 0
448
- end
449
-
450
- def add_obj str
451
- self[str] = @cache_index
452
- @cache_index += 1
453
- end
454
- end
338
+ end # Serializer
455
339
 
456
- class ObjectCache < Hash #:nodoc:
457
- def initialize
458
- @cache_index = 0
459
- @obj_references = []
460
- end
461
-
462
- def [] obj
463
- super(obj.object_id)
464
- end
465
-
466
- def add_obj obj
467
- @obj_references << obj
468
- self[obj.object_id] = @cache_index
469
- @cache_index += 1
470
- end
471
- end
472
- end
473
- end
474
- end
340
+ end #Pure
341
+ end #RocketAMF