UUID format version 1, as specified in RFC 4122, with jitter in place of the mac address and sequence counter.
# 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
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
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
# 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
# File lib/simple_uuid.rb, line 150 def eql?(other) other.respond_to?(:bytes) && bytes == other.bytes end
# File lib/simple_uuid.rb, line 146 def hash @bytes.hash end
# 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
# File lib/simple_uuid.rb, line 111 def seconds total_usecs / 1_000_000 end
# 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
# 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
# File lib/simple_uuid.rb, line 141 def to_s @bytes end
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
# File lib/simple_uuid.rb, line 115 def usecs total_usecs % 1_000_000 end
# File lib/simple_uuid.rb, line 100 def variant @bytes.unpack('QnnN')[1] >> 13 end
# 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