uuidtools 1.0.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,5 @@
1
+ == UUIDTools 2.0.0
2
+ * moved to its own module to avoid collisions
1
3
  == UUIDTools 1.0.7
2
4
  * fixed incompatible SecureRandom implementation
3
5
  == UUIDTools 1.0.6
data/Rakefile CHANGED
@@ -8,7 +8,6 @@ require 'rake/testtask'
8
8
  require 'rake/rdoctask'
9
9
  require 'rake/packagetask'
10
10
  require 'rake/gempackagetask'
11
- require 'rake/contrib/rubyforgepublisher'
12
11
  require 'spec/rake/spectask'
13
12
 
14
13
  require File.join(File.dirname(__FILE__), 'lib/uuidtools', 'version')
@@ -37,553 +37,554 @@ rescue LoadError
37
37
  require File.join(File.dirname(__FILE__), 'compat', 'securerandom')
38
38
  end
39
39
 
40
- #= uuidtools.rb
41
- #
42
- # UUIDTools was designed to be a simple library for generating any
43
- # of the various types of UUIDs. It conforms to RFC 4122 whenever
44
- # possible.
45
- #
46
- #== Example
47
- # UUID.md5_create(UUID_DNS_NAMESPACE, "www.widgets.com")
48
- # => #<UUID:0x287576 UUID:3d813cbb-47fb-32ba-91df-831e1593ac29>
49
- # UUID.sha1_create(UUID_DNS_NAMESPACE, "www.widgets.com")
50
- # => #<UUID:0x2a0116 UUID:21f7f8de-8051-5b89-8680-0195ef798b6a>
51
- # UUID.timestamp_create
52
- # => #<UUID:0x2adfdc UUID:64a5189c-25b3-11da-a97b-00c04fd430c8>
53
- # UUID.random_create
54
- # => #<UUID:0x19013a UUID:984265dc-4200-4f02-ae70-fe4f48964159>
55
- class UUID
56
- include Comparable
57
-
58
- @@last_timestamp = nil
59
- @@last_node_id = nil
60
- @@last_clock_sequence = nil
61
- @@state_file = nil
62
- @@mutex = Mutex.new
63
-
64
- def initialize(time_low, time_mid, time_hi_and_version,
65
- clock_seq_hi_and_reserved, clock_seq_low, nodes)
66
- unless time_low >= 0 && time_low < 4294967296
67
- raise ArgumentError,
68
- "Expected unsigned 32-bit number for time_low, got #{time_low}."
69
- end
70
- unless time_mid >= 0 && time_mid < 65536
71
- raise ArgumentError,
72
- "Expected unsigned 16-bit number for time_mid, got #{time_mid}."
73
- end
74
- unless time_hi_and_version >= 0 && time_hi_and_version < 65536
75
- raise ArgumentError,
76
- "Expected unsigned 16-bit number for time_hi_and_version, " +
77
- "got #{time_hi_and_version}."
78
- end
79
- unless clock_seq_hi_and_reserved >= 0 && clock_seq_hi_and_reserved < 256
80
- raise ArgumentError,
81
- "Expected unsigned 8-bit number for clock_seq_hi_and_reserved, " +
82
- "got #{clock_seq_hi_and_reserved}."
83
- end
84
- unless clock_seq_low >= 0 && clock_seq_low < 256
85
- raise ArgumentError,
86
- "Expected unsigned 8-bit number for clock_seq_low, " +
87
- "got #{clock_seq_low}."
88
- end
89
- unless nodes.kind_of?(Enumerable)
90
- raise TypeError,
91
- "Expected Enumerable, got #{nodes.class.name}."
92
- end
93
- unless nodes.size == 6
94
- raise ArgumentError,
95
- "Expected nodes to have size of 6."
96
- end
97
- for node in nodes
98
- unless node >= 0 && node < 256
40
+ module UUIDTools
41
+ #= uuidtools.rb
42
+ #
43
+ # UUIDTools was designed to be a simple library for generating any
44
+ # of the various types of UUIDs. It conforms to RFC 4122 whenever
45
+ # possible.
46
+ #
47
+ #== Example
48
+ # UUID.md5_create(UUID_DNS_NAMESPACE, "www.widgets.com")
49
+ # => #<UUID:0x287576 UUID:3d813cbb-47fb-32ba-91df-831e1593ac29>
50
+ # UUID.sha1_create(UUID_DNS_NAMESPACE, "www.widgets.com")
51
+ # => #<UUID:0x2a0116 UUID:21f7f8de-8051-5b89-8680-0195ef798b6a>
52
+ # UUID.timestamp_create
53
+ # => #<UUID:0x2adfdc UUID:64a5189c-25b3-11da-a97b-00c04fd430c8>
54
+ # UUID.random_create
55
+ # => #<UUID:0x19013a UUID:984265dc-4200-4f02-ae70-fe4f48964159>
56
+ class UUID
57
+ include Comparable
58
+
59
+ @@last_timestamp = nil
60
+ @@last_node_id = nil
61
+ @@last_clock_sequence = nil
62
+ @@state_file = nil
63
+ @@mutex = Mutex.new
64
+
65
+ def initialize(time_low, time_mid, time_hi_and_version,
66
+ clock_seq_hi_and_reserved, clock_seq_low, nodes)
67
+ unless time_low >= 0 && time_low < 4294967296
99
68
  raise ArgumentError,
100
- "Expected unsigned 8-bit number for each node, " +
101
- "got #{node}."
69
+ "Expected unsigned 32-bit number for time_low, got #{time_low}."
102
70
  end
103
- end
104
- @time_low = time_low
105
- @time_mid = time_mid
106
- @time_hi_and_version = time_hi_and_version
107
- @clock_seq_hi_and_reserved = clock_seq_hi_and_reserved
108
- @clock_seq_low = clock_seq_low
109
- @nodes = nodes
110
- end
111
-
112
- attr_accessor :time_low
113
- attr_accessor :time_mid
114
- attr_accessor :time_hi_and_version
115
- attr_accessor :clock_seq_hi_and_reserved
116
- attr_accessor :clock_seq_low
117
- attr_accessor :nodes
118
-
119
- # Parses a UUID from a string.
120
- def self.parse(uuid_string)
121
- unless uuid_string.kind_of? String
122
- raise TypeError,
123
- "Expected String, got #{uuid_string.class.name} instead."
124
- end
125
- uuid_components = uuid_string.downcase.scan(
126
- Regexp.new("^([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-" +
127
- "([0-9a-f]{2})([0-9a-f]{2})-([0-9a-f]{12})$")).first
128
- raise ArgumentError, "Invalid UUID format." if uuid_components.nil?
129
- time_low = uuid_components[0].to_i(16)
130
- time_mid = uuid_components[1].to_i(16)
131
- time_hi_and_version = uuid_components[2].to_i(16)
132
- clock_seq_hi_and_reserved = uuid_components[3].to_i(16)
133
- clock_seq_low = uuid_components[4].to_i(16)
134
- nodes = []
135
- for i in 0..5
136
- nodes << uuid_components[5][(i * 2)..(i * 2) + 1].to_i(16)
137
- end
138
- return self.new(time_low, time_mid, time_hi_and_version,
139
- clock_seq_hi_and_reserved, clock_seq_low, nodes)
140
- end
141
-
142
- # Parses a UUID from a raw byte string.
143
- def self.parse_raw(raw_string)
144
- unless raw_string.kind_of? String
145
- raise TypeError,
146
- "Expected String, got #{raw_string.class.name} instead."
147
- end
148
- integer = self.convert_byte_string_to_int(raw_string)
149
-
150
- time_low = (integer >> 96) & 0xFFFFFFFF
151
- time_mid = (integer >> 80) & 0xFFFF
152
- time_hi_and_version = (integer >> 64) & 0xFFFF
153
- clock_seq_hi_and_reserved = (integer >> 56) & 0xFF
154
- clock_seq_low = (integer >> 48) & 0xFF
155
- nodes = []
156
- for i in 0..5
157
- nodes << ((integer >> (40 - (i * 8))) & 0xFF)
158
- end
159
- return self.new(time_low, time_mid, time_hi_and_version,
160
- clock_seq_hi_and_reserved, clock_seq_low, nodes)
161
- end
162
-
163
- # Creates a UUID from a random value.
164
- def self.random_create()
165
- new_uuid = self.parse_raw(SecureRandom.random_bytes(16))
166
- new_uuid.time_hi_and_version &= 0x0FFF
167
- new_uuid.time_hi_and_version |= (4 << 12)
168
- new_uuid.clock_seq_hi_and_reserved &= 0x3F
169
- new_uuid.clock_seq_hi_and_reserved |= 0x80
170
- return new_uuid
171
- end
172
-
173
- # Creates a UUID from a timestamp.
174
- def self.timestamp_create(timestamp=nil)
175
- # We need a lock here to prevent two threads from ever
176
- # getting the same timestamp.
177
- @@mutex.synchronize do
178
- # Always use GMT to generate UUIDs.
179
- if timestamp.nil?
180
- gmt_timestamp = Time.now.gmtime
181
- else
182
- gmt_timestamp = timestamp.gmtime
71
+ unless time_mid >= 0 && time_mid < 65536
72
+ raise ArgumentError,
73
+ "Expected unsigned 16-bit number for time_mid, got #{time_mid}."
183
74
  end
184
- # Convert to 100 nanosecond blocks
185
- gmt_timestamp_100_nanoseconds = (gmt_timestamp.tv_sec * 10000000) +
186
- (gmt_timestamp.tv_usec * 10) + 0x01B21DD213814000
187
- mac_address = self.mac_address
188
- node_id = 0
189
- if mac_address != nil
190
- nodes = mac_address.split(":").collect do |octet|
191
- octet.to_i(16)
192
- end
193
- else
194
- nodes = SecureRandom.random_bytes(6).split("").map do |chr|
195
- # Ruby 1.9 / Ruby 1.8
196
- chr.respond_to?(:ord) ? chr.ord : chr.sum(8)
197
- end
198
- nodes[0] |= 0b00000001
75
+ unless time_hi_and_version >= 0 && time_hi_and_version < 65536
76
+ raise ArgumentError,
77
+ "Expected unsigned 16-bit number for time_hi_and_version, " +
78
+ "got #{time_hi_and_version}."
199
79
  end
200
- for i in 0..5
201
- node_id += (nodes[i] << (40 - (i * 8)))
80
+ unless clock_seq_hi_and_reserved >= 0 && clock_seq_hi_and_reserved < 256
81
+ raise ArgumentError,
82
+ "Expected unsigned 8-bit number for clock_seq_hi_and_reserved, " +
83
+ "got #{clock_seq_hi_and_reserved}."
202
84
  end
203
- clock_sequence = @@last_clock_sequence
204
- if clock_sequence.nil?
205
- clock_sequence = self.convert_byte_string_to_int(
206
- SecureRandom.random_bytes(16)
207
- )
85
+ unless clock_seq_low >= 0 && clock_seq_low < 256
86
+ raise ArgumentError,
87
+ "Expected unsigned 8-bit number for clock_seq_low, " +
88
+ "got #{clock_seq_low}."
208
89
  end
209
- if @@last_node_id != nil && @@last_node_id != node_id
210
- # The node id has changed. Change the clock id.
211
- clock_sequence = self.convert_byte_string_to_int(
212
- SecureRandom.random_bytes(16)
213
- )
214
- elsif @@last_timestamp != nil &&
215
- gmt_timestamp_100_nanoseconds <= @@last_timestamp
216
- clock_sequence = clock_sequence + 1
90
+ unless nodes.kind_of?(Enumerable)
91
+ raise TypeError,
92
+ "Expected Enumerable, got #{nodes.class.name}."
93
+ end
94
+ unless nodes.size == 6
95
+ raise ArgumentError,
96
+ "Expected nodes to have size of 6."
217
97
  end
218
- @@last_timestamp = gmt_timestamp_100_nanoseconds
219
- @@last_node_id = node_id
220
- @@last_clock_sequence = clock_sequence
221
-
222
- time_low = gmt_timestamp_100_nanoseconds & 0xFFFFFFFF
223
- time_mid = ((gmt_timestamp_100_nanoseconds >> 32) & 0xFFFF)
224
- time_hi_and_version = ((gmt_timestamp_100_nanoseconds >> 48) & 0x0FFF)
225
- time_hi_and_version |= (1 << 12)
226
- clock_seq_low = clock_sequence & 0xFF;
227
- clock_seq_hi_and_reserved = (clock_sequence & 0x3F00) >> 8
228
- clock_seq_hi_and_reserved |= 0x80
98
+ for node in nodes
99
+ unless node >= 0 && node < 256
100
+ raise ArgumentError,
101
+ "Expected unsigned 8-bit number for each node, " +
102
+ "got #{node}."
103
+ end
104
+ end
105
+ @time_low = time_low
106
+ @time_mid = time_mid
107
+ @time_hi_and_version = time_hi_and_version
108
+ @clock_seq_hi_and_reserved = clock_seq_hi_and_reserved
109
+ @clock_seq_low = clock_seq_low
110
+ @nodes = nodes
111
+ end
229
112
 
113
+ attr_accessor :time_low
114
+ attr_accessor :time_mid
115
+ attr_accessor :time_hi_and_version
116
+ attr_accessor :clock_seq_hi_and_reserved
117
+ attr_accessor :clock_seq_low
118
+ attr_accessor :nodes
119
+
120
+ # Parses a UUID from a string.
121
+ def self.parse(uuid_string)
122
+ unless uuid_string.kind_of? String
123
+ raise TypeError,
124
+ "Expected String, got #{uuid_string.class.name} instead."
125
+ end
126
+ uuid_components = uuid_string.downcase.scan(
127
+ Regexp.new("^([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-" +
128
+ "([0-9a-f]{2})([0-9a-f]{2})-([0-9a-f]{12})$")).first
129
+ raise ArgumentError, "Invalid UUID format." if uuid_components.nil?
130
+ time_low = uuid_components[0].to_i(16)
131
+ time_mid = uuid_components[1].to_i(16)
132
+ time_hi_and_version = uuid_components[2].to_i(16)
133
+ clock_seq_hi_and_reserved = uuid_components[3].to_i(16)
134
+ clock_seq_low = uuid_components[4].to_i(16)
135
+ nodes = []
136
+ for i in 0..5
137
+ nodes << uuid_components[5][(i * 2)..(i * 2) + 1].to_i(16)
138
+ end
230
139
  return self.new(time_low, time_mid, time_hi_and_version,
231
140
  clock_seq_hi_and_reserved, clock_seq_low, nodes)
232
141
  end
233
- end
234
142
 
235
- # Creates a UUID using the MD5 hash. (Version 3)
236
- def self.md5_create(namespace, name)
237
- return self.create_from_hash(Digest::MD5, namespace, name)
238
- end
143
+ # Parses a UUID from a raw byte string.
144
+ def self.parse_raw(raw_string)
145
+ unless raw_string.kind_of? String
146
+ raise TypeError,
147
+ "Expected String, got #{raw_string.class.name} instead."
148
+ end
149
+ integer = self.convert_byte_string_to_int(raw_string)
150
+
151
+ time_low = (integer >> 96) & 0xFFFFFFFF
152
+ time_mid = (integer >> 80) & 0xFFFF
153
+ time_hi_and_version = (integer >> 64) & 0xFFFF
154
+ clock_seq_hi_and_reserved = (integer >> 56) & 0xFF
155
+ clock_seq_low = (integer >> 48) & 0xFF
156
+ nodes = []
157
+ for i in 0..5
158
+ nodes << ((integer >> (40 - (i * 8))) & 0xFF)
159
+ end
160
+ return self.new(time_low, time_mid, time_hi_and_version,
161
+ clock_seq_hi_and_reserved, clock_seq_low, nodes)
162
+ end
239
163
 
240
- # Creates a UUID using the SHA1 hash. (Version 5)
241
- def self.sha1_create(namespace, name)
242
- return self.create_from_hash(Digest::SHA1, namespace, name)
243
- end
164
+ # Creates a UUID from a random value.
165
+ def self.random_create()
166
+ new_uuid = self.parse_raw(SecureRandom.random_bytes(16))
167
+ new_uuid.time_hi_and_version &= 0x0FFF
168
+ new_uuid.time_hi_and_version |= (4 << 12)
169
+ new_uuid.clock_seq_hi_and_reserved &= 0x3F
170
+ new_uuid.clock_seq_hi_and_reserved |= 0x80
171
+ return new_uuid
172
+ end
244
173
 
245
- # This method applies only to version 1 UUIDs.
246
- # Checks if the node ID was generated from a random number
247
- # or from an IEEE 802 address (MAC address).
248
- # Always returns false for UUIDs that aren't version 1.
249
- # This should not be confused with version 4 UUIDs where
250
- # more than just the node id is random.
251
- def random_node_id?
252
- return false if self.version != 1
253
- return ((self.nodes.first & 0x01) == 1)
254
- end
174
+ # Creates a UUID from a timestamp.
175
+ def self.timestamp_create(timestamp=nil)
176
+ # We need a lock here to prevent two threads from ever
177
+ # getting the same timestamp.
178
+ @@mutex.synchronize do
179
+ # Always use GMT to generate UUIDs.
180
+ if timestamp.nil?
181
+ gmt_timestamp = Time.now.gmtime
182
+ else
183
+ gmt_timestamp = timestamp.gmtime
184
+ end
185
+ # Convert to 100 nanosecond blocks
186
+ gmt_timestamp_100_nanoseconds = (gmt_timestamp.tv_sec * 10000000) +
187
+ (gmt_timestamp.tv_usec * 10) + 0x01B21DD213814000
188
+ mac_address = self.mac_address
189
+ node_id = 0
190
+ if mac_address != nil
191
+ nodes = mac_address.split(":").collect do |octet|
192
+ octet.to_i(16)
193
+ end
194
+ else
195
+ nodes = []
196
+ SecureRandom.random_bytes(6).each_byte { |chr| nodes << chr }
197
+ nodes[0] |= 0b00000001
198
+ end
199
+ for i in 0..5
200
+ node_id += (nodes[i] << (40 - (i * 8)))
201
+ end
202
+ clock_sequence = @@last_clock_sequence
203
+ if clock_sequence.nil?
204
+ clock_sequence = self.convert_byte_string_to_int(
205
+ SecureRandom.random_bytes(16)
206
+ )
207
+ end
208
+ if @@last_node_id != nil && @@last_node_id != node_id
209
+ # The node id has changed. Change the clock id.
210
+ clock_sequence = self.convert_byte_string_to_int(
211
+ SecureRandom.random_bytes(16)
212
+ )
213
+ elsif @@last_timestamp != nil &&
214
+ gmt_timestamp_100_nanoseconds <= @@last_timestamp
215
+ clock_sequence = clock_sequence + 1
216
+ end
217
+ @@last_timestamp = gmt_timestamp_100_nanoseconds
218
+ @@last_node_id = node_id
219
+ @@last_clock_sequence = clock_sequence
220
+
221
+ time_low = gmt_timestamp_100_nanoseconds & 0xFFFFFFFF
222
+ time_mid = ((gmt_timestamp_100_nanoseconds >> 32) & 0xFFFF)
223
+ time_hi_and_version = ((gmt_timestamp_100_nanoseconds >> 48) & 0x0FFF)
224
+ time_hi_and_version |= (1 << 12)
225
+ clock_seq_low = clock_sequence & 0xFF;
226
+ clock_seq_hi_and_reserved = (clock_sequence & 0x3F00) >> 8
227
+ clock_seq_hi_and_reserved |= 0x80
228
+
229
+ return self.new(time_low, time_mid, time_hi_and_version,
230
+ clock_seq_hi_and_reserved, clock_seq_low, nodes)
231
+ end
232
+ end
255
233
 
256
- # Returns true if this UUID is the
257
- # nil UUID (00000000-0000-0000-0000-000000000000).
258
- def nil_uuid?
259
- return false if self.time_low != 0
260
- return false if self.time_mid != 0
261
- return false if self.time_hi_and_version != 0
262
- return false if self.clock_seq_hi_and_reserved != 0
263
- return false if self.clock_seq_low != 0
264
- self.nodes.each do |node|
265
- return false if node != 0
234
+ # Creates a UUID using the MD5 hash. (Version 3)
235
+ def self.md5_create(namespace, name)
236
+ return self.create_from_hash(Digest::MD5, namespace, name)
266
237
  end
267
- return true
268
- end
269
238
 
270
- # Returns the UUID version type.
271
- # Possible values:
272
- # 1 - Time-based with unique or random host identifier
273
- # 2 - DCE Security version (with POSIX UIDs)
274
- # 3 - Name-based (MD5 hash)
275
- # 4 - Random
276
- # 5 - Name-based (SHA-1 hash)
277
- def version
278
- return (time_hi_and_version >> 12)
279
- end
239
+ # Creates a UUID using the SHA1 hash. (Version 5)
240
+ def self.sha1_create(namespace, name)
241
+ return self.create_from_hash(Digest::SHA1, namespace, name)
242
+ end
280
243
 
281
- # Returns the UUID variant.
282
- # Possible values:
283
- # 0b000 - Reserved, NCS backward compatibility.
284
- # 0b100 - The variant specified in this document.
285
- # 0b110 - Reserved, Microsoft Corporation backward compatibility.
286
- # 0b111 - Reserved for future definition.
287
- def variant
288
- variant_raw = (clock_seq_hi_and_reserved >> 5)
289
- result = nil
290
- if (variant_raw >> 2) == 0
291
- result = 0x000
292
- elsif (variant_raw >> 1) == 2
293
- result = 0x100
294
- else
295
- result = variant_raw
244
+ # This method applies only to version 1 UUIDs.
245
+ # Checks if the node ID was generated from a random number
246
+ # or from an IEEE 802 address (MAC address).
247
+ # Always returns false for UUIDs that aren't version 1.
248
+ # This should not be confused with version 4 UUIDs where
249
+ # more than just the node id is random.
250
+ def random_node_id?
251
+ return false if self.version != 1
252
+ return ((self.nodes.first & 0x01) == 1)
296
253
  end
297
- return (result >> 6)
298
- end
299
254
 
300
- # Returns true if this UUID is valid.
301
- def valid?
302
- if [0b000, 0b100, 0b110, 0b111].include?(self.variant) &&
303
- (1..5).include?(self.version)
255
+ # Returns true if this UUID is the
256
+ # nil UUID (00000000-0000-0000-0000-000000000000).
257
+ def nil_uuid?
258
+ return false if self.time_low != 0
259
+ return false if self.time_mid != 0
260
+ return false if self.time_hi_and_version != 0
261
+ return false if self.clock_seq_hi_and_reserved != 0
262
+ return false if self.clock_seq_low != 0
263
+ self.nodes.each do |node|
264
+ return false if node != 0
265
+ end
304
266
  return true
305
- else
306
- return false
307
267
  end
308
- end
309
268
 
310
- # Returns the IEEE 802 address used to generate this UUID or
311
- # nil if a MAC address was not used.
312
- def mac_address
313
- return nil if self.version != 1
314
- return nil if self.random_node_id?
315
- return (self.nodes.collect do |node|
316
- sprintf("%2.2x", node)
317
- end).join(":")
318
- end
319
-
320
- # Returns the timestamp used to generate this UUID
321
- def timestamp
322
- return nil if self.version != 1
323
- gmt_timestamp_100_nanoseconds = 0
324
- gmt_timestamp_100_nanoseconds +=
325
- ((self.time_hi_and_version & 0x0FFF) << 48)
326
- gmt_timestamp_100_nanoseconds += (self.time_mid << 32)
327
- gmt_timestamp_100_nanoseconds += self.time_low
328
- return Time.at(
329
- (gmt_timestamp_100_nanoseconds - 0x01B21DD213814000) / 10000000.0)
330
- end
269
+ # Returns the UUID version type.
270
+ # Possible values:
271
+ # 1 - Time-based with unique or random host identifier
272
+ # 2 - DCE Security version (with POSIX UIDs)
273
+ # 3 - Name-based (MD5 hash)
274
+ # 4 - Random
275
+ # 5 - Name-based (SHA-1 hash)
276
+ def version
277
+ return (time_hi_and_version >> 12)
278
+ end
331
279
 
332
- # Compares two UUIDs lexically
333
- def <=>(other_uuid)
334
- check = self.time_low <=> other_uuid.time_low
335
- return check if check != 0
336
- check = self.time_mid <=> other_uuid.time_mid
337
- return check if check != 0
338
- check = self.time_hi_and_version <=> other_uuid.time_hi_and_version
339
- return check if check != 0
340
- check = self.clock_seq_hi_and_reserved <=>
341
- other_uuid.clock_seq_hi_and_reserved
342
- return check if check != 0
343
- check = self.clock_seq_low <=> other_uuid.clock_seq_low
344
- return check if check != 0
345
- for i in 0..5
346
- if (self.nodes[i] < other_uuid.nodes[i])
347
- return -1
280
+ # Returns the UUID variant.
281
+ # Possible values:
282
+ # 0b000 - Reserved, NCS backward compatibility.
283
+ # 0b100 - The variant specified in this document.
284
+ # 0b110 - Reserved, Microsoft Corporation backward compatibility.
285
+ # 0b111 - Reserved for future definition.
286
+ def variant
287
+ variant_raw = (clock_seq_hi_and_reserved >> 5)
288
+ result = nil
289
+ if (variant_raw >> 2) == 0
290
+ result = 0x000
291
+ elsif (variant_raw >> 1) == 2
292
+ result = 0x100
293
+ else
294
+ result = variant_raw
348
295
  end
349
- if (self.nodes[i] > other_uuid.nodes[i])
350
- return 1
296
+ return (result >> 6)
297
+ end
298
+
299
+ # Returns true if this UUID is valid.
300
+ def valid?
301
+ if [0b000, 0b100, 0b110, 0b111].include?(self.variant) &&
302
+ (1..5).include?(self.version)
303
+ return true
304
+ else
305
+ return false
351
306
  end
352
307
  end
353
- return 0
354
- end
355
308
 
356
- # Returns a representation of the object's state
357
- def inspect
358
- return "#<UUID:0x#{self.object_id.to_s(16)} UUID:#{self.to_s}>"
359
- end
309
+ # Returns the IEEE 802 address used to generate this UUID or
310
+ # nil if a MAC address was not used.
311
+ def mac_address
312
+ return nil if self.version != 1
313
+ return nil if self.random_node_id?
314
+ return (self.nodes.collect do |node|
315
+ sprintf("%2.2x", node)
316
+ end).join(":")
317
+ end
360
318
 
361
- # Returns the hex digest of the UUID object.
362
- def hexdigest
363
- return self.to_i.to_s(16).rjust(32, "0")
364
- end
319
+ # Returns the timestamp used to generate this UUID
320
+ def timestamp
321
+ return nil if self.version != 1
322
+ gmt_timestamp_100_nanoseconds = 0
323
+ gmt_timestamp_100_nanoseconds +=
324
+ ((self.time_hi_and_version & 0x0FFF) << 48)
325
+ gmt_timestamp_100_nanoseconds += (self.time_mid << 32)
326
+ gmt_timestamp_100_nanoseconds += self.time_low
327
+ return Time.at(
328
+ (gmt_timestamp_100_nanoseconds - 0x01B21DD213814000) / 10000000.0)
329
+ end
365
330
 
366
- # Returns the raw bytes that represent this UUID.
367
- def raw
368
- return self.class.convert_int_to_byte_string(self.to_i, 16)
369
- end
331
+ # Compares two UUIDs lexically
332
+ def <=>(other_uuid)
333
+ check = self.time_low <=> other_uuid.time_low
334
+ return check if check != 0
335
+ check = self.time_mid <=> other_uuid.time_mid
336
+ return check if check != 0
337
+ check = self.time_hi_and_version <=> other_uuid.time_hi_and_version
338
+ return check if check != 0
339
+ check = self.clock_seq_hi_and_reserved <=>
340
+ other_uuid.clock_seq_hi_and_reserved
341
+ return check if check != 0
342
+ check = self.clock_seq_low <=> other_uuid.clock_seq_low
343
+ return check if check != 0
344
+ for i in 0..5
345
+ if (self.nodes[i] < other_uuid.nodes[i])
346
+ return -1
347
+ end
348
+ if (self.nodes[i] > other_uuid.nodes[i])
349
+ return 1
350
+ end
351
+ end
352
+ return 0
353
+ end
370
354
 
371
- # Returns a string representation for this UUID.
372
- def to_s
373
- result = sprintf("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", @time_low, @time_mid,
374
- @time_hi_and_version, @clock_seq_hi_and_reserved, @clock_seq_low);
375
- for i in 0..5
376
- result << sprintf("%2.2x", @nodes[i])
355
+ # Returns a representation of the object's state
356
+ def inspect
357
+ return "#<UUID:0x#{self.object_id.to_s(16)} UUID:#{self.to_s}>"
377
358
  end
378
- return result.downcase
379
- end
380
- alias_method :to_str, :to_s
381
-
382
- # Returns an integer representation for this UUID.
383
- def to_i
384
- @integer ||= (begin
385
- bytes = (time_low << 96) + (time_mid << 80) +
386
- (time_hi_and_version << 64) + (clock_seq_hi_and_reserved << 56) +
387
- (clock_seq_low << 48)
359
+
360
+ # Returns the hex digest of the UUID object.
361
+ def hexdigest
362
+ return self.to_i.to_s(16).rjust(32, "0")
363
+ end
364
+
365
+ # Returns the raw bytes that represent this UUID.
366
+ def raw
367
+ return self.class.convert_int_to_byte_string(self.to_i, 16)
368
+ end
369
+
370
+ # Returns a string representation for this UUID.
371
+ def to_s
372
+ result = sprintf("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", @time_low, @time_mid,
373
+ @time_hi_and_version, @clock_seq_hi_and_reserved, @clock_seq_low);
388
374
  for i in 0..5
389
- bytes += (nodes[i] << (40 - (i * 8)))
375
+ result << sprintf("%2.2x", @nodes[i])
390
376
  end
391
- bytes
392
- end)
393
- end
377
+ return result.downcase
378
+ end
379
+ alias_method :to_str, :to_s
380
+
381
+ # Returns an integer representation for this UUID.
382
+ def to_i
383
+ @integer ||= (begin
384
+ bytes = (time_low << 96) + (time_mid << 80) +
385
+ (time_hi_and_version << 64) + (clock_seq_hi_and_reserved << 56) +
386
+ (clock_seq_low << 48)
387
+ for i in 0..5
388
+ bytes += (nodes[i] << (40 - (i * 8)))
389
+ end
390
+ bytes
391
+ end)
392
+ end
394
393
 
395
- # Returns a URI string for this UUID.
396
- def to_uri
397
- return "urn:uuid:#{self.to_s}"
398
- end
394
+ # Returns a URI string for this UUID.
395
+ def to_uri
396
+ return "urn:uuid:#{self.to_s}"
397
+ end
399
398
 
400
- # Returns an integer hash value.
401
- def hash
402
- @hash ||= self.to_i % 0x3fffffff
403
- end
399
+ # Returns an integer hash value.
400
+ def hash
401
+ @hash ||= self.to_i % 0x3fffffff
402
+ end
404
403
 
405
- # Returns true if this UUID is exactly equal to the other UUID.
406
- def eql?(other)
407
- return self == other
408
- end
404
+ # Returns true if this UUID is exactly equal to the other UUID.
405
+ def eql?(other)
406
+ return self == other
407
+ end
409
408
 
410
- # Returns the MAC address of the current computer's network card.
411
- # Returns nil if a MAC address could not be found.
412
- def self.mac_address #:nodoc:
413
- if !defined?(@@mac_address)
414
- require 'rbconfig'
415
- os_platform = Config::CONFIG['target_os']
416
- if os_platform =~ /win/ && !(os_platform =~ /darwin/)
417
- script_in_path = true
418
- else
419
- script_in_path = Kernel.system("which ifconfig 2>&1 > /dev/null")
420
- end
421
- if os_platform =~ /solaris/
422
- begin
423
- ifconfig_output =
424
- (script_in_path ? `ifconfig -a` : `/sbin/ifconfig -a`)
425
- ip_addresses = ifconfig_output.scan(
426
- /inet\s?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/)
427
- ip = ip_addresses.find {|addr| addr[0] != '127.0.0.1'}[0]
428
- @@mac_address = `/usr/sbin/arp #{ip}`.split(' ')[3]
429
- rescue Exception
409
+ # Returns the MAC address of the current computer's network card.
410
+ # Returns nil if a MAC address could not be found.
411
+ def self.mac_address #:nodoc:
412
+ if !defined?(@@mac_address)
413
+ require 'rbconfig'
414
+ os_platform = Config::CONFIG['target_os']
415
+ if (os_platform =~ /win/ && !(os_platform =~ /darwin/)) ||
416
+ os_platform =~ /w32/
417
+ script_in_path = true
418
+ else
419
+ script_in_path = Kernel.system("which ifconfig 2>&1 > /dev/null")
430
420
  end
431
- if @@mac_address == "" || @@mac_address == nil
421
+ if os_platform =~ /solaris/
432
422
  begin
433
423
  ifconfig_output =
434
- (script_in_path ?
435
- `ifconfig -a` : `/sbin/ifconfig -a`).split(' ')
436
- index = ifconfig_output.index("inet") + 1
437
- ip = ifconfig_output[index]
438
- @@mac_address = `arp #{ip}`.split(' ')[3]
424
+ (script_in_path ? `ifconfig -a` : `/sbin/ifconfig -a`)
425
+ ip_addresses = ifconfig_output.scan(
426
+ /inet\s?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/)
427
+ ip = ip_addresses.find {|addr| addr[0] != '127.0.0.1'}[0]
428
+ @@mac_address = `/usr/sbin/arp #{ip}`.split(' ')[3]
439
429
  rescue Exception
440
430
  end
441
- end
442
- elsif os_platform =~ /win/ && !(os_platform =~ /darwin/)
443
- begin
444
- ifconfig_output = `ipconfig /all`
445
- mac_addresses = ifconfig_output.scan(
446
- Regexp.new("(#{(["[0-9a-fA-F]{2}"] * 6).join("-")})"))
447
- if mac_addresses.size > 0
448
- @@mac_address = mac_addresses.first.first.downcase.gsub(/-/, ":")
431
+ if @@mac_address == "" || @@mac_address == nil
432
+ begin
433
+ ifconfig_output =
434
+ (script_in_path ?
435
+ `ifconfig -a` : `/sbin/ifconfig -a`).split(' ')
436
+ index = ifconfig_output.index("inet") + 1
437
+ ip = ifconfig_output[index]
438
+ @@mac_address = `arp #{ip}`.split(' ')[3]
439
+ rescue Exception
440
+ end
449
441
  end
450
- rescue
451
- end
452
- else
453
- begin
454
- mac_addresses = []
455
- if os_platform =~ /netbsd/
456
- ifconfig_output =
457
- (script_in_path ? `ifconfig -a 2>&1` : `/sbin/ifconfig -a 2>&1`)
458
- mac_addresses = ifconfig_output.scan(
459
- Regexp.new("address\: (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
460
- elsif os_platform =~ /openbsd/
461
- ifconfig_output = `/sbin/ifconfig -a 2>&1`
462
- ifconfig_output =
463
- (script_in_path ? `ifconfig -a 2>&1` : `/sbin/ifconfig -a 2>&1`)
464
- mac_addresses = ifconfig_output.scan(
465
- Regexp.new("addr (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
466
- elsif File.exists?('/sbin/ifconfig')
467
- ifconfig_output =
468
- (script_in_path ? `ifconfig 2>&1` : `/sbin/ifconfig 2>&1`)
442
+ elsif os_platform =~ /win/ && !(os_platform =~ /darwin/)
443
+ begin
444
+ ifconfig_output = `ipconfig /all`
469
445
  mac_addresses = ifconfig_output.scan(
470
- Regexp.new("ether (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
471
- if mac_addresses.size == 0
446
+ Regexp.new("(#{(["[0-9a-fA-F]{2}"] * 6).join("-")})"))
447
+ if mac_addresses.size > 0
448
+ @@mac_address = mac_addresses.first.first.downcase.gsub(/-/, ":")
449
+ end
450
+ rescue
451
+ end
452
+ else
453
+ begin
454
+ mac_addresses = []
455
+ if os_platform =~ /netbsd/
472
456
  ifconfig_output =
473
- (script_in_path ?
474
- `ifconfig -a 2>&1` : `/sbin/ifconfig -a 2>&1`)
457
+ (script_in_path ? `ifconfig -a 2>&1` : `/sbin/ifconfig -a 2>&1`)
475
458
  mac_addresses = ifconfig_output.scan(
476
- Regexp.new("ether (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
477
- end
478
- if mac_addresses.size == 0
459
+ Regexp.new("address\: (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
460
+ elsif os_platform =~ /openbsd/
461
+ ifconfig_output = `/sbin/ifconfig -a 2>&1`
479
462
  ifconfig_output =
480
- (script_in_path ?
481
- `ifconfig | grep HWaddr | cut -c39- 2>&1` :
482
- `/sbin/ifconfig | grep HWaddr | cut -c39- 2>&1`)
463
+ (script_in_path ? `ifconfig -a 2>&1` : `/sbin/ifconfig -a 2>&1`)
483
464
  mac_addresses = ifconfig_output.scan(
484
- Regexp.new("(#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
485
- end
486
- else
487
- ifconfig_output =
488
- (script_in_path ? `ifconfig 2>&1` : `/sbin/ifconfig 2>&1`)
489
- mac_addresses = ifconfig_output.scan(
490
- Regexp.new("ether (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
491
- if mac_addresses.size == 0
465
+ Regexp.new("addr (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
466
+ elsif File.exists?('/sbin/ifconfig')
492
467
  ifconfig_output =
493
- (script_in_path ?
494
- `ifconfig -a 2>&1` : `/sbin/ifconfig -a 2>&1`)
468
+ (script_in_path ? `ifconfig 2>&1` : `/sbin/ifconfig 2>&1`)
495
469
  mac_addresses = ifconfig_output.scan(
496
470
  Regexp.new("ether (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
497
- end
498
- if mac_addresses.size == 0
471
+ if mac_addresses.size == 0
472
+ ifconfig_output =
473
+ (script_in_path ?
474
+ `ifconfig -a 2>&1` : `/sbin/ifconfig -a 2>&1`)
475
+ mac_addresses = ifconfig_output.scan(
476
+ Regexp.new("ether (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
477
+ end
478
+ if mac_addresses.size == 0
479
+ ifconfig_output =
480
+ (script_in_path ?
481
+ `ifconfig | grep HWaddr | cut -c39- 2>&1` :
482
+ `/sbin/ifconfig | grep HWaddr | cut -c39- 2>&1`)
483
+ mac_addresses = ifconfig_output.scan(
484
+ Regexp.new("(#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
485
+ end
486
+ else
499
487
  ifconfig_output =
500
- (script_in_path ?
501
- `ifconfig | grep HWaddr | cut -c39- 2>&1` :
502
- `/sbin/ifconfig | grep HWaddr | cut -c39- 2>&1`)
488
+ (script_in_path ? `ifconfig 2>&1` : `/sbin/ifconfig 2>&1`)
503
489
  mac_addresses = ifconfig_output.scan(
504
- Regexp.new("(#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
490
+ Regexp.new("ether (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
491
+ if mac_addresses.size == 0
492
+ ifconfig_output =
493
+ (script_in_path ?
494
+ `ifconfig -a 2>&1` : `/sbin/ifconfig -a 2>&1`)
495
+ mac_addresses = ifconfig_output.scan(
496
+ Regexp.new("ether (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
497
+ end
498
+ if mac_addresses.size == 0
499
+ ifconfig_output =
500
+ (script_in_path ?
501
+ `ifconfig | grep HWaddr | cut -c39- 2>&1` :
502
+ `/sbin/ifconfig | grep HWaddr | cut -c39- 2>&1`)
503
+ mac_addresses = ifconfig_output.scan(
504
+ Regexp.new("(#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
505
+ end
505
506
  end
507
+ if mac_addresses.size > 0
508
+ @@mac_address = mac_addresses.first.first
509
+ end
510
+ rescue
506
511
  end
507
- if mac_addresses.size > 0
508
- @@mac_address = mac_addresses.first.first
512
+ end
513
+ if @@mac_address != nil
514
+ if @@mac_address.respond_to?(:to_str)
515
+ @@mac_address = @@mac_address.to_str
516
+ else
517
+ @@mac_address = @@mac_address.to_s
509
518
  end
510
- rescue
519
+ @@mac_address.downcase!
520
+ @@mac_address.strip!
511
521
  end
512
- end
513
- if @@mac_address != nil
514
- if @@mac_address.respond_to?(:to_str)
515
- @@mac_address = @@mac_address.to_str
516
- else
517
- @@mac_address = @@mac_address.to_s
522
+
523
+ # Verify that the MAC address is in the right format.
524
+ # Nil it out if it isn't.
525
+ unless @@mac_address.respond_to?(:scan) &&
526
+ @@mac_address.scan(/#{(["[0-9a-f]{2}"] * 6).join(":")}/)
527
+ @@mac_address = nil
518
528
  end
519
- @@mac_address.downcase!
520
- @@mac_address.strip!
521
529
  end
530
+ return @@mac_address
531
+ end
522
532
 
523
- # Verify that the MAC address is in the right format.
524
- # Nil it out if it isn't.
525
- unless @@mac_address.respond_to?(:scan) &&
526
- @@mac_address.scan(/#{(["[0-9a-f]{2}"] * 6).join(":")}/)
527
- @@mac_address = nil
528
- end
533
+ # Allows users to set the MAC address manually in cases where the MAC
534
+ # address cannot be obtained programatically.
535
+ def self.mac_address=(new_mac_address)
536
+ @@mac_address = new_mac_address
529
537
  end
530
- return @@mac_address
531
- end
532
538
 
533
- # Allows users to set the MAC address manually in cases where the MAC
534
- # address cannot be obtained programatically.
535
- def self.mac_address=(new_mac_address)
536
- @@mac_address = new_mac_address
537
- end
539
+ # The following methods are not part of the public API,
540
+ # and generally should not be called directly.
538
541
 
539
- # The following methods are not part of the public API,
540
- # and generally should not be called directly.
541
-
542
- # Creates a new UUID from a SHA1 or MD5 hash
543
- def self.create_from_hash(hash_class, namespace, name) #:nodoc:
544
- if hash_class == Digest::MD5
545
- version = 3
546
- elsif hash_class == Digest::SHA1
547
- version = 5
548
- else
549
- raise ArgumentError,
550
- "Expected Digest::SHA1 or Digest::MD5, got #{hash_class.name}."
542
+ # Creates a new UUID from a SHA1 or MD5 hash
543
+ def self.create_from_hash(hash_class, namespace, name) #:nodoc:
544
+ if hash_class == Digest::MD5
545
+ version = 3
546
+ elsif hash_class == Digest::SHA1
547
+ version = 5
548
+ else
549
+ raise ArgumentError,
550
+ "Expected Digest::SHA1 or Digest::MD5, got #{hash_class.name}."
551
+ end
552
+ hash = hash_class.new
553
+ hash.update(namespace.raw)
554
+ hash.update(name)
555
+ hash_string = hash.to_s[0..31]
556
+ new_uuid = self.parse("#{hash_string[0..7]}-#{hash_string[8..11]}-" +
557
+ "#{hash_string[12..15]}-#{hash_string[16..19]}-#{hash_string[20..31]}")
558
+
559
+ new_uuid.time_hi_and_version &= 0x0FFF
560
+ new_uuid.time_hi_and_version |= (version << 12)
561
+ new_uuid.clock_seq_hi_and_reserved &= 0x3F
562
+ new_uuid.clock_seq_hi_and_reserved |= 0x80
563
+ return new_uuid
551
564
  end
552
- hash = hash_class.new
553
- hash.update(namespace.raw)
554
- hash.update(name)
555
- hash_string = hash.to_s[0..31]
556
- new_uuid = self.parse("#{hash_string[0..7]}-#{hash_string[8..11]}-" +
557
- "#{hash_string[12..15]}-#{hash_string[16..19]}-#{hash_string[20..31]}")
558
-
559
- new_uuid.time_hi_and_version &= 0x0FFF
560
- new_uuid.time_hi_and_version |= (version << 12)
561
- new_uuid.clock_seq_hi_and_reserved &= 0x3F
562
- new_uuid.clock_seq_hi_and_reserved |= 0x80
563
- return new_uuid
564
- end
565
565
 
566
- def self.convert_int_to_byte_string(integer, size) #:nodoc:
567
- byte_string = ""
568
- for i in 0..(size - 1)
569
- byte_string << ((integer >> (((size - 1) - i) * 8)) & 0xFF)
566
+ def self.convert_int_to_byte_string(integer, size) #:nodoc:
567
+ byte_string = ""
568
+ for i in 0..(size - 1)
569
+ byte_string << ((integer >> (((size - 1) - i) * 8)) & 0xFF)
570
+ end
571
+ return byte_string
570
572
  end
571
- return byte_string
572
- end
573
573
 
574
- def self.convert_byte_string_to_int(byte_string) #:nodoc:
575
- integer = 0
576
- size = byte_string.size
577
- for i in 0..(size - 1)
578
- ordinal = (byte_string[i].respond_to?(:ord) ?
579
- byte_string[i].ord : byte_string[i])
580
- integer += (ordinal << (((size - 1) - i) * 8))
574
+ def self.convert_byte_string_to_int(byte_string) #:nodoc:
575
+ integer = 0
576
+ size = byte_string.size
577
+ for i in 0..(size - 1)
578
+ ordinal = (byte_string[i].respond_to?(:ord) ?
579
+ byte_string[i].ord : byte_string[i])
580
+ integer += (ordinal << (((size - 1) - i) * 8))
581
+ end
582
+ return integer
581
583
  end
582
- return integer
583
584
  end
584
- end
585
585
 
586
- UUID_DNS_NAMESPACE = UUID.parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
587
- UUID_URL_NAMESPACE = UUID.parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
588
- UUID_OID_NAMESPACE = UUID.parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
589
- UUID_X500_NAMESPACE = UUID.parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
586
+ UUID_DNS_NAMESPACE = UUID.parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
587
+ UUID_URL_NAMESPACE = UUID.parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
588
+ UUID_OID_NAMESPACE = UUID.parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
589
+ UUID_X500_NAMESPACE = UUID.parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
590
+ end