RocketAMF 0.0.7 → 0.1.0

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