Permalink
Browse files

to_guid for Cassandra::Long. Don't tell the ISO.

  • Loading branch information...
1 parent 939df11 commit 767c5da12e41f5934889963c408dbdb9aa3626e0 Evan Weaver committed Aug 20, 2009
Showing with 53 additions and 36 deletions.
  1. +2 −0 CHANGELOG
  2. +22 −8 lib/cassandra/long.rb
  3. +28 −28 lib/cassandra/uuid.rb
  4. +1 −0 test/comparable_types_test.rb
View
@@ -1,4 +1,6 @@
+v0.5.5. to_guid for Long.
+
v0.5.4. Use wget instead of curl.
v0.5.3. Update Multiblog sample schema.
View
@@ -2,12 +2,20 @@
class Cassandra
# A temporally-ordered Long class for use in Cassandra column names
class Long < Comparable
-
- def initialize(bytes = nil)
+
+ def initialize(bytes = nil)
case bytes
when String
- raise TypeError, "8 bytes required" if bytes.size != 8
- @bytes = bytes
+ case bytes.size
+ when 8 # Raw byte array
+ @bytes = bytes
+ when 18 # Human-readable UUID-like representation; inverse of #to_guid
+ elements = bytes.split("-")
+ raise TypeError, "Malformed UUID-like representation" if elements.size != 3
+ @bytes = elements.join.to_a.pack('H32')
+ else
+ raise TypeError, "8 bytes required for byte array, or 18 characters required for UUID-like representation"
+ end
when Integer
raise TypeError, "Integer must be between 0 and 2**64" if bytes < 0 or bytes > 2**64
@bytes = [bytes >> 32, bytes % 2**32].pack("NN")
@@ -23,19 +31,25 @@ def initialize(bytes = nil)
def to_i
@to_i ||= begin
ints = @bytes.unpack("NN")
- (ints[0] << 32) +
+ (ints[0] << 32) +
ints[1]
end
- end
+ end
+ def to_guid
+ "%08x-%04x-%04x" % @bytes.unpack("Nnn")
+ end
+
def inspect
"<Cassandra::Long##{object_id} time: #{
Time.at((to_i >> 12) / 1_000_000).inspect
}, usecs: #{
(to_i >> 12) % 1_000_000
}, jitter: #{
to_i % 2**12
+ }, guid: #{
+ to_guid
}>"
- end
- end
+ end
+ end
end
View
@@ -8,55 +8,55 @@ class InvalidVersion < StandardError #:nodoc:
end
GREGORIAN_EPOCH_OFFSET = 0x01B2_1DD2_1381_4000 # Oct 15, 1582
-
+
VARIANT = 0b1000_0000_0000_0000
def initialize(bytes = nil)
case bytes
when String
case bytes.size
- when 16
- @bytes = bytes
- when 36
+ when 16 # Raw byte array
+ @bytes = bytes
+ when 36 # Human-readable UUID representation; inverse of #to_guid
elements = bytes.split("-")
raise TypeError, "Malformed UUID representation" if elements.size != 5
- @bytes = elements.join.to_a.pack('H32')
+ @bytes = elements.join.to_a.pack('H32')
else
raise TypeError, "16 bytes required for byte array, or 36 characters required for UUID representation"
end
-
+
when Integer
raise TypeError, "Integer must be between 0 and 2**128" if bytes < 0 or bytes > 2**128
@bytes = [
- (bytes >> 96) & 0xFFFF_FFFF,
- (bytes >> 64) & 0xFFFF_FFFF,
- (bytes >> 32) & 0xFFFF_FFFF,
+ (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/
@bytes = [
- time & 0xFFFF_FFFF,
- time >> 32,
- ((time >> 48) & 0x0FFF) | 0x1000,
- # Top 3 bytes reserved
+ time & 0xFFFF_FFFF,
+ time >> 32,
+ ((time >> 48) & 0x0FFF) | 0x1000,
+ # Top 3 bytes reserved
rand(2**13) | VARIANT,
rand(2**16),
rand(2**32)
].pack("NnnnnN")
-
+
else
raise TypeError, "Can't convert from #{bytes.class}"
end
end
def to_i
ints = @bytes.unpack("NNNN")
- (ints[0] << 96) +
- (ints[1] << 64) +
- (ints[2] << 32) +
+ (ints[0] << 96) +
+ (ints[1] << 64) +
+ (ints[2] << 32) +
ints[3]
end
@@ -65,7 +65,7 @@ def version
version = (time_high & 0xF000).to_s(16)[0].chr.to_i
version > 0 and version < 6 ? version : -1
end
-
+
def variant
@bytes.unpack('QnnN')[1] >> 13
end
@@ -76,19 +76,19 @@ def to_guid
elements[-1] = '%02x%02x%02x%02x%02x%02x' % node
"%08x-%04x-%04x-%02x%02x-%s" % elements
end
-
+
def seconds
total_usecs / 1_000_000
end
-
+
def usecs
- total_usecs % 1_000_000
+ total_usecs % 1_000_000
end
-
+
def <=>(other)
total_usecs <=> other.send(:total_usecs)
end
-
+
def inspect(long = false)
"<Cassandra::UUID##{object_id} time: #{
Time.at(seconds).inspect
@@ -97,13 +97,13 @@ def inspect(long = false)
} jitter: #{
@bytes.unpack('QQ')[1]
}" + (long ? ", version: #{version}, variant: #{variant}, guid: #{to_guid}>" : ">")
- end
-
+ end
+
private
-
+
def total_usecs
elements = @bytes.unpack("NnnQ")
- (elements[0] + (elements[1] << 32) + ((elements[2] & 0x0FFF) << 48) - GREGORIAN_EPOCH_OFFSET) / 10
+ (elements[0] + (elements[1] << 32) + ((elements[2] & 0x0FFF) << 48) - GREGORIAN_EPOCH_OFFSET) / 10
end
end
end
@@ -13,6 +13,7 @@ def test_long_equality
long = Long.new
assert_equal long, Long.new(long.to_s)
assert_equal long, Long.new(long.to_i)
+ assert_equal long, Long.new(long.to_guid)
end
def test_long_error

0 comments on commit 767c5da

Please sign in to comment.