Class: Udat::Node
Overview
The abstract class to represent any UDAT data is a Udat::Node. Udat::Node’s basically consist of a tag and the content. The tag can be a String or be nil. The content is either a scalar value stored as a String, or an ordered/unordered collection of values (where each value can optionally have a key associated with it). Keys and values of collections are always Udat::Node’s too.
Udat::Node’s can most easily be constructed from other ruby objects by using the Object#to_udat method.
By calling the method Udat::Node#encode, the Node and its children are encoded in a both easily human readable and easily machine readable format. The output can be later parsed by String#parse_udat or IO#read_udat.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#tag ⇒ Object
Tag (i.e. type of the content).
Class Method Summary collapse
-
.parse(input) ⇒ Object
Parses a given UDAT document string and returns a structure of Udat::Node’s.
-
.parse_document(input) ⇒ Object
Alias for Udat::Node.parse, will be removed in future versions.
-
.read_from_stream(io) ⇒ Object
Reads an encoded Udat::Node from a stream.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Same as Udat::Node#eql?, but behaves differently in Udat::Collection.
-
#collection? ⇒ Boolean
Returns true, if the Udat::Node represents a collection.
-
#encode ⇒ Object
Returns the data (including it’s tag) encoded in the UDAT format and enclosed in square brackets.
-
#encode_document ⇒ Object
Alias for Udat::Node#encode, will be removed in future versions.
-
#eql?(other) ⇒ Boolean
Returns true, if class, tag and content (including it’s order in case of a Udat::Collection) are matching another object.
-
#hash ⇒ Object
Returns a hash key used by ruby’s Hash’es.
-
#initialize(tag) ⇒ Node
constructor
Creates a new Udat::Node with a given tag (which may be nil).
-
#inspect ⇒ Object
Does the same as Udat::Node#encode, but preceds the result with “udat”.
-
#require_collection(tag = AnyTag) ⇒ Object
Returns self, if the Udat::Node represents a collection, otherwise an Udat::UdatTypeMismatch exception is raised.
-
#require_scalar(tag = AnyTag) ⇒ Object
Returns self, if the Udat::Node represents a scalar, otherwise an Udat::UdatTypeMismatch exception is raised.
-
#require_tag(tag) ⇒ Object
Returns self, if the tag is matching the argument, otherwise an Udat::UdatTagMismatch exception is raised.
-
#rpc(domain, port = nil) ⇒ Object
Sends the object in encoded form through a TCP connection to a given host and port, or if no port is supplied to the host and port specified in a DNS SRV record “_udat-rpc._tcp.<domain>”.
-
#scalar? ⇒ Boolean
Returns true, if the Udat::Node represents a scalar value.
-
#to_s ⇒ Object
Here the method does the same as Udat::Node#encode, but this method is overwritten in Udat::Scalar!.
-
#to_udat(tag = AnyTag) ⇒ Object
Returns self, or a duplicate of self with a different tag set, if an argument is passed.
-
#write_to_stream(io) ⇒ Object
Encodes an object in the UDAT format by calling Object#to_udat followed by Udat::Node#encode, and writes it to a stream.
Constructor Details
#initialize(tag) ⇒ Node
Creates a new Udat::Node with a given tag (which may be nil). This method is private, Udat::Node#initialize is only called through supercalls.
82 83 84 85 |
# File 'lib/udat.rb', line 82 def initialize(tag) super() self.tag = tag end |
Instance Attribute Details
#tag ⇒ Object
Tag (i.e. type of the content).
88 89 90 |
# File 'lib/udat.rb', line 88 def tag @tag end |
Class Method Details
.parse(input) ⇒ Object
Parses a given UDAT document string and returns a structure of Udat::Node’s.
Note: When parsing UDAT data, no information is gained, whether collections are ordered or unordered. After parsing, all collections will be marked as unordered, unless changed later by the application.
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 |
# File 'lib/udat.rb', line 391 def self.parse(input) input = input.to_s pos = 0 begin collection = ( parse_intern(:normal, nil) do char = input[pos, 1] pos += 1 next char.empty? ? nil : char end ) unless collection.collection? and not collection.empty? raise ParseError, "No valid UDAT object found." end return collection.first rescue EOFError raise ParseError, $!. end end |
.parse_document(input) ⇒ Object
Alias for Udat::Node.parse, will be removed in future versions.
411 412 413 |
# File 'lib/udat.rb', line 411 def self.parse_document(input) parse(input) end |
.read_from_stream(io) ⇒ Object
Reads an encoded Udat::Node from a stream.
416 417 418 419 420 421 422 |
# File 'lib/udat.rb', line 416 def self.read_from_stream(io) return ( parse_intern(:one_value, nil) do io.read(1) end ) end |
Instance Method Details
#==(other) ⇒ Object
Same as Udat::Node#eql?, but behaves differently in Udat::Collection.
224 225 226 |
# File 'lib/udat.rb', line 224 def ==(other) self.eql? other end |
#collection? ⇒ Boolean
Returns true, if the Udat::Node represents a collection.
102 103 104 |
# File 'lib/udat.rb', line 102 def collection? false end |
#encode ⇒ Object
Returns the data (including it’s tag) encoded in the UDAT format and enclosed in square brackets.
Note: The UDAT format doesn’t contain information, whether contained collections are ordered or unordered. This information is lost during the encoding process, and has to be restored in an application specific way, if neccessary.
179 180 181 |
# File 'lib/udat.rb', line 179 def encode "[#{encode_without_brackets}]" end |
#encode_document ⇒ Object
Alias for Udat::Node#encode, will be removed in future versions.
183 184 185 |
# File 'lib/udat.rb', line 183 def encode_document encode end |
#eql?(other) ⇒ Boolean
Returns true, if class, tag and content (including it’s order in case of a Udat::Collection) are matching another object.
218 219 220 221 222 |
# File 'lib/udat.rb', line 218 def eql?(other) self.class == other.class and self.tag == other.tag and self.to_s == other.to_s end |
#hash ⇒ Object
Returns a hash key used by ruby’s Hash’es.
213 214 215 |
# File 'lib/udat.rb', line 213 def hash to_s.hash end |
#inspect ⇒ Object
Does the same as Udat::Node#encode, but preceds the result with “udat”.
193 194 195 |
# File 'lib/udat.rb', line 193 def inspect "udat#{self.encode}" end |
#require_collection(tag = AnyTag) ⇒ Object
Returns self, if the Udat::Node represents a collection, otherwise an Udat::UdatTypeMismatch exception is raised. If an optional tag is given as an argument, it is checked by calling Udat::Node#require_tag.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/udat.rb', line 139 def require_collection(tag = AnyTag) if collection? if tag == AnyTag return self else return require_tag(tag) end elsif scalar? raise UdatTypeMismatch, "UDAT scalar found where a collection was expected." else raise "Internal error in UDAT library." end end |
#require_scalar(tag = AnyTag) ⇒ Object
Returns self, if the Udat::Node represents a scalar, otherwise an Udat::UdatTypeMismatch exception is raised. If an optional tag is given as an argument, it is checked by calling Udat::Node#require_tag.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/udat.rb', line 121 def require_scalar(tag = AnyTag) if scalar? if tag == AnyTag return self else return require_tag(tag) end elsif collection? raise UdatTypeMismatch, "UDAT collection found where a scalar was expected." else raise "Internal error in UDAT library." end end |
#require_tag(tag) ⇒ Object
Returns self, if the tag is matching the argument, otherwise an Udat::UdatTagMismatch exception is raised.
108 109 110 111 112 113 114 115 116 |
# File 'lib/udat.rb', line 108 def require_tag(tag) synchronize do if self.tag == tag.to_s return self else raise UdatTagMismatch, "UDAT tag mismatch." end end end |
#rpc(domain, port = nil) ⇒ Object
Sends the object in encoded form through a TCP connection to a given host and port, or if no port is supplied to the host and port specified in a DNS SRV record “_udat-rpc._tcp.<domain>”. Returns the UDAT object received as a reply. As this method can block for an unlimited amount of time, it might be useful to enclose the call in a Timeout.timeout call.
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 |
# File 'lib/udat.rb', line 437 def rpc(domain, port = nil) domain = domain.to_str port = port.to_int if port socket_args = nil result = nil if port.nil? Resolv::DNS.open do |dns| srv_rr = dns.getresource( "_udat-rpc._tcp.#{domain}", Resolv::DNS::Resource::IN::SRV ) socket_args = [srv_rr.target.to_s, srv_rr.port.to_i] end else socket_args = [domain, port] end socket = nil begin socket = TCPSocket.new(*socket_args) socket.write_udat(self) socket.close_write result = socket.read_udat ensure socket.close if socket end unless result raise EOFError, "End of file before reading UDAT RPC result." end return result end |
#scalar? ⇒ Boolean
Returns true, if the Udat::Node represents a scalar value.
98 99 100 |
# File 'lib/udat.rb', line 98 def scalar? false end |
#to_s ⇒ Object
Here the method does the same as Udat::Node#encode, but this method is overwritten in Udat::Scalar!
188 189 190 |
# File 'lib/udat.rb', line 188 def to_s encode end |
#to_udat(tag = AnyTag) ⇒ Object
Returns self, or a duplicate of self with a different tag set, if an argument is passed.
199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/udat.rb', line 199 def to_udat(tag = AnyTag) if tag == AnyTag return self else obj = nil synchronize do obj = self.dup end obj.tag = tag return obj end end |
#write_to_stream(io) ⇒ Object
Encodes an object in the UDAT format by calling Object#to_udat followed by Udat::Node#encode, and writes it to a stream. Returns self.
426 427 428 429 |
# File 'lib/udat.rb', line 426 def write_to_stream(io) io << self.to_udat.encode return self end |