@@ -40,23 +40,57 @@ require "crystal/spin_lock"
40
40
# ```
41
41
#
42
42
struct CSUUID
43
- VERSION = " 0.1.1 "
43
+ VERSION = " 0.2.0 "
44
44
45
45
@@mutex = Crystal ::SpinLock .new
46
46
# @@mutex = Mutex.new(protection: Mutex::Protection::Reentrant)
47
47
@@prng = Random ::ISAAC .new
48
48
@@string_matcher = /^(........) -(....) -(....) -(....) -(............) /
49
- # :nodoc:
50
- class_property identifier
51
- # :nodoc:
52
- class_property extra
49
+ @@unique_identifier : Slice (UInt8 ) = Slice (UInt8 ).new(6 , 0 )
50
+ @@unique_seconds_and_nanoseconds : Tuple (Int64 , Int32 ) = {0 _i64 , 0 _i32 }
53
51
54
52
@bytes : Slice (UInt8 ) = Slice (UInt8 ).new(16 )
55
53
@seconds_and_nanoseconds : Tuple (Int64 , Int32 )?
56
54
@timestamp : Time ?
57
55
@utc : Time ?
58
56
@location : Time ::Location = Time ::Location .local
59
57
58
+ def self.unique
59
+ @@mutex .sync do
60
+ t = Time .local
61
+ if t.internal_nanoseconds == @@unique_seconds_and_nanoseconds [1 ] &&
62
+ t.internal_seconds == @@unique_seconds_and_nanoseconds [0 ]
63
+ increment_unique_identifier
64
+ else
65
+ @@unique_seconds_and_nanoseconds = {t.internal_seconds, t.internal_nanoseconds}
66
+ @@unique_identifier = @@prng .random_bytes(6 )
67
+ end
68
+
69
+ new(
70
+ @@unique_seconds_and_nanoseconds [0 ],
71
+ @@unique_seconds_and_nanoseconds [1 ],
72
+ @@unique_identifier
73
+ )
74
+ end
75
+ end
76
+
77
+ def self.generate (count )
78
+ result = [] of CSUUID
79
+ count.times {result << unique}
80
+
81
+ result
82
+ end
83
+
84
+ # :nodoc:
85
+ def self.increment_unique_identifier
86
+ 5 .downto(0 ) do |position |
87
+ new_byte_value = @@unique_identifier [position] & += 1
88
+ break unless new_byte_value == 0
89
+ end
90
+
91
+ @@unique_identifier
92
+ end
93
+
60
94
def initialize (uuid : String )
61
95
@bytes = uuid.tr(" -" , " " ).hexbytes
62
96
end
@@ -81,13 +115,13 @@ struct CSUUID
81
115
82
116
private def initialize_impl (seconds : Int64 , nanoseconds : Int32 , identifier : Slice (UInt8 ) | String | Nil )
83
117
id = if identifier.is_a?(String )
84
- buf = Slice (UInt8 ).new(6 )
85
- number_of_bytes = identifier.size < 6 ? identifier.size : 6
86
- buf[0 , number_of_bytes].copy_from(identifier.hexbytes[0 , number_of_bytes])
87
- buf
88
- else
89
- identifier
90
- end
118
+ buf = Slice (UInt8 ).new(6 )
119
+ number_of_bytes = identifier.size < 6 ? identifier.size : 6
120
+ buf[0 , number_of_bytes].copy_from(identifier.hexbytes[0 , number_of_bytes])
121
+ buf
122
+ else
123
+ identifier
124
+ end
91
125
92
126
IO ::ByteFormat ::BigEndian .encode(seconds, @bytes [2 , 8 ])
93
127
IO ::ByteFormat ::BigEndian .encode(nanoseconds, @bytes [0 , 4 ])
0 commit comments