From 8c08c8298a03a01629a478b74abfd57d7f35cb05 Mon Sep 17 00:00:00 2001 From: tenderlove Date: Thu, 8 Jan 2015 22:00:54 +0000 Subject: * ext/psych/lib/psych/visitors/to_ruby.rb: revive hashes with ivars * ext/psych/lib/psych/visitors/yaml_tree.rb: dump hashes with ivars. Fixes github.com/psych/issues/43 * test/psych/test_hash.rb: test for change git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49188 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/psych/lib/psych/visitors/to_ruby.rb | 14 ++++++++++ ext/psych/lib/psych/visitors/yaml_tree.rb | 45 +++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 8 deletions(-) (limited to 'ext/psych/lib/psych') diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb index e696ebd4ff..adf38a21e8 100644 --- a/ext/psych/lib/psych/visitors/to_ruby.rb +++ b/ext/psych/lib/psych/visitors/to_ruby.rb @@ -261,6 +261,20 @@ module Psych end set + when /^!ruby\/hash-with-ivars(?::(.*))?$/ + hash = $1 ? resolve_class($1).new : {} + 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).new), o diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb index 989e1f0de5..bedf9d35b2 100644 --- a/ext/psych/lib/psych/visitors/yaml_tree.rb +++ b/ext/psych/lib/psych/visitors/yaml_tree.rb @@ -367,17 +367,46 @@ module Psych end def visit_Hash o - tag = o.class == ::Hash ? nil : "!ruby/hash:#{o.class}" - implicit = !tag + ivars = o.instance_variables - register(o, @emitter.start_mapping(nil, tag, implicit, Psych::Nodes::Mapping::BLOCK)) + if ivars.any? + tag = "!ruby/hash-with-ivars" + tag << ":#{o.class}" unless o.class == ::Hash - o.each do |k,v| - accept k - accept v - end + register(o, @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)) - @emitter.end_mapping + @emitter.scalar 'elements', nil, nil, true, false, Nodes::Scalar::ANY + + @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK + o.each do |k,v| + accept k + accept v + end + @emitter.end_mapping + + @emitter.scalar 'ivars', nil, nil, true, false, Nodes::Scalar::ANY + + @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK + o.instance_variables.each do |ivar| + accept ivar + accept o.instance_variable_get ivar + end + @emitter.end_mapping + + @emitter.end_mapping + else + tag = o.class == ::Hash ? nil : "!ruby/hash:#{o.class}" + implicit = !tag + + register(o, @emitter.start_mapping(nil, tag, implicit, Psych::Nodes::Mapping::BLOCK)) + + o.each do |k,v| + accept k + accept v + end + + @emitter.end_mapping + end end def visit_Psych_Set o -- cgit v1.2.3