RocketAMF 0.0.7 → 0.1.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.
@@ -1,51 +1,23 @@
1
1
  == DESCRIPTION:
2
2
 
3
- A fast AMF serializer/deserializer and request/response wrappers to simplify remoting implementation.
3
+ RocketAMF is a full featured AMF0/3 serializer and deserializer with support for
4
+ Flash -> Ruby and Ruby -> Flash class mapping, custom serializers, remoting
5
+ gateway helpers that follow AMF0/3 messaging specs, and a suite of specs to
6
+ ensure adherence to the specification documents put out by Adobe.
4
7
 
5
8
  == INSTALL:
6
9
 
7
10
  gem install RocketAMF --source="http://gemcutter.org"
8
11
 
9
- == EXAMPLE:
10
-
11
- # helloworld.ru
12
+ == SIMPLE EXAMPLE:
12
13
 
13
14
  require 'rocketamf'
14
15
 
15
- class HelloWorldApp
16
- APPLICATION_AMF = 'application/x-amf'.freeze
17
-
18
- def call env
19
- if is_amf?(env)
20
- # Wrap request and response
21
- env['rack.input'].rewind
22
- request = RocketAMF::Request.new.populate_from_stream(env['rack.input'].read)
23
- response = RocketAMF::Response.new
24
-
25
- # Handle request
26
- response.each_method_call request do |method, args|
27
- raise "Service #{method} does not exists" unless method == 'App.helloWorld'
28
- 'Hello world'
29
- end
30
-
31
- # Pass back response
32
- response_str = response.serialize
33
- return [200, {'Content-Type' => APPLICATION_AMF, 'Content-Length' => response_str.length.to_s}, [response_str]]
34
- else
35
- return [200, {'Content-Type' => 'text/plain', 'Content-Length' => '16' }, ["Rack AMF gateway"]]
36
- end
37
- end
38
-
39
- private
40
- def is_amf? env
41
- return false unless env['CONTENT_TYPE'] == APPLICATION_AMF
42
- return false unless env['PATH_INFO'] == '/amf'
43
- return true
44
- end
16
+ hash = {:apple => "Apfel", :red => "Rot", :eyes => "Augen"}
17
+ File.open("amf.dat", 'w') do |f|
18
+ f.write RocketAMF.serialize(hash, 3) # Use AMF3 encoding because it's smaller
45
19
  end
46
20
 
47
- run HelloWorldApp.new
48
-
49
21
  == LICENSE:
50
22
 
51
23
  (The MIT License)
data/Rakefile CHANGED
@@ -23,8 +23,8 @@ end
23
23
 
24
24
  spec = Gem::Specification.new do |s|
25
25
  s.name = 'RocketAMF'
26
- s.version = '0.0.7'
27
- s.summary = 'Fast AMF serializer/deserializer and request/response wrappers to simplify remoting implementation'
26
+ s.version = '0.1.0'
27
+ s.summary = 'Fast AMF serializer/deserializer with remoting request/response wrappers to simplify integration'
28
28
 
29
29
  s.files = FileList['README.rdoc', 'Rakefile', 'lib/**/*.rb', 'spec/**/*.rb', 'spec/**/*.bin', 'spec/spec.opts']
30
30
  s.require_path = 'lib'
@@ -34,7 +34,7 @@ spec = Gem::Specification.new do |s|
34
34
  s.extra_rdoc_files = ['README.rdoc']
35
35
  s.rdoc_options = ['--line-numbers', '--main', 'README.rdoc']
36
36
 
37
- s.authors = ['Tony Hillerson', 'Stephen Augenstein']
37
+ s.authors = ['Jacob Henry', 'Stephen Augenstein']
38
38
  s.email = 'perl.programmer@gmail.com'
39
39
  s.homepage = 'http://github.com/warhammerkid/rocket-amf'
40
40
 
@@ -1,11 +1,77 @@
1
1
  $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
2
  $:.unshift "#{File.expand_path(File.dirname(__FILE__))}/rocketamf/"
3
3
 
4
- require 'rocketamf/version'
5
4
  require 'rocketamf/class_mapping'
6
5
  require 'rocketamf/constants'
7
6
  require 'rocketamf/remoting'
8
7
 
8
+ # RocketAMF is a full featured AMF0/3 serializer and deserializer with support
9
+ # for Flash -> Ruby and Ruby -> Flash class mapping, custom serializers,
10
+ # remoting gateway helpers that follow AMF0/3 messaging specs, and a suite of
11
+ # specs to ensure adherence to the specification documents put out by Adobe.
12
+ #
13
+ # == Serialization & Deserialization
14
+ #
15
+ # RocketAMF provides two main methods - <tt>RocketAMF.serialize(obj, amf_version=0)</tt>
16
+ # and <tt>RocketAMF.deserialize(source, amf_version=0)</tt>. To use, simple pass
17
+ # in the string to deserialize and the version if different from the default. To
18
+ # serialize an object, simply call <tt>RocketAMF.serialize</tt> with the object
19
+ # and the proper version. If you're working only with AS3, it is more effiecient
20
+ # to use the version 3 encoding, as it caches duplicate string to reduce
21
+ # serialized size. However for greater compatibility the default, AMF version 0,
22
+ # should work fine.
23
+ #
24
+ # == Mapping Classes Between Flash and Ruby
25
+ #
26
+ # RocketAMF provides a simple class mapping tool to facilitate serialization and
27
+ # deserialization of typed objects. Refer to the documentation of
28
+ # <tt>RocketAMF::ClassMapping</tt> for more details. If the provided class
29
+ # mapping tool is not sufficient for your needs, you also have the option to
30
+ # replace it with a class mapper of your own devising that matches the documented
31
+ # API.
32
+ #
33
+ # == Remoting
34
+ #
35
+ # You can use RocketAMF bare to write an AMF gateway using the following code.
36
+ # In addition, you can use rack-amf (http://github.com/warhammerkid/rack-amf)
37
+ # which simplifies the code necessary to set up a functioning AMF gateway.
38
+ #
39
+ # # helloworld.ru
40
+ # require 'rocketamf'
41
+ #
42
+ # class HelloWorldApp
43
+ # APPLICATION_AMF = 'application/x-amf'.freeze
44
+ #
45
+ # def call env
46
+ # if is_amf?(env)
47
+ # # Wrap request and response
48
+ # env['rack.input'].rewind
49
+ # request = RocketAMF::Request.new.populate_from_stream(env['rack.input'].read)
50
+ # response = RocketAMF::Response.new
51
+ #
52
+ # # Handle request
53
+ # response.each_method_call request do |method, args|
54
+ # raise "Service #{method} does not exists" unless method == 'App.helloWorld'
55
+ # 'Hello world'
56
+ # end
57
+ #
58
+ # # Pass back response
59
+ # response_str = response.serialize
60
+ # return [200, {'Content-Type' => APPLICATION_AMF, 'Content-Length' => response_str.length.to_s}, [response_str]]
61
+ # else
62
+ # return [200, {'Content-Type' => 'text/plain', 'Content-Length' => '16' }, ["Rack AMF gateway"]]
63
+ # end
64
+ # end
65
+ #
66
+ # private
67
+ # def is_amf? env
68
+ # return false unless env['CONTENT_TYPE'] == APPLICATION_AMF
69
+ # return false unless env['PATH_INFO'] == '/amf'
70
+ # return true
71
+ # end
72
+ # end
73
+ #
74
+ # run HelloWorldApp.new
9
75
  module RocketAMF
10
76
  begin
11
77
  raise LoadError, 'C extensions not implemented'
@@ -40,7 +106,7 @@ module RocketAMF
40
106
  # We use const_missing to define the active ClassMapper at runtime. This way,
41
107
  # heavy modification of class mapping functionality is still possible without
42
108
  # forcing extenders to redefine the constant.
43
- def self.const_missing const
109
+ def self.const_missing const #:nodoc:
44
110
  if const == :ClassMapper
45
111
  RocketAMF.const_set(:ClassMapper, RocketAMF::ClassMapping.new)
46
112
  else
@@ -3,8 +3,6 @@ require 'rocketamf/values/array_collection'
3
3
  require 'rocketamf/values/messages'
4
4
 
5
5
  module RocketAMF
6
- # == Class Mapping
7
- #
8
6
  # Handles class name mapping between actionscript and ruby and assists in
9
7
  # serializing and deserializing data between them. Simply map an AS class to a
10
8
  # ruby class and when the object is (de)serialized it will end up as the
@@ -29,8 +27,6 @@ module RocketAMF
29
27
  # Populators are processed in insert order and must respond to the <tt>can_handle?</tt>
30
28
  # and <tt>populate</tt> methods.
31
29
  #
32
- # Example:
33
- #
34
30
  # class CustomPopulator
35
31
  # def can_handle? obj
36
32
  # true
@@ -43,11 +39,10 @@ module RocketAMF
43
39
  # end
44
40
  # RocketAMF::ClassMapper.object_populators << CustomPopulator.new
45
41
  #
42
+ #
46
43
  # Serializers are also processed in insert order and must respond to the
47
44
  # <tt>can_handle?</tt> and <tt>serialize</tt> methods.
48
45
  #
49
- # Example:
50
- #
51
46
  # class CustomSerializer
52
47
  # def can_handle? obj
53
48
  # true
@@ -65,7 +60,9 @@ module RocketAMF
65
60
  # mapping completely. In this case, simply assign an instance of your own class
66
61
  # mapper to <tt>RocketAMF::ClassMapper</tt> after loading RocketAMF. Through
67
62
  # the magic of <tt>const_missing</tt>, <tt>ClassMapper</tt> is only defined after
68
- # the first access by default, so you get no annoying warning messages.
63
+ # the first access by default, so you get no annoying warning messages. Custom
64
+ # class mappers must implement the following methods: <tt>get_as_class_name</tt>,
65
+ # <tt>get_ruby_obj</tt>, <tt>populate_ruby_obj</tt>, <tt>props_for_serialization</tt>.
69
66
  #
70
67
  # Example:
71
68
  #
@@ -163,7 +160,8 @@ module RocketAMF
163
160
  end
164
161
 
165
162
  # Instantiates a ruby object using the mapping configuration based on the
166
- # source AS class name. If there is no mapping defined, it returns a hash.
163
+ # source AS class name. If there is no mapping defined, it returns a
164
+ # <tt>RocketAMF::Values::TypedHash</tt> with the serialized class name.
167
165
  def get_ruby_obj as_class_name
168
166
  ruby_class_name = mappings.get_ruby_class_name as_class_name
169
167
  if ruby_class_name.nil?
@@ -220,7 +218,7 @@ module RocketAMF
220
218
  (ruby_obj.public_methods - @ignored_props).each do |method_name|
221
219
  # Add them to the prop hash if they take no arguments
222
220
  method_def = ruby_obj.method(method_name)
223
- props[method_name] = ruby_obj.send(method_name) if method_def.arity == 0
221
+ props[method_name.to_s] = ruby_obj.send(method_name) if method_def.arity == 0
224
222
  end
225
223
  props
226
224
  end
@@ -33,11 +33,10 @@ module RocketAMF
33
33
  AMF3_OBJECT_MARKER = 0x0A #"\n"
34
34
  AMF3_XML_MARKER = 0x0B #"\v"
35
35
  AMF3_BYTE_ARRAY_MARKER = 0x0C #"\f"
36
+ AMF3_DICT_MARKER = 0x11 #"\021"
36
37
 
37
38
  # Other AMF3 Markers
38
39
  AMF3_EMPTY_STRING = 0x01
39
- AMF3_ANONYMOUS_OBJECT = 0x01
40
- AMF3_DYNAMIC_OBJECT = 0x0B
41
40
  AMF3_CLOSE_DYNAMIC_OBJECT = 0x01
42
41
  AMF3_CLOSE_DYNAMIC_ARRAY = 0x01
43
42
 
@@ -39,7 +39,7 @@ module RocketAMF
39
39
  when AMF0_UNSUPPORTED_MARKER
40
40
  nil
41
41
  when AMF0_XML_MARKER
42
- #read_xml source
42
+ read_string source, true
43
43
  when AMF0_TYPED_OBJECT_MARKER
44
44
  read_typed_object source
45
45
  when AMF0_AMF3_MARKER
@@ -63,7 +63,9 @@ module RocketAMF
63
63
 
64
64
  def read_string source, long=false
65
65
  len = long ? read_word32_network(source) : read_word16_network(source)
66
- source.read(len)
66
+ str = source.read(len)
67
+ str.force_encoding("UTF-8") if str.respond_to?(:force_encoding)
68
+ str
67
69
  end
68
70
 
69
71
  def read_object source, add_to_ref_cache=true
@@ -180,18 +182,18 @@ module RocketAMF
180
182
  read_number source
181
183
  when AMF3_STRING_MARKER
182
184
  read_string source
183
- when AMF3_XML_DOC_MARKER
184
- #read_xml_string
185
+ when AMF3_XML_DOC_MARKER, AMF3_XML_MARKER
186
+ read_xml source
185
187
  when AMF3_DATE_MARKER
186
188
  read_date source
187
189
  when AMF3_ARRAY_MARKER
188
190
  read_array source
189
191
  when AMF3_OBJECT_MARKER
190
192
  read_object source
191
- when AMF3_XML_MARKER
192
- #read_amf3_xml
193
193
  when AMF3_BYTE_ARRAY_MARKER
194
194
  read_amf3_byte_array source
195
+ when AMF3_DICT_MARKER
196
+ read_dict source
195
197
  else
196
198
  raise AMFError, "Invalid type: #{type}"
197
199
  end
@@ -245,12 +247,32 @@ module RocketAMF
245
247
  str = ""
246
248
  if length > 0
247
249
  str = source.read(length)
250
+ str.force_encoding("UTF-8") if str.respond_to?(:force_encoding)
248
251
  @string_cache << str
249
252
  end
250
253
  return str
251
254
  end
252
255
  end
253
256
 
257
+ def read_xml source
258
+ type = read_integer source
259
+ isReference = (type & 0x01) == 0
260
+
261
+ if isReference
262
+ reference = type >> 1
263
+ return @object_cache[reference]
264
+ else
265
+ length = type >> 1
266
+ str = ""
267
+ if length > 0
268
+ str = source.read(length)
269
+ str.force_encoding("UTF-8") if str.respond_to?(:force_encoding)
270
+ @object_cache << str
271
+ end
272
+ return str
273
+ end
274
+ end
275
+
254
276
  def read_amf3_byte_array source
255
277
  type = read_integer source
256
278
  isReference = (type & 0x01) == 0
@@ -314,37 +336,39 @@ module RocketAMF
314
336
 
315
337
  if class_is_reference
316
338
  reference = class_type >> 1
317
- class_definition = @trait_cache[reference]
339
+ traits = @trait_cache[reference]
318
340
  else
319
- class_name = read_string source
320
341
  externalizable = (class_type & 0x02) != 0
321
342
  dynamic = (class_type & 0x04) != 0
322
343
  attribute_count = class_type >> 3
344
+ class_name = read_string source
323
345
 
324
346
  class_attributes = []
325
347
  attribute_count.times{class_attributes << read_string(source)} # Read class members
326
348
 
327
- class_definition = {"class_name" => class_name,
328
- "members" => class_attributes,
329
- "externalizable" => externalizable,
330
- "dynamic" => dynamic}
331
- @trait_cache << class_definition
349
+ traits = {
350
+ :class_name => class_name,
351
+ :members => class_attributes,
352
+ :externalizable => externalizable,
353
+ :dynamic => dynamic
354
+ }
355
+ @trait_cache << traits
332
356
  end
333
357
 
334
- obj = RocketAMF::ClassMapper.get_ruby_obj class_definition["class_name"]
358
+ obj = RocketAMF::ClassMapper.get_ruby_obj traits[:class_name]
335
359
  @object_cache << obj
336
360
 
337
- if class_definition['externalizable']
361
+ if traits[:externalizable]
338
362
  obj.externalized_data = deserialize(source)
339
363
  else
340
364
  props = {}
341
- class_definition['members'].each do |key|
365
+ traits[:members].each do |key|
342
366
  value = deserialize(source)
343
367
  props[key.to_sym] = value
344
368
  end
345
369
 
346
370
  dynamic_props = nil
347
- if class_definition['dynamic']
371
+ if traits[:dynamic]
348
372
  dynamic_props = {}
349
373
  while (key = read_string source) && key.length != 0 do # read next key
350
374
  value = deserialize(source)
@@ -371,6 +395,25 @@ module RocketAMF
371
395
  time
372
396
  end
373
397
  end
398
+
399
+ def read_dict source
400
+ type = read_integer source
401
+ # Currently duplicate dictionaries send false, but I'll leave this in here just in case
402
+ isReference = (type & 0x01) == 0
403
+ if isReference
404
+ reference = type >> 1
405
+ return @object_cache[reference]
406
+ else
407
+ dict = {}
408
+ @object_cache << dict
409
+ length = type >> 1
410
+ skip = read_integer source # TODO: Handle when specs are updated
411
+ 0.upto(length - 1) do |i|
412
+ dict[deserialize(source)] = deserialize(source)
413
+ end
414
+ dict
415
+ end
416
+ end
374
417
  end
375
418
  end
376
419
  end
@@ -20,6 +20,7 @@ module RocketAMF
20
20
  header_count = read_word16_network stream
21
21
  0.upto(header_count-1) do
22
22
  name = stream.read(read_word16_network(stream))
23
+ name.force_encoding("UTF-8") if name.respond_to?(:force_encoding)
23
24
  must_understand = read_int8(stream) != 0
24
25
  length = read_word32_network stream
25
26
  data = RocketAMF.deserialize stream
@@ -30,7 +31,9 @@ module RocketAMF
30
31
  message_count = read_word16_network stream
31
32
  0.upto(message_count-1) do
32
33
  target_uri = stream.read(read_word16_network(stream))
34
+ target_uri.force_encoding("UTF-8") if target_uri.respond_to?(:force_encoding)
33
35
  response_uri = stream.read(read_word16_network(stream))
36
+ response_uri.force_encoding("UTF-8") if response_uri.respond_to?(:force_encoding)
34
37
  length = read_word32_network stream
35
38
  data = RocketAMF.deserialize stream
36
39
  if data.is_a?(Array) && data.length == 1 && data[0].is_a?(::RocketAMF::Values::AbstractMessage)
@@ -58,8 +61,10 @@ module RocketAMF
58
61
  # Write headers
59
62
  stream << pack_int16_network(@headers.length) # Header count
60
63
  @headers.each do |h|
61
- stream << pack_int16_network(h.name.length)
62
- stream << h.name
64
+ name_str = h.name
65
+ name_str.encode!("UTF-8").force_encoding("ASCII-8BIT") if name_str.respond_to?(:encode)
66
+ stream << pack_int16_network(name_str.bytesize)
67
+ stream << name_str
63
68
  stream << pack_int8(h.must_understand ? 1 : 0)
64
69
  stream << pack_word32_network(-1)
65
70
  stream << RocketAMF.serialize(h.data, 0)
@@ -68,11 +73,15 @@ module RocketAMF
68
73
  # Write messages
69
74
  stream << pack_int16_network(@messages.length) # Message count
70
75
  @messages.each do |m|
71
- stream << pack_int16_network(m.target_uri.length)
72
- stream << m.target_uri
76
+ uri_str = m.target_uri
77
+ uri_str.encode!("UTF-8").force_encoding("ASCII-8BIT") if uri_str.respond_to?(:encode)
78
+ stream << pack_int16_network(uri_str.bytesize)
79
+ stream << uri_str
73
80
 
74
- stream << pack_int16_network(m.response_uri.length)
75
- stream << m.response_uri
81
+ uri_str = m.response_uri
82
+ uri_str.encode!("UTF-8").force_encoding("ASCII-8BIT") if uri_str.respond_to?(:encode)
83
+ stream << pack_int16_network(uri_str.bytesize)
84
+ stream << uri_str
76
85
 
77
86
  stream << pack_word32_network(-1)
78
87
  stream << AMF0_AMF3_MARKER if @amf_version == 3
@@ -52,7 +52,8 @@ module RocketAMF
52
52
  end
53
53
 
54
54
  def write_string str, stream
55
- len = str.length
55
+ str = str.encode("UTF-8").force_encoding("ASCII-8BIT") if str.respond_to?(:encode)
56
+ len = str.bytesize
56
57
  if len > 2**16-1
57
58
  stream << AMF0_LONG_STRING_MARKER
58
59
  stream << pack_word32_network(len)
@@ -100,8 +101,9 @@ module RocketAMF
100
101
  # Is it a typed object?
101
102
  class_name = RocketAMF::ClassMapper.get_as_class_name obj
102
103
  if class_name
104
+ class_name = class_name.encode("UTF-8").force_encoding("ASCII-8BIT") if class_name.respond_to?(:encode)
103
105
  stream << AMF0_TYPED_OBJECT_MARKER
104
- stream << pack_int16_network(class_name.length)
106
+ stream << pack_int16_network(class_name.bytesize)
105
107
  stream << class_name
106
108
  else
107
109
  stream << AMF0_OBJECT_MARKER
@@ -116,7 +118,8 @@ module RocketAMF
116
118
  # Write prop list
117
119
  props = RocketAMF::ClassMapper.props_for_serialization obj
118
120
  props.sort.each do |key, value| # Sort keys before writing
119
- stream << pack_int16_network(key.length)
121
+ key = key.encode("UTF-8").force_encoding("ASCII-8BIT") if key.respond_to?(:encode)
122
+ stream << pack_int16_network(key.bytesize)
120
123
  stream << key
121
124
  serialize value, stream
122
125
  end
@@ -134,6 +137,7 @@ module RocketAMF
134
137
  def initialize
135
138
  @string_cache = SerializerCache.new :string
136
139
  @object_cache = SerializerCache.new :object
140
+ @trait_cache = SerializerCache.new :trait
137
141
  end
138
142
 
139
143
  def version
@@ -159,6 +163,8 @@ module RocketAMF
159
163
  write_date obj, stream
160
164
  elsif obj.is_a?(StringIO)
161
165
  write_byte_array obj, stream
166
+ elsif obj.is_a?(RocketAMF::Values::ArrayCollection)
167
+ write_array_collection obj, stream
162
168
  elsif obj.is_a?(Array)
163
169
  write_array obj, stream
164
170
  elsif obj.is_a?(Hash) || obj.is_a?(Object)
@@ -229,6 +235,10 @@ module RocketAMF
229
235
  end
230
236
  end
231
237
 
238
+ def write_array_collection array, stream
239
+ write_object array, stream, {:class_name => RocketAMF::ClassMapper.get_as_class_name(array), :members => [], :externalizable => true, :dynamic => false}
240
+ end
241
+
232
242
  def write_array array, stream
233
243
  stream << AMF3_ARRAY_MARKER
234
244
  if @object_cache[array] != nil
@@ -248,7 +258,7 @@ module RocketAMF
248
258
  end
249
259
  end
250
260
 
251
- def write_object obj, stream
261
+ def write_object obj, stream, traits=nil
252
262
  stream << AMF3_OBJECT_MARKER
253
263
  if @object_cache[obj] != nil
254
264
  write_reference @object_cache[obj], stream
@@ -256,26 +266,59 @@ module RocketAMF
256
266
  # Cache object
257
267
  @object_cache.add_obj obj
258
268
 
259
- # Always serialize things as dynamic objects
260
- stream << AMF3_DYNAMIC_OBJECT
269
+ # Calculate traits if not given
270
+ if traits.nil?
271
+ traits = {
272
+ :class_name => RocketAMF::ClassMapper.get_as_class_name(obj),
273
+ :members => [],
274
+ :externalizable => false,
275
+ :dynamic => true
276
+ }
277
+ end
261
278
 
262
- # Write class name/anonymous
263
- class_name = RocketAMF::ClassMapper.get_as_class_name obj
264
- if class_name
265
- write_utf8_vr class_name, stream
279
+ # Write out traits
280
+ if traits[:class_name] && @trait_cache[traits] != nil
281
+ stream << pack_integer(@trait_cache[traits] << 2 | 0x01)
266
282
  else
267
- stream << AMF3_ANONYMOUS_OBJECT
283
+ @trait_cache.add_obj traits if traits[:class_name]
284
+
285
+ # Write out trait header
286
+ header = 0x03 # Not object ref and not trait ref
287
+ header |= 0x02 << 2 if traits[:dynamic]
288
+ header |= 0x01 << 2 if traits[:externalizable]
289
+ header |= traits[:members].length << 4
290
+ stream << pack_integer(header)
291
+
292
+ # Write out class name
293
+ write_utf8_vr(traits[:class_name].to_s, stream)
294
+
295
+ # Write out members
296
+ traits[:members].each {|m| write_utf8_vr(m, stream)}
297
+ end
298
+
299
+ # If externalizable, take externalized data shortcut
300
+ if traits[:externalizable]
301
+ serialize obj.externalized_data, stream
302
+ return
268
303
  end
269
304
 
270
- # Write out properties
305
+ # Write out sealed properties
271
306
  props = RocketAMF::ClassMapper.props_for_serialization obj
272
- props.sort.each do |key, val| # Sort props until Ruby 1.9 becomes common
273
- write_utf8_vr key.to_s, stream
274
- serialize val, stream
307
+ traits[:members].each do |m|
308
+ serialize props[m], stream
309
+ props.delete(m)
275
310
  end
276
311
 
277
- # Write close
278
- stream << AMF3_CLOSE_DYNAMIC_OBJECT
312
+ if traits[:dynamic]
313
+ # Write out dynamic properties
314
+ props.sort.each do |key, val| # Sort props until Ruby 1.9 becomes common
315
+ write_utf8_vr key.to_s, stream
316
+ serialize val, stream
317
+ end
318
+
319
+ # Write close
320
+ stream << AMF3_CLOSE_DYNAMIC_OBJECT
321
+ end
279
322
  end
280
323
  end
281
324
 
@@ -283,6 +326,8 @@ module RocketAMF
283
326
  include RocketAMF::Pure::WriteIOHelpers
284
327
 
285
328
  def write_utf8_vr str, stream
329
+ str = str.encode("UTF-8").force_encoding("ASCII-8BIT") if str.respond_to?(:encode)
330
+
286
331
  if str == ''
287
332
  stream << AMF3_EMPTY_STRING
288
333
  elsif @string_cache[str] != nil
@@ -292,7 +337,7 @@ module RocketAMF
292
337
  @string_cache.add_obj str
293
338
 
294
339
  # Build AMF string
295
- header = str.length << 1 # make room for a low bit of 1
340
+ header = str.bytesize << 1 # make room for a low bit of 1
296
341
  header = header | 1 # set the low bit to 1
297
342
  stream << pack_integer(header)
298
343
  stream << str
@@ -306,6 +351,8 @@ module RocketAMF
306
351
  StringCache.new
307
352
  elsif type == :object
308
353
  ObjectCache.new
354
+ elsif type == :trait
355
+ TraitCache.new
309
356
  end
310
357
  end
311
358
 
@@ -334,6 +381,21 @@ module RocketAMF
334
381
  @cache_index += 1
335
382
  end
336
383
  end
384
+
385
+ class TraitCache < Hash #:nodoc:
386
+ def initialize
387
+ @cache_index = 0
388
+ end
389
+
390
+ def [] obj
391
+ super(obj[:class_name])
392
+ end
393
+
394
+ def add_obj obj
395
+ self[obj[:class_name]] = @cache_index
396
+ @cache_index += 1
397
+ end
398
+ end
337
399
  end
338
400
  end
339
401
  end
@@ -1,6 +1,10 @@
1
1
  module RocketAMF
2
2
  module Values #:nodoc:
3
3
  class ArrayCollection < Array
4
+ def externalized_data
5
+ [] + self # Duplicate as an array
6
+ end
7
+
4
8
  def externalized_data=(data)
5
9
  push(*data)
6
10
  end
@@ -1,14 +1,15 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
2
 
3
- describe RocketAMF::ClassMapping do
4
- before(:all) do
5
- class ClassMappingTest
6
- attr_accessor :prop_a
7
- attr_accessor :prop_b
8
- attr_accessor :prop_c
9
- end
10
- end
3
+ class ClassMappingTest
4
+ attr_accessor :prop_a
5
+ attr_accessor :prop_b
6
+ attr_accessor :prop_c
7
+ end
8
+ class ClassMappingTest2 < ClassMappingTest; end;
11
9
 
10
+ module ANamespace; class TestRubyClass; end; end
11
+
12
+ describe RocketAMF::ClassMapping do
12
13
  before :each do
13
14
  @mapper = RocketAMF::ClassMapping.new
14
15
  @mapper.define do |m|
@@ -34,7 +35,6 @@ describe RocketAMF::ClassMapping do
34
35
  end
35
36
 
36
37
  it "should properly instantiate namespaced classes" do
37
- module ANamespace; class TestRubyClass; end; end
38
38
  @mapper.define {|m| m.map :as => 'ASClass', :ruby => 'ANamespace::TestRubyClass'}
39
39
  @mapper.get_ruby_obj('ASClass').should be_a(ANamespace::TestRubyClass)
40
40
  end
@@ -110,7 +110,7 @@ describe RocketAMF::ClassMapping do
110
110
 
111
111
  describe "property extractor" do
112
112
  it "should extract hash properties" do
113
- hash = {:a => 'test1', :b => 'test2'}
113
+ hash = {:a => 'test1', 'b' => 'test2'}
114
114
  props = @mapper.props_for_serialization(hash)
115
115
  props.should == {'a' => 'test1', 'b' => 'test2'}
116
116
  end
@@ -125,8 +125,6 @@ describe RocketAMF::ClassMapping do
125
125
  end
126
126
 
127
127
  it "should extract inherited object properties" do
128
- class ClassMappingTest2 < ClassMappingTest
129
- end
130
128
  obj = ClassMappingTest2.new
131
129
  obj.prop_a = 'Test A'
132
130
  obj.prop_b = 'Test B'
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
4
 
3
5
  describe "when deserializing" do
@@ -18,7 +20,7 @@ describe "when deserializing" do
18
20
  output.should === true
19
21
  end
20
22
 
21
- it "should deserialize strings" do
23
+ it "should deserialize UTF8 strings" do
22
24
  input = object_fixture('amf0-string.bin')
23
25
  output = RocketAMF.deserialize(input, 0)
24
26
  output.should == "this is a テスト"
@@ -74,7 +76,11 @@ describe "when deserializing" do
74
76
  output.should == Time.utc(2003, 2, 13, 5)
75
77
  end
76
78
 
77
- it "should deserialize XML"
79
+ it "should deserialize an XML document" do
80
+ input = object_fixture('amf0-xmlDoc.bin')
81
+ output = RocketAMF.deserialize(input, 0)
82
+ output.should == '<parent><child prop="test" /></parent>'
83
+ end
78
84
 
79
85
  it "should deserialize an unmapped object as a dynamic anonymous object" do
80
86
  input = object_fixture("amf0-typed-object.bin")
@@ -85,9 +91,6 @@ describe "when deserializing" do
85
91
  end
86
92
 
87
93
  it "should deserialize a mapped object as a mapped ruby class instance" do
88
- class RubyClass
89
- attr_accessor :foo, :baz
90
- end
91
94
  RocketAMF::ClassMapper.define {|m| m.map :as => 'org.rocketAMF.ASClass', :ruby => 'RubyClass'}
92
95
 
93
96
  input = object_fixture("amf0-typed-object.bin")
@@ -167,8 +170,17 @@ describe "when deserializing" do
167
170
  output.should == Time.at(0)
168
171
  end
169
172
 
170
- #BAH! Who sends XML over AMF?
171
- it "should deserialize XML"
173
+ it "should deserialize XML" do
174
+ # XMLDocument tag
175
+ input = object_fixture("amf3-xmlDoc.bin")
176
+ output = RocketAMF.deserialize(input, 3)
177
+ output.should == '<parent><child prop="test" /></parent>'
178
+
179
+ # XML tag
180
+ input = object_fixture("amf3-xml.bin")
181
+ output = RocketAMF.deserialize(input, 3)
182
+ output.should == '<parent><child prop="test"/></parent>'
183
+ end
172
184
  end
173
185
 
174
186
  describe "objects" do
@@ -186,9 +198,6 @@ describe "when deserializing" do
186
198
  end
187
199
 
188
200
  it "should deserialize a mapped object as a mapped ruby class instance" do
189
- class RubyClass
190
- attr_accessor :foo, :baz
191
- end
192
201
  RocketAMF::ClassMapper.define {|m| m.map :as => 'org.rocketAMF.ASClass', :ruby => 'RubyClass'}
193
202
 
194
203
  input = object_fixture("amf3-typedObject.bin")
@@ -231,8 +240,29 @@ describe "when deserializing" do
231
240
  input = object_fixture("amf3-byteArray.bin")
232
241
  output = RocketAMF.deserialize(input, 3)
233
242
 
234
- output.should be_a StringIO
235
- output.string.should == "\000\003これtest\100"
243
+ output.should be_a(StringIO)
244
+ expected = "\000\003これtest\100"
245
+ expected.force_encoding("ASCII-8BIT") if expected.respond_to?(:force_encoding)
246
+ output.string.should == expected
247
+ end
248
+
249
+ it "should deserialize an empty dictionary" do
250
+ input = object_fixture("amf3-emptyDictionary.bin")
251
+ output = RocketAMF.deserialize(input, 3)
252
+ output.should == {}
253
+ end
254
+
255
+ it "should deserialize a dictionary" do
256
+ input = object_fixture("amf3-dictionary.bin")
257
+ output = RocketAMF.deserialize(input, 3)
258
+
259
+ keys = output.keys
260
+ keys.length.should == 2
261
+ obj_key, str_key = keys[0].is_a?(RocketAMF::Values::TypedHash) ? [keys[0], keys[1]] : [keys[1], keys[0]]
262
+ obj_key.type.should == 'org.rocketAMF.ASClass'
263
+ output[obj_key].should == "asdf2"
264
+ str_key.should == "bar"
265
+ output[str_key].should == "asdf1"
236
266
  end
237
267
  end
238
268
 
@@ -274,9 +304,6 @@ describe "when deserializing" do
274
304
  end
275
305
 
276
306
  it "should keep reference of duplicate object traits" do
277
- class RubyClass
278
- attr_accessor :foo, :baz
279
- end
280
307
  RocketAMF::ClassMapper.define {|m| m.map :as => 'org.rocketAMF.ASClass', :ruby => 'RubyClass'}
281
308
 
282
309
  input = object_fixture("amf3-traitRef.bin")
@@ -304,7 +331,11 @@ describe "when deserializing" do
304
331
  output.should == [a,b,a,b]
305
332
  end
306
333
 
307
- it "should keep references of duplicate XML and XMLDocuments"
334
+ it "should keep references of duplicate XML and XMLDocuments" do
335
+ input = object_fixture("amf3-xmlRef.bin")
336
+ output = RocketAMF.deserialize(input, 3)
337
+ output.should == ['<parent><child prop="test"/></parent>', '<parent><child prop="test"/></parent>']
338
+ end
308
339
 
309
340
  it "should keep references of duplicate byte arrays" do
310
341
  input = object_fixture("amf3-byteArrayRef.bin")
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
4
 
3
5
  require 'rexml/document'
@@ -34,9 +36,6 @@ describe "when serializing" do
34
36
  end
35
37
 
36
38
  it "should serialize references" do
37
- class OtherClass
38
- attr_accessor :foo, :bar
39
- end
40
39
  obj = OtherClass.new
41
40
  obj.foo = "baz"
42
41
  obj.bar = 3.14
@@ -51,14 +50,11 @@ describe "when serializing" do
51
50
  end
52
51
 
53
52
  it "should serialize hashes" do
54
- output = RocketAMF.serialize({:a => 'b', :c => 'd'}, 0)
53
+ output = RocketAMF.serialize({:a => 'b', 'c' => 'd'}, 0)
55
54
  output.should == object_fixture('amf0-hash.bin')
56
55
  end
57
56
 
58
57
  it "should serialize unmapped objects" do
59
- class RubyClass
60
- attr_accessor :foo, :baz
61
- end
62
58
  obj = RubyClass.new
63
59
  obj.foo = "bar"
64
60
 
@@ -67,9 +63,6 @@ describe "when serializing" do
67
63
  end
68
64
 
69
65
  it "should serialize mapped objects" do
70
- class RubyClass
71
- attr_accessor :foo, :baz
72
- end
73
66
  obj = RubyClass.new
74
67
  obj.foo = "bar"
75
68
  RocketAMF::ClassMapper.define {|m| m.map :as => 'org.rocketAMF.ASClass', :ruby => 'RubyClass'}
@@ -77,6 +70,15 @@ describe "when serializing" do
77
70
  output = RocketAMF.serialize(obj, 0)
78
71
  output.should == object_fixture('amf0-typed-object.bin')
79
72
  end
73
+
74
+ if "".respond_to?(:force_encoding)
75
+ it "should support multiple encodings" do
76
+ shift_str = "\x53\x68\x69\x66\x74\x20\x83\x65\x83\x58\x83\x67".force_encoding("Shift_JIS") # "Shift テスト"
77
+ utf_str = "\x55\x54\x46\x20\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding("UTF-8") # "UTF テスト"
78
+ output = RocketAMF.serialize({"0" => 5, "1" => shift_str, "2" => utf_str, "3" => 5}, 0)
79
+ output.should == object_fixture("amf0-complexEncodedStringArray.bin")
80
+ end
81
+ end
80
82
  end
81
83
 
82
84
  describe "AMF3" do
@@ -153,9 +155,6 @@ describe "when serializing" do
153
155
  output = RocketAMF.serialize(input, 3)
154
156
  output.should == expected
155
157
  end
156
-
157
- #BAH! Who sends XML over AMF?
158
- it "should serialize XML"
159
158
  end
160
159
 
161
160
  describe "objects" do
@@ -188,7 +187,7 @@ describe "when serializing" do
188
187
  it "should serialize a hash as a dynamic anonymous object" do
189
188
  hash = {}
190
189
  hash[:answer] = 42
191
- hash[:foo] = "bar"
190
+ hash['foo'] = "bar"
192
191
 
193
192
  expected = object_fixture("amf3-hash.bin")
194
193
  input = hash
@@ -278,6 +277,28 @@ describe "when serializing" do
278
277
  output.should == expected
279
278
  end
280
279
 
280
+ it "should keep reference of duplicate object traits" do
281
+ obj1 = RubyClass.new
282
+ obj1.foo = "foo"
283
+ def obj1.to_amf serializer
284
+ stream = ""
285
+ serializer.write_object(self, stream, {:class_name => 'org.rocketAMF.ASClass', :dynamic => false, :externalizable => false, :members => ["baz", "foo"]})
286
+ stream
287
+ end
288
+ obj2 = RubyClass.new
289
+ obj2.foo = "bar"
290
+ def obj2.to_amf serializer
291
+ stream = ""
292
+ serializer.write_object(self, stream, {:class_name => 'org.rocketAMF.ASClass', :dynamic => false, :externalizable => false, :members => ["baz", "foo"]})
293
+ stream
294
+ end
295
+ input = [obj1, obj2]
296
+
297
+ expected = object_fixture("amf3-traitRef.bin")
298
+ output = RocketAMF.serialize(input, 3)
299
+ output.should == expected
300
+ end
301
+
281
302
  it "should keep references of duplicate arrays" do
282
303
  a = [1,2,3]
283
304
  b = %w{ a b c }
@@ -300,8 +321,6 @@ describe "when serializing" do
300
321
  output.should == expected
301
322
  end
302
323
 
303
- it "should keep references of duplicate XML and XMLDocuments"
304
-
305
324
  it "should keep references of duplicate byte arrays" do
306
325
  b = StringIO.new "ASDF"
307
326
 
@@ -313,8 +332,8 @@ describe "when serializing" do
313
332
 
314
333
  it "should serialize a deep object graph with circular references" do
315
334
  class GraphMember
316
- attr_accessor :parent
317
335
  attr_accessor :children
336
+ attr_accessor :parent
318
337
 
319
338
  def initialize
320
339
  self.children = []
@@ -337,5 +356,26 @@ describe "when serializing" do
337
356
  output.should == expected
338
357
  end
339
358
  end
359
+
360
+ if "".respond_to?(:force_encoding)
361
+ describe "and handling encodings" do
362
+ it "should support multiple encodings" do
363
+ shift_str = "\x53\x68\x69\x66\x74\x20\x83\x65\x83\x58\x83\x67".force_encoding("Shift_JIS") # "Shift テスト"
364
+ utf_str = "\x55\x54\x46\x20\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding("UTF-8") # "UTF テスト"
365
+ output = RocketAMF.serialize([5, shift_str, utf_str, 5], 3)
366
+ output.should == object_fixture("amf3-complexEncodedStringArray.bin")
367
+ end
368
+
369
+ it "should keep references of duplicate strings with different encodings" do
370
+ # String is "this is a テスト"
371
+ shift_str = "\x74\x68\x69\x73\x20\x69\x73\x20\x61\x20\x83\x65\x83\x58\x83\x67".force_encoding("Shift_JIS")
372
+ utf_str = "\x74\x68\x69\x73\x20\x69\x73\x20\x61\x20\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding("UTF-8")
373
+
374
+ expected = object_fixture("amf3-encodedStringRef.bin")
375
+ output = RocketAMF.serialize([shift_str, utf_str], 3)
376
+ output.should == expected
377
+ end
378
+ end
379
+ end
340
380
  end
341
381
  end
@@ -1,6 +1,19 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
2
 
3
3
  describe RocketAMF::Values::ArrayCollection do
4
- it "should deserialize properly"
5
- it "should serialize properly"
4
+ it "should deserialize properly" do
5
+ input = object_fixture("amf3-arrayCollection.bin")
6
+ output = RocketAMF.deserialize(input, 3)
7
+
8
+ output.should be_a(RocketAMF::Values::ArrayCollection)
9
+ output.should == ["foo", "bar"]
10
+ end
11
+
12
+ it "should serialize properly" do
13
+ expected = object_fixture('amf3-arrayCollection.bin')
14
+ input = RocketAMF::Values::ArrayCollection.new
15
+ input.push("foo", "bar")
16
+ output = RocketAMF.serialize(input, 3)
17
+ output.should == expected
18
+ end
6
19
  end
@@ -0,0 +1,2 @@
1
+
2
+ Cflex.messaging.io.ArrayCollection foobar
@@ -0,0 +1 @@
1
+ Shift テストUTF テスト
@@ -0,0 +1 @@
1
+ K<parent><child prop="test"/></parent>
@@ -0,0 +1 @@
1
+ M<parent><child prop="test" /></parent>
@@ -0,0 +1 @@
1
+  K<parent><child prop="test"/></parent> 
@@ -11,13 +11,21 @@ $:.unshift(File.dirname(__FILE__) + '/../lib')
11
11
  require 'rocketamf'
12
12
 
13
13
  def request_fixture(binary_path)
14
- File.open(File.dirname(__FILE__) + '/fixtures/request/' + binary_path).read
14
+ data = File.open(File.dirname(__FILE__) + '/fixtures/request/' + binary_path).read
15
+ data.force_encoding("ASCII-8BIT") if data.respond_to?(:force_encoding)
16
+ data
15
17
  end
16
18
 
17
19
  def object_fixture(binary_path)
18
- File.open(File.dirname(__FILE__) + '/fixtures/objects/' + binary_path).read
20
+ data = File.open(File.dirname(__FILE__) + '/fixtures/objects/' + binary_path).read
21
+ data.force_encoding("ASCII-8BIT") if data.respond_to?(:force_encoding)
22
+ data
19
23
  end
20
24
 
21
25
  def create_request(binary_path)
22
26
  RocketAMF::Request.new.populate_from_stream(StringIO.new(request_fixture(binary_path)))
23
- end
27
+ end
28
+
29
+ # Helper classes
30
+ class RubyClass; attr_accessor :baz, :foo; end;
31
+ class OtherClass; attr_accessor :bar, :foo; end;
metadata CHANGED
@@ -1,16 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: RocketAMF
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
5
11
  platform: ruby
6
12
  authors:
7
- - Tony Hillerson
13
+ - Jacob Henry
8
14
  - Stephen Augenstein
9
15
  autorequire:
10
16
  bindir: bin
11
17
  cert_chain: []
12
18
 
13
- date: 2010-03-30 00:00:00 -04:00
19
+ date: 2010-07-04 00:00:00 -04:00
14
20
  default_executable:
15
21
  dependencies: []
16
22
 
@@ -36,7 +42,6 @@ files:
36
42
  - lib/rocketamf/values/array_collection.rb
37
43
  - lib/rocketamf/values/messages.rb
38
44
  - lib/rocketamf/values/typed_hash.rb
39
- - lib/rocketamf/version.rb
40
45
  - lib/rocketamf.rb
41
46
  - spec/amf/class_mapping_spec.rb
42
47
  - spec/amf/deserializer_spec.rb
@@ -47,6 +52,7 @@ files:
47
52
  - spec/amf/values/messages_spec.rb
48
53
  - spec/spec_helper.rb
49
54
  - spec/fixtures/objects/amf0-boolean.bin
55
+ - spec/fixtures/objects/amf0-complexEncodedStringArray.bin
50
56
  - spec/fixtures/objects/amf0-date.bin
51
57
  - spec/fixtures/objects/amf0-ecma-ordinal-array.bin
52
58
  - spec/fixtures/objects/amf0-hash.bin
@@ -59,20 +65,27 @@ files:
59
65
  - spec/fixtures/objects/amf0-typed-object.bin
60
66
  - spec/fixtures/objects/amf0-undefined.bin
61
67
  - spec/fixtures/objects/amf0-untyped-object.bin
68
+ - spec/fixtures/objects/amf0-xmlDoc.bin
62
69
  - spec/fixtures/objects/amf3-0.bin
70
+ - spec/fixtures/objects/amf3-arrayCollection.bin
63
71
  - spec/fixtures/objects/amf3-arrayRef.bin
64
72
  - spec/fixtures/objects/amf3-bigNum.bin
65
73
  - spec/fixtures/objects/amf3-byteArray.bin
66
74
  - spec/fixtures/objects/amf3-byteArrayRef.bin
75
+ - spec/fixtures/objects/amf3-complexEncodedStringArray.bin
67
76
  - spec/fixtures/objects/amf3-date.bin
68
77
  - spec/fixtures/objects/amf3-datesRef.bin
78
+ - spec/fixtures/objects/amf3-dictionary.bin
69
79
  - spec/fixtures/objects/amf3-dynObject.bin
70
80
  - spec/fixtures/objects/amf3-emptyArray.bin
71
81
  - spec/fixtures/objects/amf3-emptyArrayRef.bin
82
+ - spec/fixtures/objects/amf3-emptyDictionary.bin
72
83
  - spec/fixtures/objects/amf3-emptyStringRef.bin
84
+ - spec/fixtures/objects/amf3-encodedStringRef.bin
73
85
  - spec/fixtures/objects/amf3-false.bin
74
86
  - spec/fixtures/objects/amf3-graphMember.bin
75
87
  - spec/fixtures/objects/amf3-hash.bin
88
+ - spec/fixtures/objects/amf3-intVector.bin
76
89
  - spec/fixtures/objects/amf3-largeMax.bin
77
90
  - spec/fixtures/objects/amf3-largeMin.bin
78
91
  - spec/fixtures/objects/amf3-max.bin
@@ -80,6 +93,7 @@ files:
80
93
  - spec/fixtures/objects/amf3-mixedArray.bin
81
94
  - spec/fixtures/objects/amf3-null.bin
82
95
  - spec/fixtures/objects/amf3-objRef.bin
96
+ - spec/fixtures/objects/amf3-objVector.bin
83
97
  - spec/fixtures/objects/amf3-primArray.bin
84
98
  - spec/fixtures/objects/amf3-string.bin
85
99
  - spec/fixtures/objects/amf3-stringRef.bin
@@ -87,6 +101,9 @@ files:
87
101
  - spec/fixtures/objects/amf3-traitRef.bin
88
102
  - spec/fixtures/objects/amf3-true.bin
89
103
  - spec/fixtures/objects/amf3-typedObject.bin
104
+ - spec/fixtures/objects/amf3-xml.bin
105
+ - spec/fixtures/objects/amf3-xmlDoc.bin
106
+ - spec/fixtures/objects/amf3-xmlRef.bin
90
107
  - spec/fixtures/request/acknowledge-response.bin
91
108
  - spec/fixtures/request/amf0-error-response.bin
92
109
  - spec/fixtures/request/commandMessage.bin
@@ -106,24 +123,30 @@ rdoc_options:
106
123
  require_paths:
107
124
  - lib
108
125
  required_ruby_version: !ruby/object:Gem::Requirement
126
+ none: false
109
127
  requirements:
110
128
  - - ">="
111
129
  - !ruby/object:Gem::Version
130
+ hash: 3
131
+ segments:
132
+ - 0
112
133
  version: "0"
113
- version:
114
134
  required_rubygems_version: !ruby/object:Gem::Requirement
135
+ none: false
115
136
  requirements:
116
137
  - - ">="
117
138
  - !ruby/object:Gem::Version
139
+ hash: 3
140
+ segments:
141
+ - 0
118
142
  version: "0"
119
- version:
120
143
  requirements: []
121
144
 
122
145
  rubyforge_project:
123
- rubygems_version: 1.3.5
146
+ rubygems_version: 1.3.7
124
147
  signing_key:
125
148
  specification_version: 3
126
- summary: Fast AMF serializer/deserializer and request/response wrappers to simplify remoting implementation
149
+ summary: Fast AMF serializer/deserializer with remoting request/response wrappers to simplify integration
127
150
  test_files:
128
151
  - spec/amf/class_mapping_spec.rb
129
152
  - spec/amf/deserializer_spec.rb
@@ -1,9 +0,0 @@
1
- module RocketAMF
2
- # AMF version
3
- VERSION = '0.0.7'
4
- VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
5
- VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
- VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
7
- VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
8
- VARIANT_BINARY = false
9
- end