Imported File#ftype spec from rubyspecs.
[rbx.git] / lib / rbyaml / serializer.rb
blobca694f1635480e152048a8eeb9bfed468e8692c1
1 require 'rbyaml/error'
2 require 'rbyaml/events'
3 require 'rbyaml/nodes'
5 module RbYAML
6   class SerializerError < YAMLError
7   end
9   class Serializer
10     def initialize(emitter, resolver, opts={})
11       @emitter = emitter
12       @resolver = resolver
13       @options = opts
14       @use_explicit_start = opts[:ExplicitStart]
15       @use_explicit_end = opts[:ExplicitEnd]
16       @use_version = opts[:UseVersion] && opts[:Version]
17       @use_tags = opts[:UseHeader]
18       @anchor_template = opts[:AnchorFormat] || "id%03d"
19       @serialized_nodes = {}
20       @anchors = {}
21       @last_anchor_id = 0
22       @closed = nil
23     end
25     def open
26       if @closed.nil?
27         @emitter.emit(StreamStartEvent.new)
28         @closed = false
29       elsif @closed
30         raise SerializerError.new("serializer is closed")
31       else
32         raise SerializerError.new("serializer is already opened")
33       end
34     end
36     def close
37       if @closed.nil?
38         raise SerializerError.new("serializer is not opened")
39       elsif !@closed
40         @emitter.emit(StreamEndEvent.new)
41         @closed = true
42       end
43     end
45     def serialize(node)
46       if @closed.nil?
47         raise SerializerError.new("serializer is not opened")
48       elsif @closed
49         raise SerializerError.new("serializer is closed")
50       end
51       @emitter.emit(DocumentStartEvent.new(@use_explicit_start,@use_version,@use_tags))
52       anchor_node(node)
53       serialize_node(node,nil,nil)
54       @emitter.emit(DocumentEndEvent.new(@use_explicit_end))
55       @serialized_nodes = {}
56       @anchors = {}
57       @last_alias_id = 0
58     end
60     def anchor_node(node)
61       if @anchors.include?(node)
62         @anchors[node] ||= generate_anchor(node)
63       else
64         @anchors[node] = nil
65         if SequenceNode === node
66           for item in node.value
67             anchor_node(item)
68           end
69         elsif MappingNode === node
70           for key,val in node.value
71             anchor_node(key)
72             anchor_node(val)
73           end
74         end
75       end
76     end
78     def generate_anchor(node)
79       @last_anchor_id += 1
80       @anchor_template % @last_anchor_id
81     end
82     
83     def serialize_node(node,parent,index)
84       talias = @anchors[node]
85       if @serialized_nodes.include?(node)
86         @emitter.emit(AliasEvent.new(talias))
87       else
88         @serialized_nodes[node] = true
89         @resolver.descend_resolver(parent, index)
90         if ScalarNode === node
91           detected_tag = @resolver.resolve(ScalarNode, node.value, [true,false])
92           default_tag = @resolver.resolve(ScalarNode, node.value, [false,true])
93           implicit = (node.tag == detected_tag), (node.tag == default_tag)
94           @emitter.emit(ScalarEvent.new(talias, node.tag, implicit, node.value,node.style))
95         elsif SequenceNode === node
96           implicit = (node.tag == @resolver.resolve(SequenceNode, node.value, true))
97           @emitter.emit(SequenceStartEvent.new(talias, node.tag, implicit,node.flow_style))
98           index = 0
99           for item in node.value
100             serialize_node(item,node,index)
101             index += 1
102           end
103           @emitter.emit(SequenceEndEvent.new)
104         elsif MappingNode === node
105           implicit = (node.tag == @resolver.resolve(MappingNode, node.value, true))
106           @emitter.emit(MappingStartEvent.new(talias, node.tag, implicit,node.flow_style))
107           for key, value in node.value
108             serialize_node(key,node,nil)
109             serialize_node(value,node,key)
110           end
111           @emitter.emit(MappingEndEvent.new)
112         end
113       end
114     end
115   end