summaryrefslogtreecommitdiff
path: root/ext/psych/lib/psych/visitors/to_ruby.rb
diff options
context:
space:
mode:
Diffstat (limited to 'ext/psych/lib/psych/visitors/to_ruby.rb')
-rw-r--r--ext/psych/lib/psych/visitors/to_ruby.rb70
1 files changed, 53 insertions, 17 deletions
diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb
index ca046c5da9..2e082f90b4 100644
--- a/ext/psych/lib/psych/visitors/to_ruby.rb
+++ b/ext/psych/lib/psych/visitors/to_ruby.rb
@@ -31,9 +31,7 @@ module Psych
result
end
- def visit_Psych_Nodes_Scalar o
- @st[o.anchor] = o.value if o.anchor
-
+ def deserialize o
if klass = Psych.load_tags[o.tag]
instance = klass.allocate
@@ -52,8 +50,16 @@ module Psych
case o.tag
when '!binary', 'tag:yaml.org,2002:binary'
o.value.unpack('m').first
- when '!str', 'tag:yaml.org,2002:str'
- o.value
+ when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str'
+ klass = resolve_class($1)
+ if klass
+ klass.allocate.replace o.value
+ else
+ o.value
+ end
+ when '!ruby/object:BigDecimal'
+ require 'bigdecimal'
+ BigDecimal._load o.value
when "!ruby/object:DateTime"
require 'date'
@ss.parse_time(o.value).to_datetime
@@ -92,6 +98,11 @@ module Psych
@ss.tokenize o.value
end
end
+ private :deserialize
+
+ def visit_Psych_Nodes_Scalar o
+ register o, deserialize(o)
+ end
def visit_Psych_Nodes_Sequence o
if klass = Psych.load_tags[o.tag]
@@ -108,15 +119,18 @@ module Psych
case o.tag
when '!omap', 'tag:yaml.org,2002:omap'
- map = Psych::Omap.new
- @st[o.anchor] = map if o.anchor
+ map = register(o, Psych::Omap.new)
o.children.each { |a|
map[accept(a.children.first)] = accept a.children.last
}
map
+ when /^!(?:seq|ruby\/array):(.*)$/
+ klass = resolve_class($1)
+ list = register(o, klass.allocate)
+ o.children.each { |c| list.push accept c }
+ list
else
- list = []
- @st[o.anchor] = list if o.anchor
+ list = register(o, [])
o.children.each { |c| list.push accept c }
list
end
@@ -127,16 +141,33 @@ module Psych
return revive_hash({}, o) unless o.tag
case o.tag
- when '!str', 'tag:yaml.org,2002:str'
+ when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str'
+ klass = resolve_class($1)
members = Hash[*o.children.map { |c| accept c }]
string = members.delete 'str'
+
+ if klass
+ string = klass.allocate
+ string.replace string
+ 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\/struct:?(.*)?$/
klass = resolve_class($1)
if klass
- s = klass.allocate
- @st[o.anchor] = s if o.anchor
+ s = register(o, klass.allocate)
members = {}
struct_members = s.members.map { |x| x.to_sym }
@@ -158,7 +189,7 @@ module Psych
when '!ruby/range'
h = Hash[*o.children.map { |c| accept c }]
- Range.new(h['begin'], h['end'], h['excl'])
+ register o, Range.new(h['begin'], h['end'], h['excl'])
when /^!ruby\/exception:?(.*)?$/
h = Hash[*o.children.map { |c| accept c }]
@@ -177,11 +208,11 @@ module Psych
when '!ruby/object:Complex'
h = Hash[*o.children.map { |c| accept c }]
- Complex(h['real'], h['image'])
+ register o, Complex(h['real'], h['image'])
when '!ruby/object:Rational'
h = Hash[*o.children.map { |c| accept c }]
- Rational(h['numerator'], h['denominator'])
+ register o, Rational(h['numerator'], h['denominator'])
when /^!ruby\/object:?(.*)?$/
name = $1 || 'Object'
@@ -205,10 +236,15 @@ module Psych
end
def visit_Psych_Nodes_Alias o
- @st[o.anchor]
+ @st.fetch(o.anchor) { raise BadAlias, "Unknown alias: #{o.anchor}" }
end
private
+ def register node, object
+ @st[node.anchor] = object if node.anchor
+ object
+ end
+
def revive_hash hash, o
@st[o.anchor] = hash if o.anchor
@@ -249,7 +285,7 @@ module Psych
o.init_with c
elsif o.respond_to?(:yaml_initialize)
if $VERBOSE
- "Implementing #{o.class}#yaml_initialize is deprecated, please implement \"init_with(coder)\""
+ warn "Implementing #{o.class}#yaml_initialize is deprecated, please implement \"init_with(coder)\""
end
o.yaml_initialize c.tag, c.map
else