Class: BSON::Binary

Inherits:
Object
  • Object
show all
Includes:
JSON, Comparable
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



165
166
167
# File 'lib/bson/binary.rb', line 165

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



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

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



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

def raw_type
  @raw_type
end

#typeSymbol (readonly)

Returns The binary type.

Returns:

  • (Symbol)

    The binary type.

Since:

  • 2.0.0



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

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



262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/bson/binary.rb', line 262

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



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

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



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

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



367
368
369
# File 'lib/bson/binary.rb', line 367

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



327
328
329
# File 'lib/bson/binary.rb', line 327

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



307
308
309
310
311
312
313
314
315
316
317
# File 'lib/bson/binary.rb', line 307

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) ⇒ Integer | nil

Compare this binary object to another object. The two objects must have the same type for any meaningful comparison.

Parameters:

  • other (Object)

    The object to compare against.

Returns:

  • (Integer | nil)

    If the objects have the same type, the result is -1 if self < other, 0 if self == other, and 1 if self > other. If other is not a Binary, or is a Binary of a different type, returns nil.

Since:

  • 2.0.0



102
103
104
105
106
# File 'lib/bson/binary.rb', line 102

def <=>(other)
  return nil unless other.is_a?(Binary) && type == other.type

  data <=> other.data
end

#==(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



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

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/extended-json.md).

Parameters:

  • opts (Hash)

    a customizable set of options

Returns:

  • (Hash)

    The extended json representation.

Since:

  • 2.0.0



136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/bson/binary.rb', line 136

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



125
126
127
# File 'lib/bson/binary.rb', line 125

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



115
116
117
# File 'lib/bson/binary.rb', line 115

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



174
175
176
# File 'lib/bson/binary.rb', line 174

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



186
187
188
# File 'lib/bson/binary.rb', line 186

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



242
243
244
245
246
247
248
249
# File 'lib/bson/binary.rb', line 242

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



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/bson/binary.rb', line 216

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