summaryrefslogtreecommitdiff
path: root/ext/psych/lib/psych/visitors/yaml_tree.rb
diff options
context:
space:
mode:
Diffstat (limited to 'ext/psych/lib/psych/visitors/yaml_tree.rb')
-rw-r--r--ext/psych/lib/psych/visitors/yaml_tree.rb69
1 files changed, 58 insertions, 11 deletions
diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb
index 5a092850c3..80af0466eb 100644
--- a/ext/psych/lib/psych/visitors/yaml_tree.rb
+++ b/ext/psych/lib/psych/visitors/yaml_tree.rb
@@ -159,13 +159,13 @@ module Psych
end
def visit_Regexp o
- @emitter.scalar o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY
+ register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
end
def visit_DateTime o
formatted = format_time o.to_time
tag = '!ruby/object:DateTime'
- @emitter.scalar formatted, nil, tag, false, false, Nodes::Scalar::ANY
+ register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
end
def visit_Time o
@@ -174,7 +174,7 @@ module Psych
end
def visit_Rational o
- @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
+ register o, @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
[
'denominator', o.denominator.to_s,
@@ -187,7 +187,7 @@ module Psych
end
def visit_Complex o
- @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
+ register o, @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
['real', o.real.to_s, 'image', o.imag.to_s].each do |m|
@emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
@@ -214,6 +214,10 @@ module Psych
end
end
+ def visit_BigDecimal o
+ @emitter.scalar o._dump, nil, '!ruby/object:BigDecimal', false, false, Nodes::Scalar::ANY
+ end
+
def binary? string
string.encoding == Encoding::ASCII_8BIT ||
string.index("\x00") ||
@@ -241,9 +245,15 @@ module Psych
ivars = find_ivars o
if ivars.empty?
+ unless o.class == ::String
+ tag = "!ruby/string:#{o.class}"
+ end
@emitter.scalar str, nil, tag, plain, quote, style
else
- @emitter.start_mapping nil, '!str', false, Nodes::Mapping::BLOCK
+ maptag = '!ruby/string'
+ maptag << ":#{o.class}" unless o.class == ::String
+
+ @emitter.start_mapping nil, maptag, false, Nodes::Mapping::BLOCK
@emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY
@emitter.scalar str, nil, tag, plain, quote, style
@@ -255,16 +265,16 @@ module Psych
def visit_Module o
raise TypeError, "can't dump anonymous module: #{o}" unless o.name
- @emitter.scalar o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED
+ register o, @emitter.scalar(o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED)
end
def visit_Class o
raise TypeError, "can't dump anonymous class: #{o}" unless o.name
- @emitter.scalar o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED
+ register o, @emitter.scalar(o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED)
end
def visit_Range o
- @emitter.start_mapping nil, '!ruby/range', false, Nodes::Mapping::BLOCK
+ register o, @emitter.start_mapping(nil, '!ruby/range', false, Nodes::Mapping::BLOCK)
['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m|
accept m
end
@@ -297,9 +307,13 @@ module Psych
end
def visit_Array o
- register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
- o.each { |c| accept c }
- @emitter.end_sequence
+ if o.class == ::Array
+ register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
+ o.each { |c| accept c }
+ @emitter.end_sequence
+ else
+ visit_array_subclass o
+ end
end
def visit_NilClass o
@@ -311,6 +325,39 @@ module Psych
end
private
+ def visit_array_subclass o
+ tag = "!ruby/array:#{o.class}"
+ if o.instance_variables.empty?
+ node = @emitter.start_sequence(nil, tag, false, Nodes::Sequence::BLOCK)
+ register o, node
+ o.each { |c| accept c }
+ @emitter.end_sequence
+ else
+ node = @emitter.start_mapping(nil, tag, false, Nodes::Sequence::BLOCK)
+ register o, node
+
+ # Dump the internal list
+ accept 'internal'
+ @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
+ o.each { |c| accept c }
+ @emitter.end_sequence
+
+ # Dump the ivars
+ accept 'ivars'
+ @emitter.start_mapping(nil, nil, true, Nodes::Sequence::BLOCK)
+ o.instance_variables.each do |ivar|
+ accept ivar
+ accept o.instance_variable_get ivar
+ end
+ @emitter.end_mapping
+
+ @emitter.end_mapping
+ end
+ end
+
+ def dump_list o
+ end
+
# '%:z' was no defined until 1.9.3
if RUBY_VERSION < '1.9.3'
def format_time time