Class: SimpleUUID::UUID

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/simple_uuid.rb

Overview

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

Defined Under Namespace

Classes: InvalidVersion

Constant Summary collapse

GREGORIAN_EPOCH_OFFSET =

Oct 15, 1582

0x01B2_1DD2_1381_4000
VARIANT =
0b1000_0000_0000_0000

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bytes = nil, opts = {}) ⇒ UUID

Returns a new instance of UUID.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# 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
    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 += [
        0 | VARIANT,
        0,
        0
      ]
    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

Class Method Details

.to_time(bytes) ⇒ Object

Given raw bytes, return a time object



143
144
145
146
# File 'lib/simple_uuid.rb', line 143

def self.to_time(bytes)
  usecs = total_usecs(bytes)
  Time.at(usecs / 1_000_000, usecs % 1_000_000)
end

.total_usecs(bytes) ⇒ Object

Given raw bytes, return the total_usecs



154
155
156
157
# File 'lib/simple_uuid.rb', line 154

def self.total_usecs(bytes)
  elements = bytes.unpack("Nnn")
  (elements[0] + (elements[1] << 32) + ((elements[2] & 0x0FFF) << 48) - GREGORIAN_EPOCH_OFFSET) / 10
end

Instance Method Details

#<=>(other) ⇒ Object



111
112
113
# File 'lib/simple_uuid.rb', line 111

def <=>(other)
  total_usecs <=> other.send(:total_usecs)
end

#==(other) ⇒ Object



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

def ==(other)
  to_s == other.to_s
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


138
139
140
# File 'lib/simple_uuid.rb', line 138

def eql?(other)
  other.respond_to?(:bytes) && bytes == other.bytes
end

#hashObject



134
135
136
# File 'lib/simple_uuid.rb', line 134

def hash
  @bytes.hash
end

#inspect(long = false) ⇒ Object



119
120
121
122
123
124
125
126
127
# File 'lib/simple_uuid.rb', line 119

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

#secondsObject



103
104
105
# File 'lib/simple_uuid.rb', line 103

def seconds
  total_usecs / 1_000_000
end

#to_guidObject



96
97
98
99
100
101
# File 'lib/simple_uuid.rb', line 96

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_iObject



78
79
80
81
82
83
84
# File 'lib/simple_uuid.rb', line 78

def to_i
  ints = @bytes.unpack("NNNN")
  (ints[0] << 96) +
  (ints[1] << 64) +
  (ints[2] << 32) +
  ints[3]
end

#to_sObject Also known as: bytes



129
130
131
# File 'lib/simple_uuid.rb', line 129

def to_s
  @bytes
end

#to_timeObject

Return a time object



149
150
151
# File 'lib/simple_uuid.rb', line 149

def to_time
  Time.at(total_usecs / 1_000_000, total_usecs % 1_000_000)
end

#usecsObject



107
108
109
# File 'lib/simple_uuid.rb', line 107

def usecs
  total_usecs % 1_000_000
end

#variantObject



92
93
94
# File 'lib/simple_uuid.rb', line 92

def variant
  @bytes.unpack('QnnN')[1] >> 13
end

#versionObject



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

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