class AMF::Pure::Serializer
Pure
ruby serializer for AMF3
Public Class Methods
new(class_mapper)
click to toggle source
Pass in the class mapper instance to use when serializing. This enables better caching behavior in the class mapper and allows one to change mappings between serialization attempts.
# File lib/amf/pure/serializer.rb 26 def initialize(class_mapper) 27 @class_mapper = class_mapper 28 @stream = '' 29 @depth = 0 30 end
Public Instance Methods
serialize(obj)
click to toggle source
Serialize the given object using AMF3. Can be called from inside encode_amf.
# File lib/amf/pure/serializer.rb 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
write_array(value)
click to toggle source
Helper for writing arrays inside encode_amf.
# File lib/amf/pure/serializer.rb 90 def write_array(value) 91 amf3_write_array(value) 92 end
write_object(obj, props = nil, traits = nil)
click to toggle source
Helper for writing objects inside encode_amf. If you pass in a property hash, it will use it rather than having the class mapper determine properties. You can also specify a traits hash, which can be used to reduce serialized data size or serialize things as externalizable.
# File lib/amf/pure/serializer.rb 99 def write_object(obj, props = nil, traits = nil) 100 amf3_write_object(obj, props, traits) 101 end
Private Instance Methods
amf3_serialize(object)
click to toggle source
# File lib/amf/pure/serializer.rb 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
amf3_write_array(value)
click to toggle source
# File lib/amf/pure/serializer.rb 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
amf3_write_byte_array(value)
click to toggle source
# File lib/amf/pure/serializer.rb 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
amf3_write_date(value)
click to toggle source
# File lib/amf/pure/serializer.rb 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
amf3_write_false()
click to toggle source
# File lib/amf/pure/serializer.rb 122 def amf3_write_false 123 # no data is serialized except their type marker 124 @stream << AMF3_MARKER_FALSE 125 end
amf3_write_null()
click to toggle source
# File lib/amf/pure/serializer.rb 110 def amf3_write_null 111 # no data is serialized except their type marker 112 @stream << AMF3_MARKER_NULL 113 end
amf3_write_numeric(value)
click to toggle source
# File lib/amf/pure/serializer.rb 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
amf3_write_object(value, properties = nil, traits = nil)
click to toggle source
# File lib/amf/pure/serializer.rb 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
amf3_write_reference(index)
click to toggle source
# File lib/amf/pure/serializer.rb 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
amf3_write_string(value)
click to toggle source
# File lib/amf/pure/serializer.rb 284 def amf3_write_string(value) 285 @stream << AMF3_MARKER_STRING 286 amf3_write_string_internal value 287 end
amf3_write_string_internal(value)
click to toggle source
# File lib/amf/pure/serializer.rb 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
amf3_write_time(value)
click to toggle source
# File lib/amf/pure/serializer.rb 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
amf3_write_true()
click to toggle source
# File lib/amf/pure/serializer.rb 116 def amf3_write_true 117 # no data is serialized except their type marker 118 @stream << AMF3_MARKER_TRUE 119 end