class Vici::Message
The Message
class provides the low level encoding and decoding of vici protocol messages. Directly using this class is usually not required.
Constants
- KEY_VALUE
- LIST_END
- LIST_ITEM
- LIST_START
- SECTION_END
- SECTION_START
Public Class Methods
new(data = "")
click to toggle source
# File lib/vici.rb, line 92 def initialize(data = "") if data.nil? @root = {} elsif data.is_a?(Hash) @root = data else @encoded = data end end
Public Instance Methods
encoding()
click to toggle source
Get the raw byte encoding of an on-the-wire message
# File lib/vici.rb, line 104 def encoding @encoded = encode(@root) if @encoded.nil? @encoded end
root()
click to toggle source
Get the root element of the parsed ruby data structures
# File lib/vici.rb, line 111 def root @root = parse(@encoded) if @root.nil? @root end
Private Instance Methods
encode(node)
click to toggle source
# File lib/vici.rb, line 144 def encode(node) encoding = "" node.each do |key, value| encoding = if value.is_a?(Hash) encode_section(encoding, key, value) elsif value.is_a?(Array) encode_list(encoding, key, value) else encode_kv(encoding, key, value) end end encoding end
encode_kv(encoding, key, value)
click to toggle source
# File lib/vici.rb, line 127 def encode_kv(encoding, key, value) encoding << KEY_VALUE << encode_name(key) << encode_value(value) end
encode_list(encoding, key, value)
click to toggle source
# File lib/vici.rb, line 136 def encode_list(encoding, key, value) encoding << LIST_START << encode_name(key) value.each do |item| encoding << LIST_ITEM << encode_value(item) end encoding << LIST_END end
encode_name(name)
click to toggle source
# File lib/vici.rb, line 118 def encode_name(name) [name.length].pack("c") << name end
encode_section(encoding, key, value)
click to toggle source
# File lib/vici.rb, line 131 def encode_section(encoding, key, value) encoding << SECTION_START << encode_name(key) encoding << encode(value) << SECTION_END end
encode_value(value)
click to toggle source
# File lib/vici.rb, line 122 def encode_value(value) value = value.to_s if value.class != String [value.length].pack("n") << value end
parse(encoding)
click to toggle source
# File lib/vici.rb, line 170 def parse(encoding) stack = [{}] list = nil until encoding.empty? type = encoding.unpack("c")[0] encoding = encoding[1..-1] case type when SECTION_START encoding, name = parse_name(encoding) stack.push(stack[-1][name] = {}) when SECTION_END raise ParseError, "unexpected section end" if stack.length == 1 stack.pop when KEY_VALUE encoding, name = parse_name(encoding) encoding, value = parse_value(encoding) stack[-1][name] = value when LIST_START encoding, name = parse_name(encoding) stack[-1][name] = [] list = name when LIST_ITEM raise ParseError, "unexpected list item" if list.nil? encoding, value = parse_value(encoding) stack[-1][list].push(value) when LIST_END raise ParseError, "unexpected list end" if list.nil? list = nil else raise ParseError, "invalid type: #{type}" end end raise ParseError, "unexpected message end" if stack.length > 1 stack[0] end
parse_name(encoding)
click to toggle source
# File lib/vici.rb, line 158 def parse_name(encoding) len = encoding.unpack("c")[0] name = encoding[1, len] [encoding[(1 + len)..-1], name] end
parse_value(encoding)
click to toggle source
# File lib/vici.rb, line 164 def parse_value(encoding) len = encoding.unpack("n")[0] value = encoding[2, len] [encoding[(2 + len)..-1], value] end