Last active
August 29, 2015 13:59
-
-
Save felixbuenemann/10618216 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
# Simple UUID Generator for UUID v0 (zero padded), v1, v2, v3, v4, v5 | |
# Author: Felix Buenemann https://github.com/felixbuenemann/ | |
# License: Public Domain | |
# Note: v1 code partially based on these ruby uuid implementations: | |
# https://github.com/assaf/uuid/ | |
# https://github.com/cassandra-rb/simple_uuid | |
require 'digest/md5' | |
require 'digest/sha1' | |
require 'securerandom' | |
module UUIDGenerator | |
GREGORIAN_EPOCH_OFFSET = 0x01B2_1DD2_1381_4000.freeze # Oct 15, 1582 | |
UUID_NIL = '00000000-0000-0000-0000-000000000000'.freeze | |
UUID_DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'.freeze | |
UUID_URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'.freeze | |
UUID_OID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8'.freeze | |
UUID_X500= '6ba7b814-9dad-11d1-80b4-00c04fd430c8'.freeze | |
@@mutex = Mutex.new | |
class << self | |
# if value is given, generates zero padded pseudo-uuid | |
def generate_v0(value = nil) | |
format_uuid 0, value.to_s | |
end | |
# naive implementation of uuid v1 | |
# doesn't synchronize sequence between processes | |
# and doesn't correct for clock skew | |
def generate_v1(mac = nil, time = Time.new, sequence = next_sequence) | |
clock = (time.to_i * 1_000_000 + time.usec) * 10 + GREGORIAN_EPOCH_OFFSET | |
mac = (mac ? mac.gsub(/:|-/, '').hex : 0) & 0x7FFF_FFFF_FFFF | |
format_uuid 1, '%08x%04x%04x%04x%012x' % [ | |
clock & 0xFFFF_FFFF, | |
(clock >> 32) & 0xFFFF, | |
(clock >> 48) & 0xFFFF, | |
sequence & 0xFFFF, | |
mac & 0xFFFF_FFFF_FFFF | |
] | |
end | |
def generate_v3(value, namespace = UUID_NIL) | |
namespace_bytes = uuid_str_to_bytes(namespace) | |
format_uuid 3, Digest::MD5.hexdigest("#{namespace_bytes}#{value}") | |
end | |
def generate_v4 | |
SecureRandom.uuid | |
end | |
def generate_v5(value, namespace = UUID_NIL) | |
namespace_bytes = uuid_str_to_bytes(namespace) | |
format_uuid 5, Digest::SHA1.hexdigest("#{namespace_bytes}#{value}") | |
end | |
private | |
def next_sequence | |
@@mutex.synchronize { @sequence = @sequence.to_i.next } | |
end | |
def format_uuid(version, value) | |
s = value.rjust(32, '0') | |
if version > 0 | |
s[12] = version.to_s | |
s[16] = byte_to_variant(s[16]) | |
end | |
"#{s[0..7]}-#{s[8..11]}-#{s[12..15]}-#{s[16..19]}-#{s[20..31]}" | |
end | |
def byte_to_variant(byte) | |
[0x8,0x9,0xa,0xb][byte.hex/4].to_s(16) | |
end | |
def uuid_str_to_bytes(string) | |
[string.gsub(/-/,'')].pack('H*') | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment