This class walks a YAML AST, converting each node to Ruby
# File psych/lib/psych/visitors/to_ruby.rb, line 15 def self.create(symbolize_names: false, freeze: false) class_loader = ClassLoader.new scanner = ScalarScanner.new class_loader new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze) end
# File psych/lib/psych/visitors/to_ruby.rb, line 23 def initialize ss, class_loader, symbolize_names: false, freeze: false super() @st = {} @ss = ss @load_tags = Psych.load_tags @domain_types = Psych.domain_types @class_loader = class_loader @symbolize_names = symbolize_names @freeze = freeze end
# File psych/lib/psych/visitors/to_ruby.rb, line 34 def accept target result = super unless @domain_types.empty? || !target.tag key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:') key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/ if @domain_types.key? key value, block = @domain_types[key] result = block.call value, result end end result = deduplicate(result).freeze if @freeze result end
# File psych/lib/psych/visitors/to_ruby.rb, line 325 def visit_Psych_Nodes_Alias o @st.fetch(o.anchor) { raise BadAlias, "Unknown alias: #{o.anchor}" } end
# File psych/lib/psych/visitors/to_ruby.rb, line 317 def visit_Psych_Nodes_Document o accept o.root end
# File psych/lib/psych/visitors/to_ruby.rb, line 163 def visit_Psych_Nodes_Mapping o if @load_tags[o.tag] return revive(resolve_class(@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')) e.set_backtrace h.delete('backtrace') if h.key? 'backtrace' 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
# File psych/lib/psych/visitors/to_ruby.rb, line 127 def visit_Psych_Nodes_Scalar o register o, deserialize(o) end
# File psych/lib/psych/visitors/to_ruby.rb, line 131 def visit_Psych_Nodes_Sequence o if klass = resolve_class(@load_tags[o.tag]) instance = klass.allocate if instance.respond_to?(:init_with) coder = Psych::Coder.new(o.tag) coder.seq = o.children.map { |c| accept c } instance.init_with coder end return instance end case o.tag when nil register_empty(o) when '!omap', 'tag:yaml.org,2002:omap' 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 register_empty(o) end end