Class: RubyAMF::IO::AMFSerializer
- Includes:
- Configuration, BinaryWriter, Constants, VoHelper
- Defined in:
- lib/revent/amf3/io/amf_serializer.rb
Instance Attribute Summary collapse
-
#stream ⇒ Object
Returns the value of attribute stream.
Instance Method Summary collapse
-
#initialize ⇒ AMFSerializer
constructor
A new instance of AMFSerializer.
- #reset ⇒ Object
- #reset_referencables ⇒ Object
- #write_amf3(value) ⇒ Object
- #write_amf3_array(array) ⇒ Object
- #write_amf3_byte_array(byte_array) ⇒ Object
-
#write_amf3_date(datetime) ⇒ Object
Aryk: Dates will almost never be the same, so turn off the storing_objects.
- #write_amf3_integer(int) ⇒ Object
- #write_amf3_number(number) ⇒ Object
- #write_amf3_object(hash) ⇒ Object
- #write_amf3_string(string) ⇒ Object
- #write_amf3_xml(value) ⇒ Object
Constructor Details
#initialize ⇒ AMFSerializer
Returns a new instance of AMFSerializer.
15 16 17 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 15 def initialize reset end |
Instance Attribute Details
#stream ⇒ Object
Returns the value of attribute stream.
13 14 15 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 13 def stream @stream end |
Instance Method Details
#reset ⇒ Object
19 20 21 22 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 19 def reset @stream = '' reset_referencables end |
#reset_referencables ⇒ Object
24 25 26 27 28 29 30 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 24 def reset_referencables @stored_strings = {} # hash is way faster than array @stored_strings[""] = true # add this in automatically @floats_cache = {} # for write_double at read_write.rb @write_amf3_integer_results = {} # cache the integers @current_strings_index = 0 end |
#write_amf3(value) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 32 def write_amf3(value) if !value @stream << "\001" # represents an amf3 null elsif (value.is_a?(TrueClass) || value.is_a?(FalseClass)) value ? (@stream << "\003") : (@stream << "\002") # represents an amf3 true and false elsif value.is_a?(Numeric) if value.is_a?(Integer) # Aryk: This was also incorrect before because you has Bignum check AFTER the Integer check, which means the Bignum's were getting picked up by Integers if value.is_a?(Bignum) @stream << "\005" # represents an amf3 complex number write_double(value) else write_amf3_number(value) end elsif value.is_a?(Float) @stream << "\005" # represents an amf3 complex number write_double(value) elsif value.is_a?(BigDecimal) # Aryk: BigDecimal does not relate to Float, so keep it as a seperate check. # TODO: Aryk: Not quite sure why you do value.to_s.to_f? can't you just do value.to_f? value = value.to_s('F').to_f #this is turning a string into a Ruby Float, but because there are no further operations on it it is safe @stream << "\005" # represents an amf3 complex number write_double(value) end elsif value.is_a?(String) @stream << "\006" # represents an amf3 string write_amf3_string(value) elsif value.is_a?(Array) write_amf3_array(value) elsif value.is_a?(ByteArray) write_amf3_byte_array(value) elsif value.is_a?(Hash) write_amf3_object(value) elsif value.is_a?(Time) || value.is_a?(Date) @stream << "\b" # represents an amf3 date write_amf3_date(value) # I know we can combine this with the last condition, but don't ; the Rexml and Beautiful Soup test is expensive, and for large record sets with many AR its better to be able to skip the next step elsif value.is_a?(ActiveRecord::Base) # Aryk: this way, we can bypass the "['REXML::Document', 'BeautifulSoup'].include?(value.class.to_s) " operation write_amf3_object(VoUtil.get_vo_hash_for_outgoing(value)) elsif ['REXML::Document', 'BeautifulSoup'].include?(value.class.to_s) write_byte(AMF3_XML) write_amf3_xml(value) elsif value.is_a?(Object) write_amf3_object(VoUtil.get_vo_hash_for_outgoing(value) ) end end |
#write_amf3_array(array) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 152 def write_amf3_array(array) num_objects = array.length * 2 + 1 if ClassMappings.use_array_collection @stream << "\n\a" # AMF3_OBJECT and AMF3_XML write_amf3_string("flex.messaging.io.ArrayCollection") end @stream << "\t" # represents an amf3 array write_amf3_integer(num_objects) @stream << "\001" # represents an amf3 empty string #write empty for string keyed elements here, as it's never allowed from ruby array.each{|v| write_amf3(v) } end |
#write_amf3_byte_array(byte_array) ⇒ Object
177 178 179 180 181 182 183 184 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 177 def write_amf3_byte_array(byte_array) write_word8(AMF3_BYTE_ARRAY) bytes = byte_array.bytes length = bytes.length << 1 length = length | 0x1 write_amf3_integer(length) @stream << bytes end |
#write_amf3_date(datetime) ⇒ Object
Aryk: Dates will almost never be the same, so turn off the storing_objects
164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 164 def write_amf3_date(datetime) # Aryk: Dates will almost never be the same, so turn off the storing_objects write_amf3_integer(1) seconds = if datetime.is_a?(Time) datetime.utc unless datetime.utc? datetime.to_f elsif datetime.is_a?(Date) # this also handles the case for DateTime datetime.strftime("%s").to_i # datetime = Time.gm( datetime.year, datetime.month, datetime.day ) # datetime = Time.gm( datetime.year, datetime.month, datetime.day, datetime.hour, datetime.min, datetime.sec ) end write_double((seconds*1000).to_i) # used to be total_milliseconds = datetime.to_i * 1000 + ( datetime.usec/1000 ) end |
#write_amf3_integer(int) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 87 def write_amf3_integer(int) @stream << (@write_amf3_integer_results[int] ||= ( int = int & 0x1fffffff if int < 0x80 [int].pack('c') elsif int < 0x4000 [int >> 7 & 0x7f | 0x80].pack('c') + [int & 0x7f].pack('c') elsif int < 0x200000 [int >> 14 & 0x7f | 0x80].pack('c') + [int >> 7 & 0x7f | 0x80].pack('c') + [int & 0x7f].pack('c') else [int >> 22 & 0x7f | 0x80].pack('c') + [int >> 15 & 0x7f | 0x80].pack('c') + [int >> 8 & 0x7f | 0x80].pack('c') + [int & 0xff].pack('c') end )) end |
#write_amf3_number(number) ⇒ Object
108 109 110 111 112 113 114 115 116 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 108 def write_amf3_number(number) if(number >= AMF3_INTEGER_MIN && number <= AMF3_INTEGER_MAX) #check valid range for 29bits @stream << "\004" # represents an amf3 integer write_amf3_integer(number) else #overflow condition otherwise @stream << "\005" # represents an amf3 complex number write_double(number) end end |
#write_amf3_object(hash) ⇒ Object
137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 137 def write_amf3_object(hash) not_vo_hash = !hash.is_a?(VoHash) # is this not a vohash - then doesnt have an _explicitType parameter @stream << "\n\v" # represents an amf3 object and dynamic object not_vo_hash || !hash._explicitType ? (@stream << "\001") : write_amf3_string(hash._explicitType) hash.each do |attr, value| # Aryk: no need to remove any "_explicitType" or "rmember" key since they werent added as keys if not_vo_hash # then that means that the attr might not be symbols and it hasn't gone through camelizing if thats needed attr = attr.to_s.dup # need this just in case its frozen attr.to_camel! if ClassMappings.translate_case end write_amf3_string(attr) value ? write_amf3(value) : (@stream << "\001") # represents an amf3 null end @stream << "\001" # represents an amf3 empty string #close open object end |
#write_amf3_string(string) ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 118 def write_amf3_string(string) if index = @stored_strings[string] if string == "" # store this initially so it gets caught by the stored_strings check @stream << "\001" # represents an amf3 empty string else reference = index << 1 write_amf3_integer(reference) end else @stored_strings[string] = @current_strings_index @current_strings_index += 1 # increment the index reference = string.length reference = reference << 1 reference = reference | 1 write_amf3_integer(reference) writen(string) end end |
#write_amf3_xml(value) ⇒ Object
186 187 188 189 190 191 192 193 194 195 |
# File 'lib/revent/amf3/io/amf_serializer.rb', line 186 def write_amf3_xml(value) xml = value.to_s a = xml.strip if(a != nil) b = a.gsub!(/\>(\n|\r|\r\n| |\t)*\</,'><') #clean whitespace else b = xml.gsub!(/\>(\n|\r|\r\n| |\t)*\</,'><') #clean whitespace end write_amf3_string(b) end |