Skip to content

Commit 745b40c

Browse files
rand: refactor string sampling functions to remove redundancy (#8830)
1 parent 10de905 commit 745b40c

File tree

3 files changed

+99
-30
lines changed

3 files changed

+99
-30
lines changed

vlib/rand/constants/constants.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ pub const (
99
max_u64_as_f64 = f64(max_u64) + 1
1010
u31_mask = u32(0x7FFFFFFF)
1111
u63_mask = u64(0x7FFFFFFFFFFFFFFF)
12-
)
12+
)

vlib/rand/rand.v

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -138,56 +138,45 @@ pub fn f64_in_range(min f64, max f64) f64 {
138138
}
139139

140140
const (
141-
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
141+
english_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
142+
hex_chars = 'abcdef0123456789'
143+
ascii_chars = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz{|}~'
142144
)
143145

144-
// string returns a string of length `len` containing random characters in range `[a-zA-Z]`.
145-
pub fn string(len int) string {
146-
mut buf := unsafe {malloc(len)}
146+
// string_from_set returns a string of length `len` containing random characters sampled from the given `charset`
147+
pub fn string_from_set(charset string, len int) string {
148+
if len == 0 {
149+
return ''
150+
}
151+
mut buf := unsafe { malloc(len) }
147152
for i in 0 .. len {
148153
unsafe {
149-
buf[i] = rand.chars[intn(rand.chars.len)]
154+
buf[i] = charset[intn(charset.len)]
150155
}
151156
}
152157
return unsafe { buf.vstring_with_len(len) }
153158
}
154159

155-
156-
const (
157-
hex_chars = 'abcdef0123456789'
158-
)
160+
// string returns a string of length `len` containing random characters in range `[a-zA-Z]`.
161+
pub fn string(len int) string {
162+
return string_from_set(rand.english_letters, len)
163+
}
159164

160165
// hex returns a hexadecimal number of length `len` containing random characters in range `[a-f0-9]`.
161166
pub fn hex(len int) string {
162-
mut buf := unsafe {malloc(len)}
163-
for i in 0 .. len {
164-
unsafe {
165-
buf[i] = rand.hex_chars[intn(rand.hex_chars.len)]
166-
}
167-
}
168-
return unsafe { buf.vstring_with_len(len) }
167+
return string_from_set(rand.hex_chars, len)
169168
}
170169

171-
const (
172-
ascii_chars = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz{|}~'
173-
)
174-
175170
// ascii returns a random string of the printable ASCII characters with length `len`.
176171
pub fn ascii(len int) string {
177-
mut buf := unsafe {malloc(len)}
178-
for i in 0 .. len {
179-
unsafe {
180-
buf[i] = rand.ascii_chars[intn(rand.ascii_chars.len)]
181-
}
182-
}
183-
return unsafe { buf.vstring_with_len(len) }
172+
return string_from_set(rand.ascii_chars, len)
184173
}
185174

186175
// uuid_v4 generates a random (v4) UUID
187176
// See https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
188177
pub fn uuid_v4() string {
189178
buflen := 36
190-
mut buf := unsafe {malloc(37)}
179+
mut buf := unsafe { malloc(37) }
191180
mut i_buf := 0
192181
mut x := u64(0)
193182
mut d := byte(0)
@@ -240,7 +229,7 @@ pub fn ulid() string {
240229
// ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_time_milli`.
241230
pub fn ulid_at_millisecond(unix_time_milli u64) string {
242231
buflen := 26
243-
mut buf := unsafe {malloc(27)}
232+
mut buf := unsafe { malloc(27) }
244233
mut t := unix_time_milli
245234
mut i := 9
246235
for i >= 0 {

vlib/rand/random_numbers_test.v

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,83 @@ fn test_rand_byte() {
188188
assert all[0] != all[255]
189189
assert all[0] != all[128]
190190
}
191+
192+
const (
193+
string_count = 25
194+
)
195+
196+
fn test_rand_string_from_set() {
197+
sets := [
198+
'0123456789',
199+
'qwertyuiop',
200+
'abcdefghijklmnopqrstuvwxyz',
201+
]
202+
for charset in sets {
203+
for _ in 0 .. string_count {
204+
len := rand.intn(rnd_count)
205+
str := rand.string_from_set(charset, len)
206+
assert str.len == len
207+
for character in str {
208+
position := charset.index(character.ascii_str()) or { -1 }
209+
assert position > -1
210+
}
211+
}
212+
}
213+
}
214+
215+
fn test_rand_string() {
216+
rand.seed([u32(0), 1])
217+
outputs := [
218+
'rzJfVBJgvAyCNpEdXIteDQezg',
219+
'AJOeswgoelDOCfcrSUWzVPjeL',
220+
'NQfKauQqsXYXSUMFPGnXXPJIn',
221+
'vfBGUKbpLoBMQVYXfkvRplWih',
222+
'aYHLjMJqvUJmJJHGxEnrEmQGl',
223+
'rBJXkQZcembAteaRFoxXmECJo',
224+
'HYVLfHmDOCTlSbiSzHrsAIaBH',
225+
'zgOiwyISjLSdLGhLzJsSKHVBi',
226+
'UiAtobWXGcHsEtgzuNatxfkoI',
227+
'NisnYlffJgFEcIdcgzWcGjnHy',
228+
]
229+
for output in outputs {
230+
assert rand.string(25) == output
231+
}
232+
}
233+
234+
fn test_rand_hex() {
235+
rand.seed([u32(0), 1])
236+
outputs := [
237+
'fc30e495deee09e008e15ffc3',
238+
'4320efa837788397fb59b28f4',
239+
'4995210abf33b6765c240ce62',
240+
'f3d20dbe0a8aa6b9c88cd1f6f',
241+
'8d7d58b256ab00213dd519cf7',
242+
'fa2251284bc20a21eff48127c',
243+
'5fef90cdc0c37143117599092',
244+
'2a6170531c76dfb50c54126bc',
245+
'a686dfd536042d1c1a9afdaf4',
246+
'7f12013f6e1177e2d63726de3',
247+
]
248+
for output in outputs {
249+
assert rand.hex(25) == output
250+
}
251+
}
252+
253+
fn test_rand_ascii() {
254+
rand.seed([u32(0), 1])
255+
outputs := [
256+
"2Z:&PeD'V;9=mn\$C>yKg'DIr%",
257+
'Ub7ix,}>I=&#2QJki{%FHKv&K',
258+
'1WStRylMO|p.R~qqRtr&AOEsd',
259+
'yka<GPZ&m+r0^Zi!ShB*1dU~W',
260+
'uDA?.zU2X,<DkKT#_-halW\\ki',
261+
'fsx!@uRc?re/fSPXj`Y&\\BU}p',
262+
'fI_qM"):2;CUno!<dX:Yv*FX$',
263+
'FnA(Fr|D`WZVWEzp<k)O;auub',
264+
"QRkxH!kjXh&/j{)uSe&{D'v?|",
265+
"_CyaU\$z':#}At*v2|xDu6w=;1",
266+
]
267+
for output in outputs {
268+
assert rand.ascii(25) == output
269+
}
270+
}

0 commit comments

Comments
 (0)