module BSON::Hash::ClassMethods

Public Instance Methods

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

Deserialize the hash from BSON.

@param [ ByteBuffer ] buffer The byte buffer.

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

@return [ Hash ] The decoded hash.

@see bsonspec.org/#/specification

@since 2.0.0

# File lib/bson/hash.rb, line 108
def from_bson(buffer, **options)
  if buffer.respond_to?(:get_hash)
    buffer.get_hash(**options)
  else
    hash = Document.allocate
    start_position = buffer.read_position
    expected_byte_size = buffer.get_int32
    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
    actual_byte_size = buffer.read_position - start_position
    if 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

    if hash['$ref'] && hash['$id']
      # We're doing implicit decoding here. If the document is an invalid
      # dbref, we should decode it as a BSON::Document.
      begin
        hash = DBRef.new(hash)
      rescue ArgumentError
      end
    end

    hash
  end
end