Class: BSON::Binary

Inherits:
Object
  • Object
show all
Includes:
JSON
Defined in:
lib/bson/binary.rb

Overview

Represents binary data.

See Also:

Since:

  • 2.0.0

Constant Summary collapse

BSON_TYPE =

A binary is type 0x05 in the BSON spec.

Since:

  • 2.0.0

::String.new(5.chr, encoding: BINARY).freeze
SUBTYPES =
Note:

subtype 6 (ciphertext) is used for the Client-Side Encryption feature. Data represented by this subtype is often encrypted, but may also be plaintext. All instances of this subtype necessary for Client-Side Encryption will be created internally by the Ruby driver. An application should not create new BSON::Binary objects of this subtype.

The mappings of subtypes to their single byte identifiers.

Since:

  • 2.0.0

{
  generic: 0.chr,
  function: 1.chr,
  old: 2.chr,
  uuid_old: 3.chr,
  uuid: 4.chr,
  md5: 5.chr,
  ciphertext: 6.chr,
  column: 7.chr,
  sensitive: 8.chr,
  user: 128.chr,
}.freeze
USER_SUBTYPE =

The starting point of the user-defined subtype range.

Since:

  • 2.0.0

0x80
TYPES =

The mappings of single byte subtypes to their symbol counterparts.

Since:

  • 2.0.0

SUBTYPES.invert.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from JSON

#to_json

Constructor Details

#initialize(data = '', type = :generic) ⇒ Binary

Instantiate the new binary object.

This method accepts a string in any encoding; however, if a string is of a non-BINARY encoding, the encoding is set to BINARY. This does not change the bytes of the string but it means that applications referencing the data of a Binary instance cannot assume it is in a non-binary encoding, even if the string given to the constructor was in such an encoding.

Examples:

Instantiate a binary.

BSON::Binary.new(data, :md5)

Parameters:

  • data (String) (defaults to: '')

    The raw binary data.

  • type (Symbol) (defaults to: :generic)

    The binary type.

Since:

  • 2.0.0



150
151
152
# File 'lib/bson/binary.rb', line 150

def initialize(data = '', type = :generic)
  initialize_instance(data, type)
end

Instance Attribute Details

#dataString (readonly)

The string is always stored in BINARY encoding.

Returns:

  • (String)

    The raw binary data.

Since:

  • 2.0.0



68
69
70
# File 'lib/bson/binary.rb', line 68

def data
  @data
end

#raw_typeString (readonly)

Returns The raw type value, as an encoded integer.

Returns:

  • (String)

    The raw type value, as an encoded integer.

Since:

  • 2.0.0



74
75
76
# File 'lib/bson/binary.rb', line 74

def raw_type
  @raw_type
end

#typeSymbol (readonly)

Returns The binary type.

Returns:

  • (Symbol)

    The binary type.

Since:

  • 2.0.0



71
72
73
# File 'lib/bson/binary.rb', line 71

def type
  @type
end

Class Method Details

.from_bson(buffer, **_options) ⇒ Binary

Deserialize the binary data from BSON.

Parameters:

  • buffer (ByteBuffer)

    The byte buffer.

  • options (Hash)

    a customizable set of options

Returns:

  • (Binary)

    The decoded binary data.

See Also:

Since:

  • 2.0.0



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/bson/binary.rb', line 247

def self.from_bson(buffer, **_options)
  length = buffer.get_int32
  type_byte = buffer.get_byte

  if type_byte.bytes.first < USER_SUBTYPE
    type = TYPES[type_byte]

    if type.nil?
      raise Error::UnsupportedBinarySubtype,
            "BSON data contains unsupported binary subtype #{'0x%02x' % type_byte.ord}"
    end
  else
    type = type_byte
  end

  length = buffer.get_int32 if type == :old
  data = buffer.get_bytes(length)
  new(data, type)
end

.from_csharp_legacy_uuid(uuid_binary) ⇒ BSON::Binary

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Constructs a new binary object from a csharp legacy-format binary UUID representation.

Parameters:

  • uuid_binary (String)

    the UUID data

Returns:

Since:

  • 2.0.0



324
325
326
327
# File 'lib/bson/binary.rb', line 324

def self.from_csharp_legacy_uuid(uuid_binary)
  uuid_binary.sub!(/\A(.)(.)(.)(.)(.)(.)(.)(.)(.{8})\z/, '\4\3\2\1\6\5\8\7\9')
  new(uuid_binary, :uuid_old)
end

.from_java_legacy_uuid(uuid_binary) ⇒ BSON::Binary

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Constructs a new binary object from a java legacy-format binary UUID representation.

Parameters:

  • uuid_binary (String)

    the UUID data

Returns:

Since:

  • 2.0.0



337
338
339
340
341
342
# File 'lib/bson/binary.rb', line 337

def self.from_java_legacy_uuid(uuid_binary)
  uuid_binary.sub!(/\A(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)\z/) do
    (::Regexp.last_match[1..8].reverse + ::Regexp.last_match[9..16].reverse).join
  end
  new(uuid_binary, :uuid_old)
end

.from_python_legacy_uuid(uuid_binary) ⇒ BSON::Binary

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Constructs a new binary object from a python legacy-format binary UUID representation.

Parameters:

  • uuid_binary (String)

    the UUID data

Returns:

Since:

  • 2.0.0



352
353
354
# File 'lib/bson/binary.rb', line 352

def self.from_python_legacy_uuid(uuid_binary)
  new(uuid_binary, :uuid_old)
end

.from_standard_uuid(uuid_binary) ⇒ BSON::Binary

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Constructs a new binary object from a standard-format binary UUID representation.

Parameters:

  • uuid_binary (String)

    the UUID data

Returns:

Since:

  • 2.0.0



312
313
314
# File 'lib/bson/binary.rb', line 312

def self.from_standard_uuid(uuid_binary)
  new(uuid_binary, :uuid)
end

.from_uuid(uuid, representation = nil) ⇒ Binary

Creates a BSON::Binary from a string representation of a UUID.

The UUID may be given in either 00112233-4455-6677-8899-aabbccddeeff or 00112233445566778899AABBCCDDEEFF format - specifically, any dashes in the UUID are removed and both upper and lower case letters are acceptable.

The input UUID string is always interpreted to be in the RFC 4122 format.

If representation is not provided, this method creates a BSON::Binary of subtype 4 (:uuid). If representation is provided, it must be one of :standard, :csharp_legacy, :java_legacy or :python_legacy. If representation is :standard, this method creates a subtype 4 (:uuid) binary which is the same behavior as if representation was not provided. For other representations, this method creates a Binary of subtype 3 (:uuid_old) with the UUID converted to the appropriate legacy MongoDB UUID storage format.

Parameters:

  • uuid (String)

    The string representation of the UUID.

  • representation (Symbol) (defaults to: nil)

    How to interpret the UUID.

Returns:

Raises:

  • (ArgumentError)

    If invalid representation is requested.

Since:

  • 2.0.0



292
293
294
295
296
297
298
299
300
301
302
# File 'lib/bson/binary.rb', line 292

def self.from_uuid(uuid, representation = nil)
  raise ArgumentError, "Representation must be given as a symbol: #{representation}" if representation.is_a?(String)

  uuid_binary = uuid.delete('-').scan(/../).map(&:hex).map(&:chr).join
  representation ||= :standard

  handler = :"from_#{representation}_uuid"
  raise ArgumentError, "Invalid representation: #{representation}" unless respond_to?(handler)

  send(handler, uuid_binary)
end

Instance Method Details

#==(other) ⇒ true, false Also known as: eql?

Determine if this binary object is equal to another object.

Examples:

Check the binary equality.

binary == other

Parameters:

  • other (Object)

    The object to compare against.

Returns:

  • (true, false)

    If the objects are equal.

Since:

  • 2.0.0



86
87
88
89
90
# File 'lib/bson/binary.rb', line 86

def ==(other)
  return false unless other.is_a?(Binary)

  type == other.type && data == other.data
end

#as_extended_json(**options) ⇒ Hash

Converts this object to a representation directly serializable to Extended JSON (github.com/mongodb/specifications/blob/master/source/extended-json.rst).

Parameters:

  • opts (Hash)

    a customizable set of options

Returns:

  • (Hash)

    The extended json representation.

Since:

  • 2.0.0



121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/bson/binary.rb', line 121

def as_extended_json(**options)
  subtype = @raw_type.each_byte.map { |c| c.to_s(16) }.join
  subtype = "0#{subtype}" if subtype.length == 1

  value = Base64.encode64(data).strip

  if options[:mode] == :legacy
    { '$binary' => value, '$type' => subtype }
  else
    { '$binary' => { 'base64' => value, 'subType' => subtype } }
  end
end

#as_json(*_args) ⇒ Hash

Return a representation of the object for use in application-level JSON serialization. Since BSON::Binary is used exclusively in BSON-related contexts, this method returns the canonical Extended JSON representation.

Returns:

  • (Hash)

    The extended json representation.

Since:

  • 2.0.0



110
111
112
# File 'lib/bson/binary.rb', line 110

def as_json(*_args)
  as_extended_json
end

#hashFixnum

Generates a Fixnum hash value for this object.

Allows using Binary as hash keys.

Returns:

  • (Fixnum)

Since:

  • 2.3.1



100
101
102
# File 'lib/bson/binary.rb', line 100

def hash
  [ data, type ].hash
end

#init_with(coder) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

For legacy deserialization support where BSON::Binary objects are expected to have a specific internal representation (with only

Since:

  • 2.0.0



159
160
161
# File 'lib/bson/binary.rb', line 159

def init_with(coder)
  initialize_instance(coder['data'], coder['type'])
end

#inspectString

Get a nice string for use with object inspection.

Examples:

Inspect the binary.

object_id.inspect

Returns:

  • (String)

    The binary in form BSON::Binary:object_id

Since:

  • 2.3.0



171
172
173
# File 'lib/bson/binary.rb', line 171

def inspect
  "<BSON::Binary:0x#{object_id} type=#{type} data=0x#{data[0, 8].unpack1('H*')}...>"
end

#to_bson(buffer = ByteBuffer.new) ⇒ BSON::ByteBuffer

Encode the binary type

Examples:

Encode the binary.

binary.to_bson

Returns:

See Also:

Since:

  • 2.0.0



227
228
229
230
231
232
233
234
# File 'lib/bson/binary.rb', line 227

def to_bson(buffer = ByteBuffer.new)
  position = buffer.length
  buffer.put_int32(0)
  buffer.put_byte(@raw_type)
  buffer.put_int32(data.bytesize) if type == :old
  buffer.put_bytes(data)
  buffer.replace_int32(position, buffer.length - position - 5)
end

#to_uuid(representation = nil) ⇒ String

Returns a string representation of the UUID stored in this Binary.

If the Binary is of subtype 4 (:uuid), this method returns the UUID in RFC 4122 format. If the representation parameter is provided, it must be the value :standard as a symbol or a string.

If the Binary is of subtype 3 (:uuid_old), this method requires that the representation parameter is provided and is one of :csharp_legacy, :java_legacy or :python_legacy or the equivalent strings. In this case the method assumes the Binary stores the UUID in the specified format, transforms the stored bytes to the standard RFC 4122 representation and returns the UUID in RFC 4122 format.

If the Binary is of another subtype, this method raises TypeError.

Parameters:

  • representation (Symbol) (defaults to: nil)

    How to interpret the UUID.

Returns:

  • (String)

    The string representation of the UUID.

Raises:

  • (TypeError)

    If the subtype of Binary is not :uuid nor :uuid_old.

  • (ArgumentError)

    If the representation other than :standard is requested for Binary subtype 4 (:uuid), if :standard representation is requested for Binary subtype 3 (:uuid_old), or if an invalid representation is requested.

Since:

  • 2.0.0



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/bson/binary.rb', line 201

def to_uuid(representation = nil)
  if representation.is_a?(String)
    raise ArgumentError,
          "Representation must be given as a symbol: #{representation.inspect}"
  end

  case type
  when :uuid
    from_uuid_to_uuid(representation || :standard)
  when :uuid_old
    from_uuid_old_to_uuid(representation)
  else
    raise TypeError, "The type of Binary must be :uuid or :uuid_old, this object is: #{type.inspect}"
  end
end