rand: fix rand.uuid_v4()'s clock_seq_hi_and_reserved field

pull/13511/head
Delyan Angelov 2022-02-18 12:37:27 +02:00
parent c9867a9ae4
commit 3c38abc56e
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
3 changed files with 24 additions and 10 deletions

View File

@ -1,9 +1,11 @@
module rand module rand
import time import time
const clock_seq_hi_and_reserved_valid_values = [`8`, `9`, `a`, `b`]
// uuid_v4 generates a random (v4) UUID // uuid_v4 generates a random (v4) UUID
// See https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random) // See https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
pub fn uuid_v4() string { pub fn uuid_v4() string {
buflen := 36 buflen := 36
mut buf := unsafe { malloc_noscan(37) } mut buf := unsafe { malloc_noscan(37) }
@ -31,20 +33,26 @@ pub fn uuid_v4() string {
x = x >> 8 x = x >> 8
d = byte(x) d = byte(x)
unsafe { unsafe {
buf[19] = if d > 0x39 { d + 0x27 } else { d } // From https://www.ietf.org/rfc/rfc4122.txt :
// >> Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved
// >> to zero and one, respectively.
// all nibbles starting with 10 are: 1000, 1001, 1010, 1011 -> hex digits `8`, `9`, `a`, `b`
// these are stored in clock_seq_hi_and_reserved_valid_values, choose one of them at random:
buf[19] = rand.clock_seq_hi_and_reserved_valid_values[d & 0x03]
// >> Set the four most significant bits (bits 12 through 15) of the
// >> time_hi_and_version field to the 4-bit version number from Section 4.1.3.
buf[14] = `4`
buf[8] = `-` buf[8] = `-`
buf[13] = `-` buf[13] = `-`
buf[18] = `-` buf[18] = `-`
buf[23] = `-` buf[23] = `-`
buf[14] = `4` buf[buflen] = 0 // ensure the string will be 0 terminated, just in case
buf[buflen] = 0 // for i in 0..37 { println('i: ${i:2} | ${buf[i].ascii_str()} | ${buf[i].hex()} | ${buf[i]:08b}') }
return buf.vstring_with_len(buflen) return buf.vstring_with_len(buflen)
} }
} }
const ( const ulid_encoding = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'
ulid_encoding = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'
)
// ulid generates an Unique Lexicographically sortable IDentifier. // ulid generates an Unique Lexicographically sortable IDentifier.
// See https://github.com/ulid/spec . // See https://github.com/ulid/spec .

View File

@ -12,9 +12,13 @@ fn test_rand_uuid_v4() {
assert uuid1.len == 36 assert uuid1.len == 36
assert uuid2.len == 36 assert uuid2.len == 36
assert uuid3.len == 36 assert uuid3.len == 36
assert uuid1[14] == `4` for i in 0 .. 1000 {
assert uuid2[14] == `4` x := rand.uuid_v4()
assert uuid3[14] == `4` // check the version field is always 4:
assert x[14] == `4`
// and the clock_seq_hi_and_reserved field is valid too:
assert x[19] in [`8`, `9`, `a`, `b`]
}
} }
// ulids: // ulids:

View File

@ -3,4 +3,6 @@ import rand
fn main() { fn main() {
n := rand.intn(1000) n := rand.intn(1000)
println(n) println(n)
u := rand.uuid_v4()
println(u)
} }