class SimpleUUID::UUID

UUID format version 1, as specified in RFC 4122, with jitter in place of the mac address and sequence counter.

Constants

GREGORIAN_EPOCH_OFFSET
VARIANT

Public Class Methods

new(bytes = nil, opts = {}) click to toggle source
# File lib/simple_uuid.rb, line 23
def initialize(bytes = nil, opts = {})
  case bytes
  when self.class # UUID
    @bytes = bytes.to_s
  when String
    case bytes.size
    when 16 # Raw byte array
      @bytes = bytes.respond_to?(:force_encoding) ? bytes.force_encoding("ASCII-8BIT") : bytes
    when 36 # Human-readable UUID representation; inverse of #to_guid
      elements = bytes.split("-")
      raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (malformed UUID representation)" if elements.size != 5
      @bytes = [elements.join].pack('H32')
    else
      raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (invalid bytecount)"
    end

  when Integer
    raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (integer out of range)" if bytes < 0 or bytes > 2**128
    @bytes = [
      (bytes >> 96) & 0xFFFF_FFFF,
      (bytes >> 64) & 0xFFFF_FFFF,
      (bytes >> 32) & 0xFFFF_FFFF,
      bytes & 0xFFFF_FFFF
    ].pack("NNNN")

  when NilClass, Time
    time = (bytes || Time).stamp * 10 + GREGORIAN_EPOCH_OFFSET
    # See http://github.com/spectra/ruby-uuid/
    byte_array = [
      time & 0xFFFF_FFFF,
      time >> 32,
      ((time >> 48) & 0x0FFF) | 0x1000,
    ]

    # Top 3 bytes reserved
    if opts[:randomize] == false
      byte_array += if !opts[:salt].nil?
        clock_h, clock_l, node_h, node_l =
          opts[:salt].to_s.unpack("CCnN")

        clock = [
          clock_h | VARIANT,
          clock_l
        ].pack("n").unpack("n").first

        [ clock, node_h, node_l ]
      else
        [ 0 | VARIANT, 0, 0 ]
      end
    else
      byte_array += [
        rand(2**13) | VARIANT,
        rand(2**16),
        rand(2**32)
      ]
    end

    @bytes = byte_array.pack("NnnnnN")
  else
    raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (unknown source class)"
  end
end
to_time(bytes) click to toggle source

Given raw bytes, return a time object

# File lib/simple_uuid.rb, line 155
def self.to_time(bytes)
  usecs = total_usecs(bytes)
  Time.at(usecs / 1_000_000, usecs % 1_000_000)
end
total_usecs(bytes) click to toggle source

Given raw bytes, return the ::total_usecs

# File lib/simple_uuid.rb, line 166
def self.total_usecs(bytes)
  elements = bytes.unpack("Nnn")
  (elements[0] + (elements[1] << 32) + ((elements[2] & 0x0FFF) << 48) - GREGORIAN_EPOCH_OFFSET) / 10
end

Public Instance Methods

<=>(other) click to toggle source
# File lib/simple_uuid.rb, line 119
def <=>(other)
  me = to_s.unpack('Nn2C*')
  him = other.to_s.unpack('Nn2C*')
  # swap most significant time bits to front
  me[0], me[2], him[0], him[2] = me[2], me[0], him[2], him[0]
  me.zip(him) do |m, h|
    comp = m <=> h
    return comp if comp != 0
  end
  return 0
end
bytes() click to toggle source
Alias for: to_s
eql?(other) click to toggle source
# File lib/simple_uuid.rb, line 150
def eql?(other)
  other.respond_to?(:bytes) && bytes == other.bytes
end
hash() click to toggle source
# File lib/simple_uuid.rb, line 146
def hash
  @bytes.hash
end
inspect(long = false) click to toggle source
# File lib/simple_uuid.rb, line 131
def inspect(long = false)
  "<UUID##{object_id} time: #{
    to_time.inspect
  }, usecs: #{
    usecs
  } jitter: #{
    @bytes.unpack('QQ')[1]
  }" + (long ? ", version: #{version}, variant: #{variant}, guid: #{to_guid}>" :  ">")
end
seconds() click to toggle source
# File lib/simple_uuid.rb, line 111
def seconds
  total_usecs / 1_000_000
end
to_guid() click to toggle source
# File lib/simple_uuid.rb, line 104
def to_guid
  elements = @bytes.unpack("NnnCCa6")
  node = elements[-1].unpack('C*')
  elements[-1] = '%02x%02x%02x%02x%02x%02x' % node
  "%08x-%04x-%04x-%02x%02x-%s" % elements
end
to_i() click to toggle source
# File lib/simple_uuid.rb, line 86
def to_i
  ints = @bytes.unpack("NNNN")
  (ints[0] << 96) +
  (ints[1] << 64) +
  (ints[2] << 32) +
  ints[3]
end
to_s() click to toggle source
# File lib/simple_uuid.rb, line 141
def to_s
  @bytes
end
Also aliased as: bytes
to_time() click to toggle source

Return a time object

# File lib/simple_uuid.rb, line 161
def to_time
  Time.at(total_usecs / 1_000_000, total_usecs % 1_000_000)
end
usecs() click to toggle source
# File lib/simple_uuid.rb, line 115
def usecs
  total_usecs % 1_000_000
end
variant() click to toggle source
# File lib/simple_uuid.rb, line 100
def variant
  @bytes.unpack('QnnN')[1] >> 13
end
version() click to toggle source
# File lib/simple_uuid.rb, line 94
def version
  time_high = @bytes.unpack("NnnQ")[2]
  version = (time_high & 0xF000).to_s(16)[0].chr.to_i
  version > 0 and version < 6 ? version : -1
end