mrpin-amf 2.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/README.rdoc +52 -0
  4. data/Rakefile +59 -0
  5. data/benchmark.rb +86 -0
  6. data/doc/amf3-speification.pdf +0 -0
  7. data/ext/rocketamf_ext/class_mapping.c +483 -0
  8. data/ext/rocketamf_ext/constants.h +52 -0
  9. data/ext/rocketamf_ext/deserializer.c +776 -0
  10. data/ext/rocketamf_ext/deserializer.h +28 -0
  11. data/ext/rocketamf_ext/extconf.rb +18 -0
  12. data/ext/rocketamf_ext/remoting.c +184 -0
  13. data/ext/rocketamf_ext/rocketamf_ext.c +38 -0
  14. data/ext/rocketamf_ext/serializer.c +834 -0
  15. data/ext/rocketamf_ext/serializer.h +29 -0
  16. data/ext/rocketamf_ext/utility.h +4 -0
  17. data/lib/amf/common/hash_with_type.rb +20 -0
  18. data/lib/amf/ext.rb +22 -0
  19. data/lib/amf/pure/amf_constants.rb +42 -0
  20. data/lib/amf/pure/deserializer.rb +354 -0
  21. data/lib/amf/pure/errors/all_files.rb +2 -0
  22. data/lib/amf/pure/errors/amf_error.rb +5 -0
  23. data/lib/amf/pure/errors/amf_error_incomplete.rb +5 -0
  24. data/lib/amf/pure/helpers/all_files.rb +8 -0
  25. data/lib/amf/pure/helpers/cache_objects.rb +18 -0
  26. data/lib/amf/pure/helpers/cache_strings.rb +14 -0
  27. data/lib/amf/pure/helpers/io_helper_base.rb +19 -0
  28. data/lib/amf/pure/helpers/io_helper_read.rb +67 -0
  29. data/lib/amf/pure/helpers/io_helper_write.rb +49 -0
  30. data/lib/amf/pure/mapping/class_mapper.rb +159 -0
  31. data/lib/amf/pure/mapping/mapping_set.rb +49 -0
  32. data/lib/amf/pure/serializer.rb +318 -0
  33. data/lib/amf/pure.rb +16 -0
  34. data/lib/amf.rb +140 -0
  35. data/mrpin-amf.gemspec +24 -0
  36. data/spec/fixtures/objects/complex/amf3-associative-array.bin +1 -0
  37. data/spec/fixtures/objects/complex/amf3-byte-array.bin +0 -0
  38. data/spec/fixtures/objects/complex/amf3-date.bin +0 -0
  39. data/spec/fixtures/objects/complex/amf3-dictionary.bin +0 -0
  40. data/spec/fixtures/objects/complex/amf3-dynamic-object.bin +2 -0
  41. data/spec/fixtures/objects/complex/amf3-empty-array.bin +1 -0
  42. data/spec/fixtures/objects/complex/amf3-empty-dictionary.bin +0 -0
  43. data/spec/fixtures/objects/complex/amf3-hash.bin +2 -0
  44. data/spec/fixtures/objects/complex/amf3-mixed-array.bin +10 -0
  45. data/spec/fixtures/objects/complex/amf3-primitive-array.bin +1 -0
  46. data/spec/fixtures/objects/complex/amf3-typed-object.bin +2 -0
  47. data/spec/fixtures/objects/encoding/amf3-complex-encoded-string-array.bin +1 -0
  48. data/spec/fixtures/objects/encoding/amf3-encoded-string-ref.bin +0 -0
  49. data/spec/fixtures/objects/references/amf3-array-ref.bin +1 -0
  50. data/spec/fixtures/objects/references/amf3-byte-array-ref.bin +1 -0
  51. data/spec/fixtures/objects/references/amf3-date-ref.bin +0 -0
  52. data/spec/fixtures/objects/references/amf3-empty-array-ref.bin +1 -0
  53. data/spec/fixtures/objects/references/amf3-empty-string-ref.bin +1 -0
  54. data/spec/fixtures/objects/references/amf3-graph-member.bin +0 -0
  55. data/spec/fixtures/objects/references/amf3-object-ref.bin +0 -0
  56. data/spec/fixtures/objects/references/amf3-string-ref.bin +0 -0
  57. data/spec/fixtures/objects/references/amf3-trait-ref.bin +3 -0
  58. data/spec/fixtures/objects/simple/amf3-0.bin +0 -0
  59. data/spec/fixtures/objects/simple/amf3-bigNum.bin +0 -0
  60. data/spec/fixtures/objects/simple/amf3-false.bin +1 -0
  61. data/spec/fixtures/objects/simple/amf3-float.bin +0 -0
  62. data/spec/fixtures/objects/simple/amf3-large-max.bin +0 -0
  63. data/spec/fixtures/objects/simple/amf3-large-min.bin +0 -0
  64. data/spec/fixtures/objects/simple/amf3-max.bin +1 -0
  65. data/spec/fixtures/objects/simple/amf3-min.bin +0 -0
  66. data/spec/fixtures/objects/simple/amf3-null.bin +1 -0
  67. data/spec/fixtures/objects/simple/amf3-string.bin +1 -0
  68. data/spec/fixtures/objects/simple/amf3-symbol.bin +1 -0
  69. data/spec/fixtures/objects/simple/amf3-true.bin +1 -0
  70. data/spec/helpers/class_mapping_test.rb +4 -0
  71. data/spec/helpers/class_mapping_test2.rb +3 -0
  72. data/spec/helpers/fixtures.rb +34 -0
  73. data/spec/helpers/other_class.rb +4 -0
  74. data/spec/helpers/ruby_class.rb +4 -0
  75. data/spec/helpers/test_ruby_class.rb +4 -0
  76. data/spec/spec-class_mapping.rb +98 -0
  77. data/spec/spec_deserializer.rb +239 -0
  78. data/spec/spec_fast_class_mapping.rb +147 -0
  79. data/spec/spec_helper.rb +8 -0
  80. data/spec/spec_serializer.rb +267 -0
  81. metadata +146 -0
@@ -0,0 +1,159 @@
1
+ require 'amf/pure/mapping/mapping_set'
2
+
3
+ module AMF
4
+
5
+ # Handles class name mapping between other language and ruby and assists in
6
+ # serializing and deserializing data between them. Simply map an other-language class to a
7
+ # ruby class and when the object is (de)serialized it will end up as the
8
+ # appropriate class.
9
+ #
10
+ # Example:
11
+ #
12
+ # AMF.class_mapper.register_class_alias('SomeClass', 'RubyClass')
13
+ #
14
+ # class_map =
15
+ # {
16
+ # 'ClassNameLocal0' => 'ClassNameRemote0',
17
+ # 'ClassNameLocal1' => 'ClassNameRemote1'
18
+ # }
19
+ # AMF::Root.register_classes(class_map)
20
+
21
+ #
22
+ class ClassMapper
23
+
24
+ class << self
25
+
26
+ attr_reader :map
27
+
28
+ #
29
+ # Methods
30
+ #
31
+
32
+ public
33
+ def initialize
34
+ @map = MappingSet.new
35
+ end
36
+
37
+ public
38
+ def register_class_alias(class_local, class_remote)
39
+ @map.register_class_alias(class_local, class_remote)
40
+ end
41
+
42
+ public
43
+ def register_classes(map)
44
+ map.each do |class_local, class_remote|
45
+ self.register_class_alias(class_local, class_remote)
46
+ end
47
+ end
48
+
49
+ # Reset all class mappings except the defaults
50
+ public
51
+ def reset
52
+ @map = MappingSet.new
53
+ nil
54
+ end
55
+ end #end of static
56
+
57
+ # init static
58
+ self.initialize
59
+
60
+ #
61
+ # Methods
62
+ #
63
+
64
+ public
65
+ def initialize
66
+ #cache static variable
67
+ @map = ClassMapper.map
68
+ @ignored_props = Object.new.public_methods
69
+ end
70
+
71
+ # Returns the other-language class name for the given ruby object.
72
+ public
73
+ def get_class_name_remote(object)
74
+ # Get class name
75
+ return object.class_type if object.is_a?(HashWithType)
76
+ return nil if object.is_a?(Hash)
77
+
78
+ class_name_local = object.class.name
79
+
80
+ # Get mapped remote class name
81
+ @map.get_class_name_remote(class_name_local)
82
+ end
83
+
84
+ # Instantiates a ruby object using the mapping configuration based on the
85
+ # source ActionScript class name. If there is no mapping defined, it returns
86
+ # a <tt>AMF::HashWithType</tt> with the serialized class name.
87
+ public
88
+ def create_object(class_name_remote)
89
+ result = nil
90
+
91
+ if class_name_remote.nil? || class_name_remote.empty?
92
+ return {}
93
+ end
94
+
95
+ class_name_local = @map.get_class_name_local(class_name_remote)
96
+
97
+ if class_name_local.nil?
98
+ # Populate a simple hash, since no mapping
99
+ result = HashWithType.new(class_name_remote)
100
+ else
101
+ ruby_class = class_name_local.split('::').inject(Kernel) { |scope, const_name| scope.const_get(const_name) }
102
+ result = ruby_class.new
103
+ end
104
+
105
+ result
106
+ end
107
+
108
+ # Populates the ruby object using the given properties. props will be hashes with symbols for keys.
109
+ public
110
+ def object_deserialize(target, props)
111
+ # Don't even bother checking if it responds to setter methods if it's a TypedHash
112
+ if target.is_a?(HashWithType)
113
+ target.merge! props
114
+ return target
115
+ end
116
+
117
+ # Some type of object
118
+ hash_like = target.respond_to?('[]=')
119
+
120
+ props.each do |key, value|
121
+ if target.respond_to?("#{key}=")
122
+ target.send("#{key}=", value)
123
+ elsif hash_like
124
+ target[key] = value
125
+ end
126
+ end
127
+
128
+ target
129
+ end
130
+
131
+ # Extracts all exportable properties from the given ruby object and returns
132
+ # them in a hash. If overriding, make sure to return a hash wth string keys
133
+ # unless you are only going to be using the native C extensions, as the pure
134
+ # ruby serializer performs a sort on the keys to acheive consistent, testable
135
+ # results.
136
+ public
137
+ def object_serialize(ruby_obj)
138
+ result = {}
139
+
140
+ # Handle hashes
141
+ if ruby_obj.is_a?(Hash)
142
+
143
+ # Stringify keys to make it easier later on and allow sorting
144
+ ruby_obj.each { |k, v| result[k.to_s] = v }
145
+
146
+ else
147
+
148
+ # Generic object serializer
149
+ (ruby_obj.public_methods - @ignored_props).each do |method_name|
150
+ # Add them to the prop hash if they take no arguments
151
+ method_def = ruby_obj.method(method_name)
152
+ result[method_name.to_s] = ruby_obj.send(method_name) if method_def.arity == 0
153
+ end
154
+ end
155
+
156
+ result
157
+ end # props_for_serialization
158
+ end #ClassMapping
159
+ end #AMF
@@ -0,0 +1,49 @@
1
+ module AMF
2
+
3
+ # Container for all mapped classes
4
+ class MappingSet
5
+
6
+ #
7
+ # Methods
8
+ #
9
+
10
+ # Creates a mapping set object and populates the default mappings
11
+ public
12
+ def initialize
13
+ @mappings_remote = {}
14
+ @mappings_local = {}
15
+ end
16
+
17
+ # Map a given other-language class to a ruby class.
18
+ #
19
+ # Use fully qualified names for both.
20
+ #
21
+ # Example:
22
+ #
23
+ # register_class_alias('Example::Date', 'com.example.Date')
24
+ public
25
+ def register_class_alias(class_local, class_remote)
26
+ # Convert params to strings
27
+ class_remote = class_remote.to_s
28
+ class_local = class_local.to_s
29
+
30
+ @mappings_remote[class_remote] = class_local
31
+ @mappings_local[class_local] = class_remote
32
+ end
33
+
34
+ # Returns the ruby class name for the given other-language class name
35
+ # returning nil if not found
36
+ public
37
+ def get_class_name_local(class_name_remote) #:nodoc:
38
+ @mappings_remote[class_name_remote.to_s]
39
+ end
40
+
41
+ # Returns the other-language class name for the given ruby class name,
42
+ # returning nil if not found
43
+ public
44
+ def get_class_name_remote(class_name_local) #:nodoc:
45
+ @mappings_local[class_name_local.to_s]
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,318 @@
1
+ module AMF
2
+ module Pure
3
+ # Pure ruby serializer for AMF3
4
+ class Serializer
5
+
6
+ #
7
+ # Modules
8
+ #
9
+
10
+ private
11
+ include AMF::Pure::IOHelperWrite
12
+ include AMF::AMFConstants
13
+
14
+ #
15
+ # Properties
16
+ #
17
+
18
+ #
19
+ # Methods
20
+ #
21
+
22
+ # Pass in the class mapper instance to use when serializing. This enables
23
+ # better caching behavior in the class mapper and allows one to change
24
+ # mappings between serialization attempts.
25
+ public
26
+ def initialize(class_mapper)
27
+ @class_mapper = class_mapper
28
+ @stream = ''
29
+ @depth = 0
30
+ end
31
+
32
+ # Serialize the given object using AMF3. Can be called from inside
33
+ # encode_amf.
34
+ def serialize(obj)
35
+ # Initialize caches
36
+ if @depth == 0
37
+ @cache_strings = CacheStrings.new
38
+ @cache_objects = CacheObjects.new
39
+ @cache_traits = CacheStrings.new
40
+ end
41
+ @depth += 1
42
+
43
+ # Perform serialization
44
+ amf3_serialize(obj)
45
+
46
+ # Cleanup
47
+ @depth -= 1
48
+
49
+ if @depth == 0
50
+ @cache_strings = nil
51
+ @cache_objects = nil
52
+ @cache_traits = nil
53
+ end
54
+
55
+ @stream
56
+ end
57
+
58
+ private
59
+ def amf3_serialize(object)
60
+ case true
61
+ when object.is_a?(NilClass)
62
+ amf3_write_null
63
+ when object.respond_to?(:encode_amf)
64
+ object.encode_amf(self)
65
+ when object.is_a?(TrueClass)
66
+ amf3_write_true
67
+ when object.is_a?(FalseClass)
68
+ amf3_write_false
69
+ when object.is_a?(Numeric)
70
+ amf3_write_numeric(object)
71
+ when object.is_a?(Symbol), object.is_a?(String)
72
+ amf3_write_string(object.to_s)
73
+ when object.is_a?(Time)
74
+ amf3_write_time object
75
+ when object.is_a?(Date)
76
+ amf3_write_date(object)
77
+ when object.is_a?(StringIO)
78
+ amf3_write_byte_array(object)
79
+ when object.is_a?(Array)
80
+ amf3_write_array(object)
81
+ when object.is_a?(Hash), object.is_a?(Object)
82
+ amf3_write_object(object)
83
+ else
84
+ raise AMFError, 'unknown type for serialize'
85
+ end
86
+ end
87
+
88
+ # Helper for writing arrays inside encode_amf.
89
+ public
90
+ def write_array(value)
91
+ amf3_write_array(value)
92
+ end
93
+
94
+ # Helper for writing objects inside encode_amf. If you pass in a property hash, it will use
95
+ # it rather than having the class mapper determine properties.
96
+ # You can also specify a traits hash, which can be used to reduce serialized
97
+ # data size or serialize things as externalizable.
98
+ public
99
+ def write_object(obj, props = nil, traits = nil)
100
+ amf3_write_object(obj, props, traits)
101
+ end
102
+
103
+ private
104
+ def amf3_write_reference(index)
105
+ header = index << 1 # shift value left to leave a low bit of 0
106
+ @stream << pack_integer(header)
107
+ end
108
+
109
+ private
110
+ def amf3_write_null
111
+ # no data is serialized except their type marker
112
+ @stream << AMF3_MARKER_NULL
113
+ end
114
+
115
+ private
116
+ def amf3_write_true
117
+ # no data is serialized except their type marker
118
+ @stream << AMF3_MARKER_TRUE
119
+ end
120
+
121
+ private
122
+ def amf3_write_false
123
+ # no data is serialized except their type marker
124
+ @stream << AMF3_MARKER_FALSE
125
+ end
126
+
127
+ private
128
+ def amf3_write_numeric(value)
129
+ if !value.integer? || value < INTEGER_MIN || value > INTEGER_MAX # Check valid range for 29 bits
130
+ @stream << AMF3_MARKER_DOUBLE
131
+ @stream << pack_double(value)
132
+ else
133
+ @stream << AMF3_MARKER_INTEGER
134
+ @stream << pack_integer(value)
135
+ end
136
+ end
137
+
138
+ private
139
+ def amf3_write_time(value)
140
+ @stream << AMF3_MARKER_DATE
141
+
142
+ if @cache_objects[value] != nil
143
+ amf3_write_reference(@cache_objects[value])
144
+ else
145
+ # Cache time
146
+ @cache_objects.add_object(value)
147
+
148
+ # Build AMF string
149
+ value = value.getutc # Dup and convert to UTC
150
+ milli = (value.to_f * 1000).to_i
151
+ @stream << AMF3_MARKER_NULL
152
+ @stream << pack_double(milli)
153
+ end
154
+ end
155
+
156
+ private
157
+ def amf3_write_date(value)
158
+ @stream << AMF3_MARKER_DATE
159
+
160
+ if @cache_objects[value] != nil
161
+ amf3_write_reference(@cache_objects[value])
162
+ else
163
+ # Cache date
164
+ @cache_objects.add_object(value)
165
+
166
+ # Build AMF string
167
+ @stream << AMF3_MARKER_NULL
168
+ @stream << pack_double(value.strftime('%Q').to_i)
169
+ end
170
+ end
171
+
172
+ private
173
+ def amf3_write_byte_array(value)
174
+ @stream << AMF3_MARKER_BYTE_ARRAY
175
+
176
+ if @cache_objects[value] != nil
177
+ amf3_write_reference(@cache_objects[value])
178
+ else
179
+ @cache_objects.add_object(value)
180
+ str = value.string
181
+ @stream << pack_integer(str.bytesize << 1 | 1)
182
+ @stream << str
183
+ end
184
+ end
185
+
186
+ private
187
+ def amf3_write_array(value)
188
+ # Write type marker
189
+ @stream << AMF3_MARKER_ARRAY
190
+
191
+ # Write reference or cache array
192
+ if @cache_objects[value] != nil
193
+ amf3_write_reference(@cache_objects[value])
194
+ return
195
+ end
196
+
197
+ @cache_objects.add_object(value)
198
+
199
+ # Build AMF string for array
200
+ header = value.length << 1 # make room for a low bit of 1
201
+ header = header | 1 # set the low bit to 1
202
+ @stream << pack_integer(header)
203
+
204
+ @stream << AMF3_CLOSE_DYNAMIC_ARRAY
205
+
206
+ value.each do |elem|
207
+ amf3_serialize elem
208
+ end
209
+ end
210
+
211
+ private
212
+ def amf3_write_object(value, properties = nil, traits = nil)
213
+ @stream << AMF3_MARKER_OBJECT
214
+
215
+ # Caching...
216
+ if @cache_objects[value] != nil
217
+ amf3_write_reference(@cache_objects[value])
218
+ return
219
+ end
220
+
221
+ @cache_objects.add_object(value)
222
+
223
+ # Calculate traits if not given
224
+ use_default_class_name = false
225
+
226
+ if traits.nil?
227
+ traits =
228
+ {
229
+ class_name: @class_mapper.get_class_name_remote(value),
230
+ members: [],
231
+ dynamic: true
232
+ }
233
+ use_default_class_name = true unless traits[:class_name]
234
+ end
235
+
236
+ class_name = use_default_class_name ? '__default__' : traits[:class_name]
237
+
238
+ # Write out traits
239
+ if !class_name.nil? && @cache_traits[class_name] != nil
240
+ @stream << pack_integer(@cache_traits[class_name] << 2 | 0x01)
241
+ else
242
+ @cache_traits.add_string(class_name) unless class_name.nil?
243
+
244
+ # Write out trait header
245
+ header = 0x03 # Not object ref and not trait ref
246
+ header |= 0x02 << 2 if traits[:dynamic]
247
+ header |= traits[:members].length << 4
248
+ @stream << pack_integer(header)
249
+
250
+ # Write out class name
251
+ if use_default_class_name
252
+ amf3_write_string_internal('')
253
+ else
254
+ amf3_write_string_internal(class_name.to_s)
255
+ end
256
+
257
+ # Write out members
258
+ traits[:members].each { |m| amf3_write_string_internal(m) }
259
+ end
260
+
261
+ # Extract properties if not given
262
+ properties = @class_mapper.object_serialize(value) if properties.nil?
263
+
264
+ # Write out sealed properties
265
+ traits[:members].each do |m|
266
+ amf3_serialize(properties[m])
267
+ properties.delete(m)
268
+ end
269
+
270
+ # Write out dynamic properties
271
+ if traits[:dynamic]
272
+ # Write out dynamic properties
273
+ properties.each do |key, val|
274
+ amf3_write_string_internal(key.to_s)
275
+ amf3_serialize(val)
276
+ end
277
+
278
+ # Write close
279
+ @stream << AMF3_CLOSE_DYNAMIC_OBJECT
280
+ end
281
+ end
282
+
283
+ private
284
+ def amf3_write_string(value)
285
+ @stream << AMF3_MARKER_STRING
286
+ amf3_write_string_internal value
287
+ end
288
+
289
+
290
+ private
291
+ def amf3_write_string_internal(value)
292
+ if value.respond_to?(:encode)
293
+ value = value.dup if value.frozen?
294
+
295
+ value = value.encode('UTF-8')
296
+
297
+ value.force_encoding('ASCII-8BIT')
298
+ end
299
+
300
+ if value == ''
301
+ @stream << AMF3_EMPTY_STRING
302
+ elsif @cache_strings[value] != nil
303
+ amf3_write_reference(@cache_strings[value])
304
+ else
305
+
306
+ # Cache string
307
+ @cache_strings.add_string(value)
308
+
309
+ # Build AMF string
310
+ @stream << pack_integer(value.bytesize << 1 | 1)
311
+ @stream << value
312
+ end
313
+ end
314
+
315
+ end # Serializer
316
+
317
+ end #Pure
318
+ end #AMF
data/lib/amf/pure.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'amf/pure/deserializer'
2
+ require 'amf/pure/serializer'
3
+
4
+ module AMF
5
+ # This module holds all the modules/classes that implement AMF's functionality
6
+ # in pure ruby
7
+ module Pure
8
+ $DEBUG and warn 'Using pure library for AMF.'
9
+ end
10
+
11
+ #:stopdoc:
12
+ # Import serializer/deserializer
13
+ Deserializer = AMF::Pure::Deserializer
14
+ Serializer = AMF::Pure::Serializer
15
+ #:startdoc:
16
+ end
data/lib/amf.rb ADDED
@@ -0,0 +1,140 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+ $:.unshift "#{File.expand_path(File.dirname(__FILE__))}/tamf/"
3
+ $:.unshift "#{File.expand_path(File.dirname(__FILE__))}/amf/types/"
4
+
5
+ require 'date'
6
+ require 'stringio'
7
+ require 'amf/common/hash_with_type'
8
+ require 'amf/pure/errors/all_files'
9
+ require 'amf/pure/helpers/all_files'
10
+ require 'amf/pure/mapping/class_mapper'
11
+
12
+
13
+ #todo: implement C version
14
+ # begin
15
+ # require 'rocketamf/ext'
16
+ # rescue LoadError
17
+
18
+ require 'amf/pure'
19
+ # end
20
+
21
+ # AMF is a full featured AMF3 serializer/deserializer with support for
22
+ # bi-directional other language to ruby class mapping, custom serialization and mapping,
23
+ # remoting gateway helpers that follow AMF3 messaging specs, and a suite of specs
24
+ # to ensure adherence to the specification documents put out by Adobe. If the C
25
+ # components compile, then RocketAMF automatically takes advantage of them to
26
+ # provide a substantial performance benefit. In addition, RocketAMF is fully
27
+ # compatible with Ruby 2.0, 2.1.
28
+ #
29
+ # == Performance
30
+ # # 100.000 objects
31
+ # # Ruby 2.0
32
+ # Testing pure AMF3:
33
+ # minimum serialize time: 49.294496s
34
+ # minimum deserialize time: 6.600238s
35
+ #
36
+ # == Example
37
+ #
38
+ #
39
+ # test_object =
40
+ # {
41
+ # first_name: "Greg",
42
+ # last_name: "House"
43
+ # }
44
+ #
45
+ # data = AMF::Root.serialize(test_object)
46
+ #
47
+ # restored_object = AMF::Root.serialize(data)
48
+ #
49
+ # == Mapping Classes Between Other language and Ruby
50
+ #
51
+ # RocketAMF provides a simple class mapping tool to facilitate serialization and
52
+ # deserialization of typed objects. Refer to the documentation of
53
+ # <tt>RocketAMF::ClassMapping</tt> for more details. If the provided class
54
+ # mapping tool is not sufficient for your needs, you also have the option to
55
+ # replace it with a class mapper of your own devising that matches the documented
56
+ # API.
57
+ #
58
+ # == Advanced Serialization (encode_amf and IExternalizable)
59
+ #
60
+ # RocketAMF provides some additional functionality to support advanced
61
+ # serialization techniques. If you define an <tt>encode_amf</tt> method on your
62
+ # object, it will get called during serialization. It is passed a single argument,
63
+ # the serializer, and it can use the serializer stream, the <tt>serialize</tt>
64
+ # method, the <tt>write_array</tt> method, the <tt>write_object</tt> method, and
65
+ # the serializer version. Below is a simple example that uses <tt>write_object</tt>
66
+ # to customize the property hash that is used for serialization.
67
+ #
68
+ # Example:
69
+ #
70
+ # class TestObject
71
+ # def encode_amf serializer
72
+ # serializer.write_object self, @attributes
73
+ # end
74
+ # end
75
+ #
76
+ # If you plan on using the <tt>serialize</tt> method, make sure to pass in the
77
+ # current serializer version, or you could create a message that cannot be deserialized.
78
+ #
79
+ # Example:
80
+ #
81
+ # class VariableObject
82
+ # def encode_amf serializer
83
+ # serializer.serialize(false)
84
+ # end
85
+ # end
86
+ #
87
+ module AMF
88
+
89
+ class Root
90
+ # Deserialize the AMF string _source_ of the given AMF version into a Ruby
91
+ # data structure and return it. Creates an instance of <tt>AMF::Deserializer</tt>
92
+ # with a new instance of <tt>AMF::Root.class_mapper</tt> and calls deserialize
93
+ # on it with the given source, returning the result.
94
+ public
95
+ def self.deserialize(source)
96
+ deserializer = AMF::Deserializer.new(@class_mapper.new)
97
+ deserializer.deserialize(source)
98
+ end
99
+
100
+ # Serialize the given Ruby data structure _obj_ into an AMF3 stream.
101
+ # Creates an instance of <tt>AMF::Serializer</tt>
102
+ # with a new instance of <tt>AMF::Root.class_mapper</tt> and calls serialize
103
+ # on it with the given object, returning the result.
104
+ public
105
+ def self.serialize(obj)
106
+ serializer = AMF::Serializer.new(@class_mapper.new)
107
+ serializer.serialize(obj)
108
+ end
109
+
110
+ public
111
+ def self.register_class_alias(class_name_local, class_name_remote)
112
+ @class_mapper.register_class_alias(class_name_local, class_name_remote)
113
+ end
114
+
115
+ public
116
+ def self.register_classes(map)
117
+ @class_mapper.register_classes(map)
118
+ end
119
+
120
+ public
121
+ def self.clear_class_aliases
122
+ @class_mapper.reset
123
+ end
124
+
125
+ private
126
+ def self.init_class_mapper
127
+ #todo: use c version
128
+ # Activating the C Class Mapper:
129
+ # require 'rubygems'
130
+ # require 'amf'
131
+ # AMF::ClassMapper = AMF::Ext::FastClassMapping
132
+
133
+ @class_mapper = AMF::ClassMapper
134
+ end
135
+
136
+ init_class_mapper
137
+
138
+ end
139
+
140
+ end
data/mrpin-amf.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'mrpin-amf'
5
+ spec.version = '2.1.8'
6
+ spec.platform = Gem::Platform::RUBY
7
+ spec.authors = ['Jacob Henry', 'Stephen Augenstein', "Joc O'Connor", 'Gregory Tkach']
8
+ spec.email = %w(gregory.tkach@gmail.com)
9
+ spec.homepage = 'https://github.com/mrpin/mrpin-amf-ruby'
10
+ spec.license = 'MIT'
11
+ spec.summary = 'Fast AMF3 serializer/deserializer'
12
+ spec.description = 'Fast AMF3 serializer/deserializer with remoting request/response wrappers to simplify integration'
13
+
14
+ spec.files = `git ls-files`.split($/)
15
+ spec.test_files = Dir[*['spec/**/*_spec.rb']]
16
+ spec.extensions = Dir[*['ext/**/extconf.rb']]
17
+ spec.require_paths = ['lib']
18
+
19
+ spec.add_development_dependency 'rake-compiler', '~> 0'
20
+
21
+ spec.has_rdoc = true
22
+ spec.extra_rdoc_files = %w( README.rdoc )
23
+ spec.rdoc_options = %w(--line-numbers --main README.rdoc)
24
+ end
@@ -0,0 +1 @@
1
+  asdf fdsafoobar42 bar1 bar2 bar3