From 745b40c0a3c118b821c7bbab6208e84628a008cb Mon Sep 17 00:00:00 2001 From: Subhomoy Haldar Date: Fri, 19 Feb 2021 14:46:02 +0530 Subject: [PATCH] rand: refactor string sampling functions to remove redundancy (#8830) --- vlib/rand/constants/constants.v | 2 +- vlib/rand/rand.v | 55 +++++++++-------------- vlib/rand/random_numbers_test.v | 80 +++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 34 deletions(-) diff --git a/vlib/rand/constants/constants.v b/vlib/rand/constants/constants.v index 5afa08d408..76fe211dab 100644 --- a/vlib/rand/constants/constants.v +++ b/vlib/rand/constants/constants.v @@ -9,4 +9,4 @@ pub const ( max_u64_as_f64 = f64(max_u64) + 1 u31_mask = u32(0x7FFFFFFF) u63_mask = u64(0x7FFFFFFFFFFFFFFF) -) \ No newline at end of file +) diff --git a/vlib/rand/rand.v b/vlib/rand/rand.v index b2d0f76cc3..2b81a8defc 100644 --- a/vlib/rand/rand.v +++ b/vlib/rand/rand.v @@ -138,56 +138,45 @@ pub fn f64_in_range(min f64, max f64) f64 { } const ( - chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + english_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + hex_chars = 'abcdef0123456789' + ascii_chars = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz{|}~' ) +// string_from_set returns a string of length `len` containing random characters sampled from the given `charset` +pub fn string_from_set(charset string, len int) string { + if len == 0 { + return '' + } + mut buf := unsafe { malloc(len) } + for i in 0 .. len { + unsafe { + buf[i] = charset[intn(charset.len)] + } + } + return unsafe { buf.vstring_with_len(len) } +} + // string returns a string of length `len` containing random characters in range `[a-zA-Z]`. pub fn string(len int) string { - mut buf := unsafe {malloc(len)} - for i in 0 .. len { - unsafe { - buf[i] = rand.chars[intn(rand.chars.len)] - } - } - return unsafe { buf.vstring_with_len(len) } + return string_from_set(rand.english_letters, len) } - -const ( - hex_chars = 'abcdef0123456789' -) - // hex returns a hexadecimal number of length `len` containing random characters in range `[a-f0-9]`. pub fn hex(len int) string { - mut buf := unsafe {malloc(len)} - for i in 0 .. len { - unsafe { - buf[i] = rand.hex_chars[intn(rand.hex_chars.len)] - } - } - return unsafe { buf.vstring_with_len(len) } + return string_from_set(rand.hex_chars, len) } -const ( - ascii_chars = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz{|}~' -) - // ascii returns a random string of the printable ASCII characters with length `len`. pub fn ascii(len int) string { - mut buf := unsafe {malloc(len)} - for i in 0 .. len { - unsafe { - buf[i] = rand.ascii_chars[intn(rand.ascii_chars.len)] - } - } - return unsafe { buf.vstring_with_len(len) } + return string_from_set(rand.ascii_chars, len) } // uuid_v4 generates a random (v4) UUID // See https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random) pub fn uuid_v4() string { buflen := 36 - mut buf := unsafe {malloc(37)} + mut buf := unsafe { malloc(37) } mut i_buf := 0 mut x := u64(0) mut d := byte(0) @@ -240,7 +229,7 @@ pub fn ulid() string { // ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_time_milli`. pub fn ulid_at_millisecond(unix_time_milli u64) string { buflen := 26 - mut buf := unsafe {malloc(27)} + mut buf := unsafe { malloc(27) } mut t := unix_time_milli mut i := 9 for i >= 0 { diff --git a/vlib/rand/random_numbers_test.v b/vlib/rand/random_numbers_test.v index 987787cc37..7e8e1fe8c0 100644 --- a/vlib/rand/random_numbers_test.v +++ b/vlib/rand/random_numbers_test.v @@ -188,3 +188,83 @@ fn test_rand_byte() { assert all[0] != all[255] assert all[0] != all[128] } + +const ( + string_count = 25 +) + +fn test_rand_string_from_set() { + sets := [ + '0123456789', + 'qwertyuiop', + 'abcdefghijklmnopqrstuvwxyz', + ] + for charset in sets { + for _ in 0 .. string_count { + len := rand.intn(rnd_count) + str := rand.string_from_set(charset, len) + assert str.len == len + for character in str { + position := charset.index(character.ascii_str()) or { -1 } + assert position > -1 + } + } + } +} + +fn test_rand_string() { + rand.seed([u32(0), 1]) + outputs := [ + 'rzJfVBJgvAyCNpEdXIteDQezg', + 'AJOeswgoelDOCfcrSUWzVPjeL', + 'NQfKauQqsXYXSUMFPGnXXPJIn', + 'vfBGUKbpLoBMQVYXfkvRplWih', + 'aYHLjMJqvUJmJJHGxEnrEmQGl', + 'rBJXkQZcembAteaRFoxXmECJo', + 'HYVLfHmDOCTlSbiSzHrsAIaBH', + 'zgOiwyISjLSdLGhLzJsSKHVBi', + 'UiAtobWXGcHsEtgzuNatxfkoI', + 'NisnYlffJgFEcIdcgzWcGjnHy', + ] + for output in outputs { + assert rand.string(25) == output + } +} + +fn test_rand_hex() { + rand.seed([u32(0), 1]) + outputs := [ + 'fc30e495deee09e008e15ffc3', + '4320efa837788397fb59b28f4', + '4995210abf33b6765c240ce62', + 'f3d20dbe0a8aa6b9c88cd1f6f', + '8d7d58b256ab00213dd519cf7', + 'fa2251284bc20a21eff48127c', + '5fef90cdc0c37143117599092', + '2a6170531c76dfb50c54126bc', + 'a686dfd536042d1c1a9afdaf4', + '7f12013f6e1177e2d63726de3', + ] + for output in outputs { + assert rand.hex(25) == output + } +} + +fn test_rand_ascii() { + rand.seed([u32(0), 1]) + outputs := [ + "2Z:&PeD'V;9=mn\$C>yKg'DIr%", + 'Ub7ix,}>I=QJki{%FHKv&K', + '1WStRylMO|p.R~qqRtr&AOEsd', + 'yka