mrpin-rocketamf 1.0.4 → 2.0.0

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