Provides a DSL for defining struct-like fields for building messages for the Mongo Wire.
@example
class Command extend Message::ClassMethods int32 :length end Command.fields # => [:length] command = Command.new command.length = 12 command.serialize_length("") # => "\f\x00\x00\x00"
Declare a null terminated string field.
@example
class Query < Message cstring :collection end
@param [String] name the name of this field
# File lib/moped/protocol/message.rb, line 81 def cstring(name) attr_accessor name class_eval def serialize_#{name}(buffer) buffer << #{name} buffer << 0 end, __FILE__, __LINE__ + 1 fields << name end
Declare a BSON Document field.
@example
class Update < Message document :selector end
@example optional document field
class Query < Message document :selector document :fields, optional: true end
@example array of documents
class Reply < Message document :documents, type: :array end
@param [String] name the name of this field @param [Hash] options the options for this field @option options [:array] :type specify an array of documents @option options [Boolean] :optional specify this field as optional
# File lib/moped/protocol/message.rb, line 116 def document(name, options = {}) attr_accessor name if options[:optional] class_eval def serialize_#{name}(buffer) BSON::Document.serialize(#{name}, buffer) if #{name} end, __FILE__, __LINE__ + 1 elsif options[:type] == :array class_eval def serialize_#{name}(buffer) #{name}.each do |document| BSON::Document.serialize(document, buffer) end end, __FILE__, __LINE__ + 1 else class_eval def serialize_#{name}(buffer) BSON::Document.serialize(#{name}, buffer) end, __FILE__, __LINE__ + 1 end fields << name end
@return [Array] the fields defined for this message
# File lib/moped/protocol/message.rb, line 69 def fields @fields ||= [] end
Declares the message class as complete, and defines its serialization method from the declared fields.
# File lib/moped/protocol/message.rb, line 276 def finalize class_eval def serialize(buffer = "") start = buffer.bytesize #{fields.map { |f| "serialize_#{f}(buffer)" }.join("\n")} self.length = buffer.bytesize - start buffer[start, 4] = serialize_length "" buffer end alias to_s serialize, __FILE__, __LINE__ + 1 end
Declare a flag field (32 bit signed integer)
@example
class Update < Message flags :flags, upsert: 2 ** 0, multi: 2 ** 1 end
@param [String] name the name of this field @param [Hash{Symbol => Number}] flags the flags for this flag field
# File lib/moped/protocol/message.rb, line 154 def flags(name, flag_map = {}) class_eval def #{name} @#{name} ||= [] end def #{name}=(flags) if flags.is_a? Numeric @#{name} = #{name}_from_int(flags) else @#{name} = flags end end def #{name}_as_int bits = 0 flags = self.#{name} #{flag_map.map { |flag, value| "bits |= #{value} if flags.include? #{flag.inspect}" }.join "\n"} bits end def #{name}_from_int(bits) flags = [] #{flag_map.map { |flag, value| "flags << #{flag.inspect} if #{value} & bits == #{value}" }.join "\n"} flags end def serialize_#{name}(buffer) buffer << [#{name}_as_int].pack('l<') end def deserialize_#{name}(buffer) bits, = buffer.read(4).unpack('l<') self.#{name} = bits end, __FILE__, __LINE__ + 1 fields << name end
Declare a 32 bit signed integer field.
@example
class Query < Message int32 :length end
@param [String] name the name of this field
# File lib/moped/protocol/message.rb, line 203 def int32(name) attr_writer name class_eval def #{name} @#{name} ||= 0 end def serialize_#{name}(buffer) buffer << [#{name}].pack('l<') end def deserialize_#{name}(buffer) self.#{name}, = buffer.read(4).unpack('l<') end, __FILE__, __LINE__ + 1 fields << name end
Declare a 64 bit signed integer field.
@example
class Query < Message int64 :cursor_id end
@example with array type
class KillCursors < Message int64 :cursor_ids, type: :array end
@param [String] name the name of this field @param [Hash] options the options for this field @option options [:array] :type specify an array of 64 bit ints
# File lib/moped/protocol/message.rb, line 238 def int64(name, options = {}) attr_writer name if options[:type] == :array class_eval def #{name} @#{name} ||= [] end def serialize_#{name}(buffer) buffer << #{name}.pack('q<*') end def deserialize_#{name}(buffer) raise NotImplementedError end, __FILE__, __LINE__ + 1 else class_eval def #{name} @#{name} ||= 0 end def serialize_#{name}(buffer) buffer << [#{name}].pack('q<') end def deserialize_#{name}(buffer) self.#{name}, = buffer.read(8).unpack('q<') end, __FILE__, __LINE__ + 1 end fields << name end
Generated with the Darkfish Rdoc Generator 2.