$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) $:.unshift "#{File.expand_path(File.dirname(__FILE__))}/rocketamf/" require 'rocketamf/class_mapping' require 'rocketamf/constants' require 'rocketamf/remoting' # Joc's monkeypatch for string bytesize (only available in 1.8.7+) if !"amf".respond_to? :bytesize class String def bytesize self.size end end end # RocketAMF is a full featured AMF0/3 serializer and deserializer with support # for Flash -> Ruby and Ruby -> Flash class mapping, custom serializers, # remoting gateway helpers that follow AMF0/3 messaging specs, and a suite of # specs to ensure adherence to the specification documents put out by Adobe. # # == Serialization & Deserialization # # RocketAMF provides two main methods - RocketAMF.serialize(obj, amf_version=0) # and RocketAMF.deserialize(source, amf_version=0). To use, simple pass # in the string to deserialize and the version if different from the default. To # serialize an object, simply call RocketAMF.serialize with the object # and the proper version. If you're working only with AS3, it is more effiecient # to use the version 3 encoding, as it caches duplicate string to reduce # serialized size. However for greater compatibility the default, AMF version 0, # should work fine. # # == Mapping Classes Between Flash and Ruby # # RocketAMF provides a simple class mapping tool to facilitate serialization and # deserialization of typed objects. Refer to the documentation of # RocketAMF::ClassMapping for more details. If the provided class # mapping tool is not sufficient for your needs, you also have the option to # replace it with a class mapper of your own devising that matches the documented # API. # # == Remoting # # You can use RocketAMF bare to write an AMF gateway using the following code. # In addition, you can use rack-amf (http://github.com/warhammerkid/rack-amf) # which simplifies the code necessary to set up a functioning AMF gateway. # # # helloworld.ru # require 'rocketamf' # # class HelloWorldApp # APPLICATION_AMF = 'application/x-amf'.freeze # # def call env # if is_amf?(env) # # Wrap request and response # env['rack.input'].rewind # request = RocketAMF::Envelope.new.populate_from_stream(env['rack.input'].read) # response = RocketAMF::Envelope.new # # # Handle request # response.each_method_call request do |method, args| # raise "Service #{method} does not exists" unless method == 'App.helloWorld' # 'Hello world' # end # # # Pass back response # response_str = response.serialize # return [200, {'Content-Type' => APPLICATION_AMF, 'Content-Length' => response_str.length.to_s}, [response_str]] # else # return [200, {'Content-Type' => 'text/plain', 'Content-Length' => '16' }, ["Rack AMF gateway"]] # end # end # # private # def is_amf? env # return false unless env['CONTENT_TYPE'] == APPLICATION_AMF # return false unless env['PATH_INFO'] == '/amf' # return true # end # end # # run HelloWorldApp.new module RocketAMF begin raise LoadError, 'C extensions not implemented' rescue LoadError require 'rocketamf/pure' end # Deserialize the AMF string _source_ of the given AMF version into a Ruby # data structure and return it def self.deserialize source, amf_version = 0 if amf_version == 0 RocketAMF::Deserializer.new.deserialize(source) elsif amf_version == 3 RocketAMF::AMF3Deserializer.new.deserialize(source) else raise AMFError, "unsupported version #{amf_version}" end end # Serialize the given Ruby data structure _obj_ into an AMF stream using the # given AMF version def self.serialize obj, amf_version = 0 if amf_version == 0 RocketAMF::Serializer.new.serialize(obj) elsif amf_version == 3 RocketAMF::AMF3Serializer.new.serialize(obj) else raise AMFError, "unsupported version #{amf_version}" end end # We use const_missing to define the active ClassMapper at runtime. This way, # heavy modification of class mapping functionality is still possible without # forcing extenders to redefine the constant. def self.const_missing const #:nodoc: if const == :ClassMapper RocketAMF.const_set(:ClassMapper, RocketAMF::ClassMapping.new) else super(const) end end # The base exception for AMF errors. class AMFError < StandardError; end end