Class: UUID
- Inherits:
-
Object
- Object
- UUID
- Includes:
- Comparable
- Defined in:
- lib/cast_off/compile/namespace/uuid.rb
Overview
Pure ruby UUID generator, which is compatible with RFC4122
Constant Summary collapse
- UNIXEpoch =
UUID epoch is 15th Oct. 1582
0x01B21DD213814000
- STATE_FILE =
'ruby-uuid'
- NameSpace_DNS =
Pre-defined UUID Namespaces described in RFC4122 Appendix C.
parse "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
- NameSpace_URL =
parse "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
- NameSpace_OID =
parse "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
- NameSpace_X500 =
parse "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
- Nil =
The Nil UUID in RFC4122 Section 4.1.7
parse "00000000-0000-0000-0000-000000000000"
Class Method Summary collapse
-
.new(clock = nil, time = Time.now, mac_addr = nil) ⇒ Object
create the “version 1” UUID with current system clock, current UTC timestamp, and the IEEE 802 address (so-called MAC address).
-
.new_md5(str, namespace) ⇒ Object
UUID generation using MD5 (for backward compat.).
-
.new_random ⇒ Object
UUID generation using random-number generator.
-
.new_sha1(str, namespace) ⇒ Object
UUID generation using SHA1.
-
.pack(tl, tm, th, ch, cl, n) ⇒ Object
The ‘primitive constructor’ of this class Note UUID.pack(uuid.unpack) == uuid.
-
.parse(obj) ⇒ Object
A simple GUID parser: just ignores unknown characters and convert hexadecimal dump into 16-octet object.
Instance Method Summary collapse
-
#<=>(other) ⇒ Object
UUIDs are comparable (don’t know what benefits are there, though).
-
#==(other) ⇒ Object
(also: #eql?)
Two UUIDs are said to be equal if and only if their (byte-order canonicalized) integer representations are equivallent.
-
#clock ⇒ Object
The clock sequence of this UUID.
-
#hash ⇒ Object
Two identical UUIDs should have same hash.
-
#new_md5(str) ⇒ Object
shortcut too.
-
#new_sha1(str) ⇒ Object
shortcut.
-
#node ⇒ Object
(also: #mac_address, #ieee802)
The IEEE 802 address in a hexadecimal format.
- #raw_bytes ⇒ Object
-
#time ⇒ Object
The timestamp of this UUID.
-
#to_int ⇒ Object
(also: #to_i)
Convert into 128-bit unsigned integer Typically a Bignum instance, but can be a Fixnum.
-
#to_s ⇒ Object
(also: #guid)
Generate the string representation (a.k.a GUID) of this UUID.
-
#to_uri ⇒ Object
(also: #urn, #inspect)
Convert into a RFC4122-comforming URN representation.
-
#unpack ⇒ Object
The ‘primitive deconstructor’, or the dual to pack.
-
#version ⇒ Object
The version of this UUID.
Class Method Details
.new(clock = nil, time = Time.now, mac_addr = nil) ⇒ Object
create the “version 1” UUID with current system clock, current UTC timestamp, and the IEEE 802 address (so-called MAC address).
Speed notice: it’s slow. It writes some data into hard drive on every invokation. If you want to speed this up, try remounting tmpdir with a memory based filesystem (such as tmpfs). STILL slow? then no way but rewrite it with c :)
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 134 def new clock=nil, time=Time.now, mac_addr=nil c = t = m = nil Dir.chdir Dir.tmpdir do unless FileTest.exist? STATE_FILE then # Generate a pseudo MAC address because we have no pure-ruby way # to know the MAC address of the NIC this system uses. Note # that cheating with pseudo arresses here is completely legal: # see Section 4.5 of RFC4122 for details. sha1 = Digest::SHA1.new 256.times do r = [prand].pack "N" sha1.update r end str = sha1.digest r = rand 34 # 40-6 node = str[r, 6] || str node = node.bytes.to_a node[0] |= 0x01 # multicast bit node = node.pack "C*" k = rand 0x40000 open STATE_FILE, 'w' do |fp| fp.flock IO::LOCK_EX write_state fp, k, node fp.chmod 0o777 # must be world writable end end open STATE_FILE, 'r+' do |fp| fp.flock IO::LOCK_EX c, m = read_state fp c += 1 # important; increment here write_state fp, c, m end end c = clock & 0b11_1111_1111_1111 if clock m = mac_addr if mac_addr time = Time.at time if time.is_a? Float case time when Time t = time.to_i * 10_000_000 + time.tv_usec * 10 + UNIXEpoch when Integer t = time + UNIXEpoch else raise TypeError, "cannot convert ``#{time}'' into Time." end tl = t & 0xFFFF_FFFF tm = t >> 32 tm = tm & 0xFFFF th = t >> 48 th = th & 0b0000_1111_1111_1111 th = th | 0b0001_0000_0000_0000 cl = c & 0b0000_0000_1111_1111 ch = c & 0b0011_1111_0000_0000 ch = ch >> 8 ch = ch | 0b1000_0000 pack tl, tm, th, ch, cl, m end |
.new_md5(str, namespace) ⇒ Object
UUID generation using MD5 (for backward compat.)
109 110 111 112 113 114 115 116 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 109 def new_md5 str, namespace md5 = Digest::MD5.new md5.update namespace.raw_bytes md5.update str sum = md5.digest raw = mask 3, sum[0..16] create raw end |
.new_random ⇒ Object
UUID generation using random-number generator. From it’s random nature, there’s no warranty that the created ID is really universaly unique.
121 122 123 124 125 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 121 def new_random rnd = [prand, prand, prand, prand].pack "N4" raw = mask 4, rnd create raw end |
.new_sha1(str, namespace) ⇒ Object
UUID generation using SHA1. Recommended over create_md5. Namespace object is another UUID, some of them are pre-defined below.
99 100 101 102 103 104 105 106 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 99 def new_sha1 str, namespace sha1 = Digest::SHA1.new sha1.update namespace.raw_bytes sha1.update str sum = sha1.digest raw = mask 5, sum[0..15] create raw end |
.pack(tl, tm, th, ch, cl, n) ⇒ Object
The ‘primitive constructor’ of this class Note UUID.pack(uuid.unpack) == uuid
203 204 205 206 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 203 def pack tl, tm, th, ch, cl, n raw = [tl, tm, th, ch, cl, n].pack "NnnCCa6" create raw end |
.parse(obj) ⇒ Object
A simple GUID parser: just ignores unknown characters and convert hexadecimal dump into 16-octet object.
194 195 196 197 198 199 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 194 def parse obj str = obj.to_s.sub %r/\Aurn:uuid:/, '' str.gsub! %r/[^0-9A-Fa-f]/, '' raw = [str[0..31]].pack 'H*' create raw end |
Instance Method Details
#<=>(other) ⇒ Object
UUIDs are comparable (don’t know what benefits are there, though).
293 294 295 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 293 def <=> other to_s <=> other.to_s end |
#==(other) ⇒ Object Also known as: eql?
Two UUIDs are said to be equal if and only if their (byte-order canonicalized) integer representations are equivallent. Refer RFC4122 for details.
281 282 283 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 281 def == other to_i == other.to_i end |
#clock ⇒ Object
The clock sequence of this UUID
239 240 241 242 243 244 245 246 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 239 def clock a = unpack ch = a[3] & 0b0001_1111 cl = a[4] c = cl c += ch << 8 c end |
#hash ⇒ Object
Two identical UUIDs should have same hash
287 288 289 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 287 def hash to_i end |
#new_md5(str) ⇒ Object
shortcut too
303 304 305 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 303 def new_md5 str self.class.new_md5 str, self end |
#new_sha1(str) ⇒ Object
shortcut
298 299 300 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 298 def new_sha1 str self.class.new_sha1 str, self end |
#node ⇒ Object Also known as: mac_address, ieee802
The IEEE 802 address in a hexadecimal format
249 250 251 252 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 249 def node m = unpack[5].unpack 'C*' '%02x%02x%02x%02x%02x%02x' % m end |
#raw_bytes ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 47 def raw_bytes ret = String.new tmp = @num 16.times do |i| x, y = tmp.divmod 256 ret << y tmp = x end ret.reverse! ret end |
#time ⇒ Object
The timestamp of this UUID. Throws RageError if that time exceeds UNIX time range
217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 217 def time a = unpack tl = a[0] tm = a[1] th = a[2] & 0x0FFF t = tl t += tm << 32 t += th << 48 t -= UNIXEpoch tv_sec = t / 10_000_000 t -= tv_sec * 10_000_000 tv_usec = t / 10 Time.at tv_sec, tv_usec end |
#to_int ⇒ Object Also known as: to_i
Convert into 128-bit unsigned integer Typically a Bignum instance, but can be a Fixnum.
273 274 275 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 273 def to_int @num end |
#to_s ⇒ Object Also known as: guid
Generate the string representation (a.k.a GUID) of this UUID
257 258 259 260 261 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 257 def to_s a = unpack a[-1] = mac_address "%08x-%04x-%04x-%02x%02x-%s" % a end |
#to_uri ⇒ Object Also known as: urn, inspect
Convert into a RFC4122-comforming URN representation
265 266 267 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 265 def to_uri "urn:uuid:" + self.to_s end |
#unpack ⇒ Object
The ‘primitive deconstructor’, or the dual to pack. Note UUID.pack(uuid.unpack) == uuid
211 212 213 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 211 def unpack raw_bytes.unpack "NnnCCa6" end |
#version ⇒ Object
The version of this UUID
233 234 235 236 |
# File 'lib/cast_off/compile/namespace/uuid.rb', line 233 def version v = unpack[2] & 0b1111_0000_0000_0000 v >> 12 end |