Support for the Ruby 2.4 series has ended. See here for reference.

In Files

  • psych/lib/psych/visitors/to_ruby.rb
  • psych/psych_to_ruby.c

Psych::Visitors::ToRuby

This class walks a YAML AST, converting each node to Ruby

Constants

SHOVEL

Attributes

class_loader[R]

Public Class Methods

create() click to toggle source
 
               # File psych/lib/psych/visitors/to_ruby.rb, line 15
def self.create
  class_loader = ClassLoader.new
  scanner      = ScalarScanner.new class_loader
  new(scanner, class_loader)
end
            
new(ss, class_loader) click to toggle source
 
               # File psych/lib/psych/visitors/to_ruby.rb, line 23
def initialize ss, class_loader
  super()
  @st = {}
  @ss = ss
  @domain_types = Psych.domain_types
  @class_loader = class_loader
end
            

Public Instance Methods

accept(target) click to toggle source
 
               # File psych/lib/psych/visitors/to_ruby.rb, line 31
def accept target
  result = super
  return result if @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]
    return block.call value, result
  end

  result
end
            
visit_Psych_Nodes_Alias(o) click to toggle source
 
               # File psych/lib/psych/visitors/to_ruby.rb, line 318
def visit_Psych_Nodes_Alias o
  @st.fetch(o.anchor) { raise BadAlias, "Unknown alias: #{o.anchor}" }
end
            
visit_Psych_Nodes_Document(o) click to toggle source
 
               # File psych/lib/psych/visitors/to_ruby.rb, line 310
def visit_Psych_Nodes_Document o
  accept o.root
end
            
visit_Psych_Nodes_Mapping(o) click to toggle source
 
               # File psych/lib/psych/visitors/to_ruby.rb, line 158
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
            
visit_Psych_Nodes_Scalar(o) click to toggle source
 
               # File psych/lib/psych/visitors/to_ruby.rb, line 122
def visit_Psych_Nodes_Scalar o
  register o, deserialize(o)
end
            
visit_Psych_Nodes_Sequence(o) click to toggle source
 
               # File psych/lib/psych/visitors/to_ruby.rb, line 126
def visit_Psych_Nodes_Sequence o
  if klass = resolve_class(Psych.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
            
visit_Psych_Nodes_Stream(o) click to toggle source
 
               # File psych/lib/psych/visitors/to_ruby.rb, line 314
def visit_Psych_Nodes_Stream o
  o.children.map { |c| accept c }
end