Class: Psych::Visitors::YAMLTree

Inherits:
Visitor show all
Defined in:
lib/psych/visitors/yaml_tree.rb,
ext/psych/yaml_tree.c

Overview

YAMLTree builds a YAML ast given a ruby object. For example:

builder = Psych::Visitors::YAMLTree.new
builder << { :foo => 'bar' }
builder.tree # => #<Psych::Nodes::Stream .. }

Direct Known Subclasses

Stream, JSONTree

Instance Attribute Summary

Attributes inherited from Visitor

#finished, #started

Instance Method Summary collapse

Constructor Details

#initialize(options = {}, emitter = Psych::TreeBuilder.new) ⇒ YAMLTree

Returns a new instance of YAMLTree.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/psych/visitors/yaml_tree.rb', line 11

def initialize options = {}, emitter = Psych::TreeBuilder.new
  super()
  @emitter  = emitter
  @st       = {}
  @ss       = ScalarScanner.new

  @dispatch_cache = Hash.new do |h,klass|
    method = "visit_#{(klass.name || '').split('::').join('_')}"

    method = respond_to?(method) ? method : h[klass.superclass]

    raise(TypeError, "Can't dump #{target.class}") unless method

    h[klass] = method
  end
end

Instance Method Details

#accept(target) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/psych/visitors/yaml_tree.rb', line 52

def accept target
  # return any aliases we find
  if node = @st[target.object_id]
    node.anchor = target.object_id.to_s
    return @emitter.alias target.object_id.to_s
  end

  if target.respond_to?(:to_yaml)
    loc = target.method(:to_yaml).source_location.first
    if loc !~ /(syck\/rubytypes.rb|psych\/core_ext.rb)/
      unless target.respond_to?(:encode_with)
        if $VERBOSE
          warn "implementing to_yaml is deprecated, please implement \"encode_with\""
        end

        target.to_yaml(:nodump => true)
      end
    end
  end

  if target.respond_to?(:encode_with)
    dump_coder target
  else
    send(@dispatch_cache[target.class], target)
  end
end

#finishObject



34
35
36
37
38
# File 'lib/psych/visitors/yaml_tree.rb', line 34

def finish
  @emitter.end_stream.tap do
    @finished = true
  end
end

#push(object) ⇒ Object Also known as: <<



44
45
46
47
48
49
# File 'lib/psych/visitors/yaml_tree.rb', line 44

def push object
  start unless started?
  @emitter.start_document [], [], false
  accept object
  @emitter.end_document
end

#start(encoding = Nodes::Stream::UTF8) ⇒ Object



28
29
30
31
32
# File 'lib/psych/visitors/yaml_tree.rb', line 28

def start encoding = Nodes::Stream::UTF8
  @emitter.start_stream(encoding).tap do
    @started = true
  end
end

#treeObject



40
41
42
# File 'lib/psych/visitors/yaml_tree.rb', line 40

def tree
  finish unless finished?
end

#visit_Array(o) ⇒ Object



256
257
258
259
260
# File 'lib/psych/visitors/yaml_tree.rb', line 256

def visit_Array o
  register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
  o.each { |c| accept c }
  @emitter.end_sequence
end

#visit_Class(o) ⇒ Object

Raises:

  • (TypeError)


222
223
224
# File 'lib/psych/visitors/yaml_tree.rb', line 222

def visit_Class o
  raise TypeError, "can't dump anonymous class #{o.class}"
end

#visit_Complex(o) ⇒ Object



162
163
164
165
166
167
168
169
170
# File 'lib/psych/visitors/yaml_tree.rb', line 162

def visit_Complex 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
  end

  @emitter.end_mapping
end

#visit_DateTime(o) ⇒ Object



138
139
140
141
142
# File 'lib/psych/visitors/yaml_tree.rb', line 138

def visit_DateTime o
  formatted = format_time o.to_time
  tag = '!ruby/object:DateTime'
  @emitter.scalar formatted, nil, tag, false, false, Nodes::Scalar::ANY
end

#visit_Exception(o) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/psych/visitors/yaml_tree.rb', line 115

def visit_Exception o
  tag = ['!ruby/exception', o.class.name].join ':'

  @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK

  {
    'message'   => private_iv_get(o, 'mesg'),
    'backtrace' => private_iv_get(o, 'backtrace'),
  }.each do |k,v|
    next unless v
    @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
    accept v
  end

  dump_ivars o

  @emitter.end_mapping
end

#visit_Float(o) ⇒ Object



179
180
181
182
183
184
185
186
187
188
# File 'lib/psych/visitors/yaml_tree.rb', line 179

def visit_Float o
  if o.nan?
    @emitter.scalar '.nan', nil, nil, true, false, Nodes::Scalar::ANY
  elsif o.infinite?
    @emitter.scalar((o.infinite? > 0 ? '.inf' : '-.inf'),
      nil, nil, true, false, Nodes::Scalar::ANY)
  else
    @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
  end
end

#visit_Hash(o) ⇒ Object



234
235
236
237
238
239
240
241
242
243
# File 'lib/psych/visitors/yaml_tree.rb', line 234

def visit_Hash o
  register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK))

  o.each do |k,v|
    accept k
    accept v
  end

  @emitter.end_mapping
end

#visit_Integer(o) ⇒ Object Also known as: visit_TrueClass, visit_FalseClass, visit_Date



172
173
174
# File 'lib/psych/visitors/yaml_tree.rb', line 172

def visit_Integer o
  @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
end

#visit_NilClass(o) ⇒ Object



262
263
264
# File 'lib/psych/visitors/yaml_tree.rb', line 262

def visit_NilClass o
  @emitter.scalar('', nil, 'tag:yaml.org,2002:null', false, false, Nodes::Scalar::ANY)
end

#visit_Object(o) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/psych/visitors/yaml_tree.rb', line 87

def visit_Object o
  tag = Psych.dump_tags[o.class]
  unless tag
    klass = o.class == Object ? nil : o.class.name
    tag   = ['!ruby/object', klass].compact.join(':')
  end

  map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
  register(o, map)

  dump_ivars o
  @emitter.end_mapping
end

#visit_Psych_Omap(o) ⇒ Object



79
80
81
82
83
84
85
# File 'lib/psych/visitors/yaml_tree.rb', line 79

def visit_Psych_Omap o
  seq = @emitter.start_sequence(nil, '!omap', false, Nodes::Sequence::BLOCK)
  register(o, seq)

  o.each { |k,v| visit_Hash k => v }
  @emitter.end_sequence
end

#visit_Psych_Set(o) ⇒ Object



245
246
247
248
249
250
251
252
253
254
# File 'lib/psych/visitors/yaml_tree.rb', line 245

def visit_Psych_Set o
  register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK))

  o.each do |k,v|
    accept k
    accept v
  end

  @emitter.end_mapping
end

#visit_Range(o) ⇒ Object



226
227
228
229
230
231
232
# File 'lib/psych/visitors/yaml_tree.rb', line 226

def visit_Range 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
  @emitter.end_mapping
end

#visit_Rational(o) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/psych/visitors/yaml_tree.rb', line 149

def visit_Rational o
  @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)

  [
    'denominator', o.denominator.to_s,
    'numerator', o.numerator.to_s
  ].each do |m|
    @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
  end

  @emitter.end_mapping
end

#visit_Regexp(o) ⇒ Object



134
135
136
# File 'lib/psych/visitors/yaml_tree.rb', line 134

def visit_Regexp o
  @emitter.scalar o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY
end

#visit_String(o) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/psych/visitors/yaml_tree.rb', line 190

def visit_String o
  plain = false
  quote = false
  style = Nodes::Scalar::ANY

  if o.index("\x00") || o.count("^ -~\t\r\n").fdiv(o.length) > 0.3
    str   = [o].pack('m').chomp
    tag   = '!binary' # FIXME: change to below when syck is removed
    #tag   = 'tag:yaml.org,2002:binary'
    style = Nodes::Scalar::LITERAL
  else
    str   = o
    tag   = nil
    quote = !(String === @ss.tokenize(o))
    plain = !quote
  end

  ivars = find_ivars o

  if ivars.empty?
    @emitter.scalar str, nil, tag, plain, quote, style
  else
    @emitter.start_mapping nil, '!str', false, Nodes::Mapping::BLOCK
    @emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY
    @emitter.scalar str, nil, tag, plain, quote, style

    dump_ivars o

    @emitter.end_mapping
  end
end

#visit_Struct(o) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/psych/visitors/yaml_tree.rb', line 101

def visit_Struct o
  tag = ['!ruby/struct', o.class.name].compact.join(':')

  register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
  o.members.each do |member|
    @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
    accept o[member]
  end

  dump_ivars o

  @emitter.end_mapping
end

#visit_Symbol(o) ⇒ Object



266
267
268
# File 'lib/psych/visitors/yaml_tree.rb', line 266

def visit_Symbol o
  @emitter.scalar ":#{o}", nil, nil, true, false, Nodes::Scalar::ANY
end

#visit_Time(o) ⇒ Object



144
145
146
147
# File 'lib/psych/visitors/yaml_tree.rb', line 144

def visit_Time o
  formatted = format_time o
  @emitter.scalar formatted, nil, nil, true, false, Nodes::Scalar::ANY
end