class Poseidon::Protocol::ProtocolStruct
Public Class Methods
new(hash)
click to toggle source
Calls superclass method
# File lib/poseidon/protocol/protocol_struct.rb, line 7 def self.new(hash) klass = super(*hash.keys) klass.type_map = hash klass end
prepend_crc32()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 26 def self.prepend_crc32 @prepend_crc32 = true self end
prepend_crc32?()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 40 def self.prepend_crc32? @prepend_crc32 end
prepend_size()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 21 def self.prepend_size @prepend_size = true self end
prepend_size?()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 36 def self.prepend_size? @prepend_size end
read(buffer)
click to toggle source
Populate struct from buffer based on members and their type definition.
# File lib/poseidon/protocol/protocol_struct.rb, line 153 def self.read(buffer) s = new s.read(buffer) s end
size_bound_array(member)
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 48 def self.size_bound_array(member) @size_bound_members ||= [] @size_bound_members << member self end
size_bound_array?(member)
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 54 def self.size_bound_array?(member) @size_bound_members ||= [] @size_bound_members.include?(member) end
truncatable()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 31 def self.truncatable @truncatable = true self end
truncatable?()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 44 def self.truncatable? @truncatable end
type_map()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 17 def self.type_map @type_map end
type_map=(type_map)
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 13 def self.type_map=(type_map) @type_map = type_map end
Public Instance Methods
checksum_failed?()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 247 def checksum_failed? @checksum_failed end
error_class()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 89 def error_class Errors::ERROR_CODES[self[:error]] end
have_header?(buffer)
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 197 def have_header?(buffer) if self.class.truncatable? if self.class.prepend_crc32? header_bytes = 8 else header_bytes = 4 end return buffer.bytes_remaining >= header_bytes else return true end end
maybe_prepend_crc32(buffer) { || ... }
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 123 def maybe_prepend_crc32(buffer) if self.class.prepend_crc32? buffer.prepend_crc32 do yield end else yield end end
maybe_prepend_size(buffer) { || ... }
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 113 def maybe_prepend_size(buffer) if self.class.prepend_size? buffer.prepend_size do yield end else yield end end
objects_with_errors()
click to toggle source
Recursively find all objects with errors
# File lib/poseidon/protocol/protocol_struct.rb, line 60 def objects_with_errors children = [] each_pair do |member, value| case value when Array value.each do |v| if v.respond_to?(:objects_with_errors) children << v end end else if value.respond_to?(:objects_with_errors) children << value end end end children_with_errors = children.map(&:objects_with_errors).flatten if members.include?(:error) && self[:error] != Errors::NO_ERROR_CODE children_with_errors + [self] else children_with_errors end end
raise_error()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 85 def raise_error raise error_class if error_class end
raise_error_if_one_exists()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 93 def raise_error_if_one_exists objects_with_errors.each do |object| object.raise_error end end
read(buffer)
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 159 def read(buffer) if self.class.prepend_size? if !have_header?(buffer) @truncated = true return end @size = buffer.int32 if self.class.prepend_crc32? @crc32 = buffer.int32 @computed_crc32 = [Zlib::crc32(buffer.peek(@size-4))].pack("l>").unpack("l>").first if @crc32 != @computed_crc32 @checksum_failed = true end expected_bytes_remaining = @size - 4 else expected_bytes_remaining = @size end if self.class.truncatable? && expected_bytes_remaining > buffer.bytes_remaining @truncated = true return end end members.each do |member| begin self[member] = read_member(buffer, member) rescue DecodingError # Just reraise instead of producing a crazy nested exception raise rescue raise DecodingError, "Error while reading #{member} in #{self.class} (#{$!.class}: #{$!.message}))" end end end
read_member(buffer, member)
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 211 def read_member(buffer, member) case type = type_map[member] when Array if self.class.size_bound_array?(member) if @size array_buffer = ResponseBuffer.new(buffer.read(@size)) else array_buffer = buffer end array = [] while !array_buffer.eof? && (v = read_type(array_buffer, type.first)) array << v end array else buffer.int32.times.map { read_type(buffer, type.first) } end else read_type(buffer, type) end end
read_type(buffer, type)
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 234 def read_type(buffer, type) case type when Symbol buffer.send(type) else type.read(buffer) end end
truncated?()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 251 def truncated? @truncated end
type_map()
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 243 def type_map self.class.type_map end
write(buffer)
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 99 def write(buffer) maybe_prepend_size(buffer) do maybe_prepend_crc32(buffer) do each_pair do |member, value| begin write_member(buffer, member, value) rescue raise EncodingError, "Error writting #{member} in #{self.class} (#{$!.class}: #{$!.message})" end end end end end
write_member(buffer, member, value)
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 133 def write_member(buffer, member, value) case type = type_map[member] when Array buffer.int32(value.size) unless self.class.size_bound_array?(member) value.each { |v| write_type(buffer, type.first, v) } else write_type(buffer, type, value) end end
write_type(buffer, type, value)
click to toggle source
# File lib/poseidon/protocol/protocol_struct.rb, line 143 def write_type(buffer, type, value) case type when Symbol buffer.send(type, value) else value.write(buffer) end end