Parses a tokenized Marshal stream into a structure that resembles how the stream would be loaded.
Marshal can contain references to previous objects. These references are included in the structure following referenceable items. For example, a recursive array:
a = [] a << self
Has the following Marshal stream:
"\x04\x08[\x06@\x00" # @\x00 is a link to the first Object in the stream
And has the following Marshal structure:
[:array, 0, 1, [:link, 0]]
The first item after :array
, the 0
is the
object's stream ID. The :link
references this ID.
Creates a new Parser using a token stream
Enumerator tokens
.
# File lib/marshal/structure/parser.rb, line 29 def initialize tokens @tokens = tokens @objects = -1 @symbols = -1 end
Constructs a Symbol from the token stream
# File lib/marshal/structure/parser.rb, line 262 def get_symbol token = @tokens.next case token when :symbol then [:symbol, *parse_symbol] when :symbol_link then [:symbol_link, @tokens.next] else raise ArgumentError, "expected SYMBOL or SYMLINK, got #{token.inspect}" end end
Creates a new object reference
# File lib/marshal/structure/parser.rb, line 38 def object_ref @objects += 1 end
Creates the structure for the remaining stream.
# File lib/marshal/structure/parser.rb, line 45 def parse token = @tokens.next return token if [:nil, :true, :false].include? token obj = [token] rest = case token when :array then parse_array when :bignum then parse_bignum when :class, :module then parse_class when :data then parse_data when :extended then parse_extended when :fixnum, :link, :symbol_link then [@tokens.next] when :float then parse_float when :hash then parse_hash when :hash_default then parse_hash_def when :object then parse_object when :regexp then parse_regexp when :string then parse_string when :struct then parse_struct when :symbol then parse_symbol when :user_class then parse_extended when :user_defined then parse_user_defined when :user_marshal then parse_user_marshal when :instance_variables then [parse].concat parse_instance_variables when :module_old then obj[0] = :module parse_class else raise Marshal::Structure::Error, "bug: unknown token #{token.inspect}" end obj.concat rest rescue Marshal::Structure::EndOfMarshal raise ArgumentError, 'marshal data too short' end
Creates the body of an :array
object
# File lib/marshal/structure/parser.rb, line 88 def parse_array obj = [object_ref] items = @tokens.next obj << items items.times do obj << parse end obj end
Creates the body of a :bignum
object
# File lib/marshal/structure/parser.rb, line 105 def parse_bignum result = @tokens.next [object_ref, result] end
Creates the body of a :class
object
# File lib/marshal/structure/parser.rb, line 114 def parse_class [object_ref, @tokens.next] end
Creates the body of a wrapped C pointer object
# File lib/marshal/structure/parser.rb, line 121 def parse_data [object_ref, get_symbol, parse] end
Creates the body of an extended object
# File lib/marshal/structure/parser.rb, line 128 def parse_extended [get_symbol, parse] end
Creates the body of a :float
object
# File lib/marshal/structure/parser.rb, line 135 def parse_float float = @tokens.next [object_ref, float] end
Creates the body of a :hash
object
# File lib/marshal/structure/parser.rb, line 144 def parse_hash obj = [object_ref] pairs = @tokens.next obj << pairs pairs.times do obj << parse obj << parse end obj end
Creates the body of a :hash_def
object
# File lib/marshal/structure/parser.rb, line 161 def parse_hash_def ref, hash = parse_hash [ref, hash, parse] end
Instance variables contain an object followed by a count of instance variables and their contents
# File lib/marshal/structure/parser.rb, line 171 def parse_instance_variables instance_variables = [] pairs = @tokens.next instance_variables << pairs pairs.times do instance_variables << get_symbol instance_variables << parse end instance_variables end
Creates an Object
# File lib/marshal/structure/parser.rb, line 188 def parse_object [object_ref, get_symbol, parse_instance_variables] end
Creates a Regexp
# File lib/marshal/structure/parser.rb, line 195 def parse_regexp [object_ref, @tokens.next, @tokens.next] end
Creates a String
# File lib/marshal/structure/parser.rb, line 202 def parse_string [object_ref, @tokens.next] end
Creates a Struct
# File lib/marshal/structure/parser.rb, line 209 def parse_struct obj = [object_ref, get_symbol] members = @tokens.next obj << members members.times do obj << get_symbol obj << parse end obj end
Creates a Symbol
# File lib/marshal/structure/parser.rb, line 226 def parse_symbol sym = @tokens.next [symbol_ref, sym] end
Creates an object saved by _dump
# File lib/marshal/structure/parser.rb, line 235 def parse_user_defined name = get_symbol data = @tokens.next [object_ref, name, data] end
Creates an object saved by marshal_dump
# File lib/marshal/structure/parser.rb, line 246 def parse_user_marshal name = get_symbol [object_ref, name, parse] end
Creates a new symbol reference
# File lib/marshal/structure/parser.rb, line 255 def symbol_ref @symbols += 1 end