Class: Lapis::Uuid

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

Overview

Note:

The naming scheme used for this class is as follows:

  • uuid - An instance of this class.

  • value - Packed string, not human readable. 16 bytes in length.

  • uuid_str - Formatted string, human readable. Formatted as xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12).

Universally unique identifier. Items with distinct different UUIDs should be different entities. Items with the same UUID should be the same entity.

Constant Summary collapse

DEFAULT =

Empty UUID.

Uuid.new("\x0" * 16).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value) ⇒ Uuid

Creates a UUID or one from an existing value.

See Also:


23
24
25
26
27
28
29
30
31
32
# File 'lib/lapis/uuid.rb', line 23

def initialize(value)
  value_str = value.to_s
  fail ArgumentError, 'Packed UUID value must be 16 bytes.' unless value_str.length == 16

  # Get a copy to prevent external processes modifying the value.
  @value = value_str.dup

  # Prevent modification.
  @value.freeze
end

Instance Attribute Details

#valueString (readonly)

Raw, packed byte string containing the UUID's value.


17
18
19
# File 'lib/lapis/uuid.rb', line 17

def value
  @value
end

Class Method Details

.generateUUID

Generates a new (and random) UUID


38
39
40
41
42
43
44
45
# File 'lib/lapis/uuid.rb', line 38

def generate
  # A built-in method from Ruby to generate a valid UUID is SecureRandom.uuid.
  # However, it returns it as a formatted string.
  # The formatted string has to be converted to a packed string before it can be used.
  uuid_str = SecureRandom.uuid
  value    = pack_uuid_str(uuid_str)
  Uuid.new(value)
end

.parse(uuid_str) ⇒ Uuid?

Note:

Casing does not matter for a-f.

Note:

Dashes may be omitted from the string. This allows strings of 32 hexadecimal characters.

Creates a UUID object from its string representation.


82
83
84
85
86
87
88
89
90
91
92
# File 'lib/lapis/uuid.rb', line 82

def parse(uuid_str)
  if valid_str?(uuid_str)
    # Properly formatted UUID string.
    # Pack the UUID into a byte string and return a new instance.
    value = pack_uuid_str(uuid_str)
    Uuid.new(value)
  else
    # Not properly formatted.
    nil
  end
end

.valid_str?(uuid_str) ⇒ true, false

Determines whether a string contains a valid formatted UUID.


51
52
53
54
55
56
57
58
59
60
# File 'lib/lapis/uuid.rb', line 51

def valid_str?(uuid_str)
  if uuid_str.is_a? String
    # Check the formatting.
    # Note that the validity of the UUID isn't checked.
    !!/^\A[0-9a-f]{8}(-?)[0-9a-f]{4}\1[0-9a-f]{4}\1[0-9a-f]{4}\1[0-9a-f]{12}\z$/i.match(uuid_str)
  else
    # A string wasn't passed in.
    fail ArgumentError
  end
end

Instance Method Details

#<=>(other) ⇒ -1, ...

Compares two UUIDs to each other to determine which is lower.


137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/lapis/uuid.rb', line 137

def <=>(other)
  case other
    when Uuid
      # Compare two UUID instances.
      cmp_packed(other.value)

    when String
      if other.length == 16
        # Compare against a packed string
        cmp_packed(other)

      else
        # Compare against a formatted string
        cmp_formatted(other)
      end

    else
      # Everything else can't be compared.
      nil
  end
end

#==(other) ⇒ true, false

Checks if two UUIDs have the same value.


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/lapis/uuid.rb', line 109

def ==(other)
  case other
    when Uuid
      # Compare two UUID instances.
      eq_packed(other.value)

    when String
      if other.length == 16
        # Compare against a packed string
        eq_packed(other)

      else
        # Compare against a formatted string
        eq_formatted(other)
      end

    else
      # Everything else can't be equated.
      false
  end
end

#eql?(other) ⇒ true, false

Note:

This method compares only Lapis::Uuid instances. false will be returned if other is not a Lapis::Uuid.

Checks for hash equality of two UUIDs.


101
102
103
# File 'lib/lapis/uuid.rb', line 101

def eql?(other)
  other.is_a?(Uuid) && eq_packed(other.value)
end

#hashFixnum

Produces a hash value of the UUID.


161
162
163
# File 'lib/lapis/uuid.rb', line 161

def hash
  @value.hash
end

#to_s(dashes = true) ⇒ String

Produces the string representation of the UUID.


169
170
171
172
173
174
175
176
# File 'lib/lapis/uuid.rb', line 169

def to_s(dashes = true)
  bytes = @value.bytes
  if dashes
    sprintf('%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x', *bytes)
  else
    sprintf('%02x' * 16, *bytes)
  end
end