Abstracting Services In Ruby C0 Coverage Information - RCov

lib/asir/coder/xml.rb

Name Total Lines Lines of Code Total Coverage Code Coverage
lib/asir/coder/xml.rb 212 191
96.70%
96.34%

Key

Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.

Coverage Details

1 require 'asir'
2 require 'asir/object_resolving'
3 gem 'libxml-ruby'
4 require 'xml'
5 
6 module ASIR
7   class Coder
8     # !SLIDE
9     # XML
10     #
11     # Encode/Decode objects as XML.
12     class XML < self
13       class Error < ::ASIR::Error
14         class BadIdref < self; end
15       end
16       def _encode obj
17         @stream = ''
18         @dom_id_map = { }
19         @dom_id = 0
20         @cls_tag_map = { }
21         encode_dom obj
22         @stream
23       end
24 
25       def _decode obj
26         @stream = obj
27         @decoder ||= DECODER; @decoder_object = nil
28         @dom_id_map = { }
29         @dom_id = 0
30         @cls_tag_map = { }
31         @parser = ::XML::Parser.string(@stream)
32         @dom = @parser.parse
33         decode_dom @dom.root
34       end
35 
36       def encode_dom obj
37         if dom_id = @dom_id_map[obj.object_id]
38           tag_obj(obj, nil, :idref => dom_id.first)
39         else
40           _encode_dom obj
41         end
42       end
43 
44       def _encode_dom obj
45         case obj
46         when NilClass, TrueClass, FalseClass
47           tag_obj(obj)
48         when Numeric
49           tag_obj(obj, nil, :v => obj.to_s)
50         when Symbol
51           tag_obj(obj) do
52             @stream << obj.to_s
53           end
54         when String
55           tag_obj(obj, :id) do 
56             @stream << obj.to_s
57           end
58         when Array
59           tag_obj(obj, :id) do 
60             obj.each do | elem |
61               encode_dom elem
62             end
63           end
64         when Hash
65           tag_obj(obj, :id) do 
66             obj.each do | key, val |
67               encode_dom key
68               encode_dom val
69             end
70           end
71         else
72           tag_obj(obj, :id) do 
73             obj.instance_variables.each do | attr |
74               val = obj.instance_variable_get(attr)
75               key = attr.to_s.sub(/^@/, '')
76               tag(key) do 
77                 encode_dom val
78               end
79             end
80           end
81         end
82       end
83 
84       def tag_obj obj, with_id = false, attrs = nil
85         if block_given?
86           tag(cls_tag(obj), with_id ? { with_id => map_obj_to_dom_id!(obj) } : nil) do
87             yield
88           end
89         else
90           tag(cls_tag(obj), attrs)
91         end
92       end
93 
94       CC = '::'.freeze; D = '.'.freeze
95       def cls_tag obj
96         obj = obj.class
97         @cls_tag_map[obj] ||= obj.name.gsub(CC, D).freeze
98       end
99 
100       def map_obj_to_dom_id! obj
101         if dom_id = @dom_id_map[obj.object_id]
102           dom_id.first
103         else
104           @dom_id_map[obj.object_id] = [ @dom_id += 1, obj ]
105           @dom_id
106         end
107       end
108 
109       B  = '<'.freeze;  S = ' '.freeze; E = '>'.freeze; SE = '/>'.freeze
110       BS = '</'.freeze; A = '='.freeze
111       def tag tag, attrs = nil
112         tag = tag.to_s
113         @stream << B << tag << S
114         if attrs
115           attrs.each do | key, val |
116             @stream << key.to_s << A << val.to_s.inspect << S
117           end
118         end
119         if block_given?
120           @stream << E; yield; @stream << BS << tag << E
121         else
122           @stream << SE
123         end
124       end
125 
126       ################################################################
127 
128       def decode_dom dom
129         if dom_id = dom.attributes[:idref]
130           unless obj = @dom_id_map[dom_id]
131             raise Error::BadIdref, "in element #{dom}"
132           end
133           obj
134         else
135           obj = _decode_dom(dom)
136           map_dom_id_to_obj! dom, obj if dom.attributes[:id]
137           obj
138         end
139       end
140 
141       def _decode_dom dom
142         cls_name = dom.name
143         decoder = @decoder[cls_name] || 
144           (@decoder_object ||= @decoder['Object'])
145         raise Error, "BUG: " unless decoder
146         decoder.call(self, dom)
147       end
148 
149       DECODER = {
150         'NilClass'   => lambda { | _, dom | nil },
151         'TrueClass'  => lambda { | _, dom | true },
152         'FalseClass' => lambda { | _, dom | false },
153         'String'     => lambda { | _, dom | (dom.attributes[:v] || dom.content) },
154         'Symbol'     => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_sym },
155         'Integer'    => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_i },
156         'Float'      => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_f },
157         "Array" => lambda { | _, dom | 
158           obj = [ ]
159           _.map_dom_id_to_obj! dom, obj
160           dom.each_element do | elem |
161             obj << _.decode_dom(elem)
162           end
163           obj
164         },
165         'Hash' => lambda { | _, dom |
166           obj = { }
167           _.map_dom_id_to_obj! dom, obj
168           key = nil
169           dom.each_element do | val |
170             if key
171               obj[_.decode_dom(key)] = _.decode_dom(val)
172               key = nil
173             else
174               key = val
175             end
176           end
177           obj
178         },
179         'Object' => lambda { | _, dom |
180           cls_name = dom.name
181           # $stderr.puts "cls_name = #{cls_name.inspect}"
182           cls = _.tag_cls(cls_name)
183           obj = cls.allocate
184           _.map_dom_id_to_obj! dom, obj
185           dom.each_element do | child |
186             key = child.name
187             val = _.decode_dom child.first
188             obj.instance_variable_set("@#{key}", val)
189           end
190           obj
191         },
192       }
193       DECODER['Fixnum'] = DECODER['Bignum'] = DECODER['Integer']
194 
195       def map_dom_id_to_obj! dom, obj
196         dom_id = dom.attributes[:id]
197         debugger unless dom_id
198         raise Error, "no :id attribute in #{dom}" unless dom_id
199         if (other_obj = @dom_id_map[dom_id]) and other_obj.object_id != obj.object_id
200           raise Error, "BUG: :id #{dom_id} already used for #{other_obj.class.name} #{other_obj.inspect}"
201         end
202         @dom_id_map[dom_id] = obj
203       end
204 
205       include ObjectResolving
206       def tag_cls cls_name
207         @cls_tag_map[cls_name.freeze] ||= resolve_object(cls_name.gsub('.', '::'))
208       end
209 
210     end
211   end
212 end

Generated on Fri Jan 27 17:37:46 -0600 2012 with rcov 0.9.8