class Marshal::NFREEZE

Public Class Methods

new() click to toggle source
# File lib/nfreeze.rb, line 81
def initialize
   buf   = "".encode Encoding::BINARY
   @io   = StringIO.new buf
   @seen = Hash.new
end

Public Instance Methods

nfreeze(obj) click to toggle source
# File lib/nfreeze.rb, line 72
def nfreeze obj
   @io.rewind
   @io.write "\x5\x8"
   recur obj
   return @io.string
end

Private Instance Methods

dump(x) click to toggle source
# File lib/nfreeze.rb, line 115
def dump x
   @io.write x.chr
end
dump_array(obj) click to toggle source
# File lib/nfreeze.rb, line 119
def dump_array obj
   len = obj.length
   if len > 2147483647
      raise ArgumentError, "#{len} elems array is too big for perl"
   else
      @io.write [2, len].pack('cN')
      obj.each do |i|
         recur i, :ref
      end
   end
end
dump_double(obj) click to toggle source
# File lib/nfreeze.rb, line 154
def dump_double obj
   @io.write [7, obj].pack('cd')
end
dump_hash(obj) click to toggle source
# File lib/nfreeze.rb, line 131
def dump_hash obj
   len = obj.keys.length
   if len > 2147483647
      raise ArgumentError, "#{len} elems hash is too big for perl"
   else
      @io.write [3, len].pack('cN')
      obj.each_pair do |k, v|
         case k when String then
            len = k.bytesize
            if len > 2147483647
               raise ArgumentError, "#{len} octets key is too big for perl"
            else
               recur v, :ref
               @io.write [len, k].pack('NA*')
            end
         else
            raise ArgumentError, "non-string keys cant be represented:"+
               k.inspect
         end                  
      end
   end
end
dump_int(obj) click to toggle source
# File lib/nfreeze.rb, line 158
def dump_int obj
   case obj when (-2147483648 ... 2147483648) then
      @io.write [9, obj].pack('cN')
   else
      raise ArgumentError, "#{obj.inspect} is too big for perl"
   end
end
dump_string(obj) click to toggle source
# File lib/nfreeze.rb, line 166
def dump_string obj
   # Perl can only understand Unicodes
   newobj = obj.encode Encoding::UTF_8
   newlen = newobj.bytesize
   if newlen > 2147483647
      raise ArgumentError, "#{newlen} octets string is too big for perl"
   else
      @io.write [24, newlen, newobj].pack('cNA*')
   end
end
recur(obj, refp = false) click to toggle source
# File lib/nfreeze.rb, line 87
def recur obj, refp = false
   # We  are not  implementing Torjan's  topological sort  algorithm here
   # because our  restriction is stronger  than just unable  to represent
   # infinite loops; we can only serlalize pure trees.
   if @seen.has_key? obj.object_id
      raise ArgumentError, "cyclic data structures not supportted for now"+
         obj.inspect
   else
      case obj when NilClass, Integer, String then
         # immediates
      else
         @seen.store obj.object_id, nil
      end
   end
   case obj
   when NilClass   then dump 14
   when TrueClass  then dump 15
   when FalseClass then dump 16
   when Integer    then dump_int    obj
   when Float      then dump_double obj
   when String     then dump_string obj
   when Array      then dump 4 if refp; dump_array obj
   when Hash       then dump 4 if refp; dump_hash  obj
   else
      raise ArgumentError, "unsupported class encountered: #{obj.inspect}"
   end
end