module BSON::Hash::ClassMethods

The methods to augment the Hash class with (class-level methods).

Public Instance Methods

from_bson(buffer, **options) click to toggle source

Deserialize the hash from BSON.

@note If the argument cannot be parsed, an exception will be raised

and the argument will be left in an undefined state. The caller
must explicitly call `rewind` on the buffer before trying to parse
it again.

@param [ ByteBuffer ] buffer The byte buffer.

@option options [ nil | :bson ] :mode Decoding mode to use.

@return [ Hash ] The decoded hash.

@see bsonspec.org/#/specification

# File lib/bson/hash.rb, line 137
def from_bson(buffer, **options)
  if buffer.respond_to?(:get_hash)
    buffer.get_hash(**options)
  else
    hash = parse_hash_from_buffer(buffer, **options)
    maybe_dbref(hash)
  end
end

Private Instance Methods

maybe_dbref(hash) click to toggle source

If the hash looks like a DBRef, try and decode it as such. If is turns out to be invalid–or if it doesn’t look like a DBRef to begin with–return the hash itself.

@param [ Hash ] hash the hash to try and decode

@return [ DBRef | Hash ] the result of decoding the hash

# File lib/bson/hash.rb, line 155
def maybe_dbref(hash)
  return DBRef.new(hash) if hash['$ref'] && hash['$id']

  hash
rescue Error::InvalidDBRefArgument
  hash
end
parse_hash_contents(hash, buffer, **options) click to toggle source

Given an empty hash and a byte buffer, parse the key/value pairs from the buffer and populate the hash with them.

@param [ Hash ] hash the hash to populate @param [ ByteBuf ] buffer the buffer to read data from @param [ Hash ] options the keyword arguments

# File lib/bson/hash.rb, line 189
def parse_hash_contents(hash, buffer, **options)
  while (type = buffer.get_byte) != NULL_BYTE
    field = buffer.get_cstring
    cls = BSON::Registry.get(type, field)
    value = if options.empty?
              # Compatibility with the older Ruby driver versions which define
              # a DBRef class with from_bson accepting a single argument.
              cls.from_bson(buffer)
            else
              cls.from_bson(buffer, **options)
            end
    hash.store(field, value)
  end
end
parse_hash_from_buffer(buffer, **options) click to toggle source

Given a byte buffer, extract and return a hash from it.

@param [ ByteBuf ] buffer the buffer to read data from @param [ Hash ] options the keyword arguments

@return [ Hash ] the hash parsed from the buffer

# File lib/bson/hash.rb, line 169
def parse_hash_from_buffer(buffer, **options)
  hash = Document.allocate
  start_position = buffer.read_position
  expected_byte_size = buffer.get_int32

  parse_hash_contents(hash, buffer, **options)

  actual_byte_size = buffer.read_position - start_position
  return hash unless actual_byte_size != expected_byte_size

  raise Error::BSONDecodeError,
        "Expected hash to take #{expected_byte_size} bytes but it took #{actual_byte_size} bytes"
end