def visit_Psych_Nodes_Mapping o
def visit_Psych_Nodes_Mapping o
if Psych.load_tags[o.tag]
return revive(resolve_class(Psych.load_tags[o.tag]), o)
end
return revive_hash(register(o, {}), o) unless o.tag
case o.tag
when /^!ruby\/struct:?(.*)?$/
klass = resolve_class($1) if $1
if klass
s = register(o, klass.allocate)
members = {}
struct_members = s.members.map { |x| class_loader.symbolize x }
o.children.each_slice(2) do |k,v|
member = accept(k)
value = accept(v)
if struct_members.include?(class_loader.symbolize(member))
s.send("#{member}=", value)
else
members[member.to_s.sub(/^@/, '')] = value
end
end
init_with(s, members, o)
else
klass = class_loader.struct
members = o.children.map { |c| accept c }
h = Hash[*members]
s = klass.new(*h.map { |k,v|
class_loader.symbolize k
}).new(*h.map { |k,v| v })
register(o, s)
s
end
when /^!ruby\/object:?(.*)?$/
name = $1 || 'Object'
if name == 'Complex'
class_loader.complex
h = Hash[*o.children.map { |c| accept c }]
register o, Complex(h['real'], h['image'])
elsif name == 'Rational'
class_loader.rational
h = Hash[*o.children.map { |c| accept c }]
register o, Rational(h['numerator'], h['denominator'])
elsif name == 'Hash'
revive_hash(register(o, {}), o)
else
obj = revive((resolve_class(name) || class_loader.object), o)
obj
end
when /^!(?:str|ruby\/string)(?::(.*))?$/, 'tag:yaml.org,2002:str'
klass = resolve_class($1)
members = {}
string = nil
o.children.each_slice(2) do |k,v|
key = accept k
value = accept v
if key == 'str'
if klass
string = klass.allocate.replace value
else
string = value
end
register(o, string)
else
members[key] = value
end
end
init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o)
when /^!ruby\/array:(.*)$/
klass = resolve_class($1)
list = register(o, klass.allocate)
members = Hash[o.children.map { |c| accept c }.each_slice(2).to_a]
list.replace members['internal']
members['ivars'].each do |ivar, v|
list.instance_variable_set ivar, v
end
list
when '!ruby/range'
klass = class_loader.range
h = Hash[*o.children.map { |c| accept c }]
register o, klass.new(h['begin'], h['end'], h['excl'])
when /^!ruby\/exception:?(.*)?$/
h = Hash[*o.children.map { |c| accept c }]
e = build_exception((resolve_class($1) || class_loader.exception),
h.delete('message'))
init_with(e, h, o)
when '!set', 'tag:yaml.org,2002:set'
set = class_loader.psych_set.new
@st[o.anchor] = set if o.anchor
o.children.each_slice(2) do |k,v|
set[accept(k)] = accept(v)
end
set
when /^!ruby\/hash-with-ivars(?::(.*))?$/
hash = $1 ? resolve_class($1).allocate : {}
register o, hash
o.children.each_slice(2) do |key, value|
case key.value
when 'elements'
revive_hash hash, value
when 'ivars'
value.children.each_slice(2) do |k,v|
hash.instance_variable_set accept(k), accept(v)
end
end
end
hash
when /^!map:(.*)$/, /^!ruby\/hash:(.*)$/
revive_hash register(o, resolve_class($1).allocate), o
when '!omap', 'tag:yaml.org,2002:omap'
map = register(o, class_loader.psych_omap.new)
o.children.each_slice(2) do |l,r|
map[accept(l)] = accept r
end
map
when /^!ruby\/marshalable:(.*)$/
name = $1
klass = resolve_class(name)
obj = register(o, klass.allocate)
if obj.respond_to?(:init_with)
init_with(obj, revive_hash({}, o), o)
elsif obj.respond_to?(:marshal_load)
marshal_data = o.children.map(&method(:accept))
obj.marshal_load(marshal_data)
obj
else
raise ArgumentError, "Cannot deserialize #{name}"
end
else
revive_hash(register(o, {}), o)
end
end