Skip to content

Commit 66f21ca

Browse files
committed
rand: add pub fn rand.read(mut buf []byte) and pub fn rand.bytes(needed int) ?[]byte{} + tests
1 parent ece7383 commit 66f21ca

File tree

4 files changed

+82
-0
lines changed

4 files changed

+82
-0
lines changed

vlib/rand/rand.c.v

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,17 @@ fn init() {
138138
default_rng = new_default()
139139
C.atexit(deinit)
140140
}
141+
142+
// read fills in `buf` a maximum of `buf.len` random bytes
143+
pub fn read(mut buf []byte) {
144+
p64 := unsafe { &u64(buf.data) }
145+
u64s := buf.len / 8
146+
for i in 0 .. u64s {
147+
unsafe {
148+
*(p64 + i) = default_rng.u64()
149+
}
150+
}
151+
for i in u64s * 8 .. buf.len {
152+
buf[i] = byte(default_rng.u32())
153+
}
154+
}

vlib/rand/rand.js.v

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,10 @@ pub fn ulid_at_millisecond(unix_time_milli u64) string {
6565

6666
return res
6767
}
68+
69+
// read fills in `buf` a maximum of `buf.len` random bytes
70+
pub fn read(mut buf []byte) {
71+
for i in 0 .. buf.len {
72+
buf[i] = byte(default_rng.u32())
73+
}
74+
}

vlib/rand/rand.v

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,16 @@ pub fn f64_in_range(min f64, max f64) f64 {
174174
return default_rng.f64_in_range(min, max)
175175
}
176176

177+
// bytes returns a buffer of `bytes_needed` random bytes
178+
pub fn bytes(bytes_needed int) ?[]byte {
179+
if bytes_needed < 0 {
180+
return error('can not read < 0 random bytes')
181+
}
182+
mut res := []byte{len: bytes_needed}
183+
read(mut res)
184+
return res
185+
}
186+
177187
const (
178188
english_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
179189
hex_chars = 'abcdef0123456789'

vlib/rand/random_bytes_test.v

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import rand
2+
3+
fn test_rand_bytes() ? {
4+
mut randoms := []string{}
5+
for i in 0 .. 100 {
6+
x := rand.bytes(i) ?.hex()
7+
if x.len > 0 {
8+
randoms << x
9+
}
10+
assert x.len == i * 2
11+
}
12+
mut differences := 0
13+
for idx in 1 .. randoms.len {
14+
start := randoms[idx]#[0..8]
15+
prev_start := randoms[idx - 1]#[0..8]
16+
if start != prev_start {
17+
differences++
18+
}
19+
}
20+
assert differences > 95 // normally around 98
21+
dump(differences)
22+
}
23+
24+
fn test_rand_read() ? {
25+
max := 50
26+
mut a := []byte{len: max}
27+
mut differences := 0
28+
for j in 1 .. max {
29+
start := '00'.repeat(j)
30+
for k in j + 1 .. max {
31+
end := '00'.repeat(max - k)
32+
middle := '00'.repeat(k - j)
33+
// eprintln('> j: $j | k: $k | start: $start | middle: $middle | end: $end')
34+
for i in 0 .. max {
35+
a[i] = 0
36+
}
37+
assert a[j..k].hex() == middle
38+
for i in 0 .. 10 {
39+
rand.read(mut a[j..k])
40+
// dump(a.hex())
41+
assert a[0..j].hex() == start
42+
assert a[k..].hex() == end
43+
if a[j..k].hex() != middle {
44+
differences++
45+
}
46+
}
47+
}
48+
}
49+
dump(differences)
50+
assert differences > 11700 // normally around 11758
51+
}

0 commit comments

Comments
 (0)