rand: add `pub fn rand.read(mut buf []byte)` and `pub fn rand.bytes(needed int) ?[]byte{}` + tests

pull/12662/head
Delyan Angelov 2022-02-06 10:49:43 +02:00
parent ece73836aa
commit 66f21cae55
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
4 changed files with 82 additions and 0 deletions

View File

@ -138,3 +138,17 @@ fn init() {
default_rng = new_default()
C.atexit(deinit)
}
// read fills in `buf` a maximum of `buf.len` random bytes
pub fn read(mut buf []byte) {
p64 := unsafe { &u64(buf.data) }
u64s := buf.len / 8
for i in 0 .. u64s {
unsafe {
*(p64 + i) = default_rng.u64()
}
}
for i in u64s * 8 .. buf.len {
buf[i] = byte(default_rng.u32())
}
}

View File

@ -65,3 +65,10 @@ pub fn ulid_at_millisecond(unix_time_milli u64) string {
return res
}
// read fills in `buf` a maximum of `buf.len` random bytes
pub fn read(mut buf []byte) {
for i in 0 .. buf.len {
buf[i] = byte(default_rng.u32())
}
}

View File

@ -174,6 +174,16 @@ pub fn f64_in_range(min f64, max f64) f64 {
return default_rng.f64_in_range(min, max)
}
// bytes returns a buffer of `bytes_needed` random bytes
pub fn bytes(bytes_needed int) ?[]byte {
if bytes_needed < 0 {
return error('can not read < 0 random bytes')
}
mut res := []byte{len: bytes_needed}
read(mut res)
return res
}
const (
english_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
hex_chars = 'abcdef0123456789'

View File

@ -0,0 +1,51 @@
import rand
fn test_rand_bytes() ? {
mut randoms := []string{}
for i in 0 .. 100 {
x := rand.bytes(i) ?.hex()
if x.len > 0 {
randoms << x
}
assert x.len == i * 2
}
mut differences := 0
for idx in 1 .. randoms.len {
start := randoms[idx]#[0..8]
prev_start := randoms[idx - 1]#[0..8]
if start != prev_start {
differences++
}
}
assert differences > 95 // normally around 98
dump(differences)
}
fn test_rand_read() ? {
max := 50
mut a := []byte{len: max}
mut differences := 0
for j in 1 .. max {
start := '00'.repeat(j)
for k in j + 1 .. max {
end := '00'.repeat(max - k)
middle := '00'.repeat(k - j)
// eprintln('> j: $j | k: $k | start: $start | middle: $middle | end: $end')
for i in 0 .. max {
a[i] = 0
}
assert a[j..k].hex() == middle
for i in 0 .. 10 {
rand.read(mut a[j..k])
// dump(a.hex())
assert a[0..j].hex() == start
assert a[k..].hex() == end
if a[j..k].hex() != middle {
differences++
}
}
}
}
dump(differences)
assert differences > 11700 // normally around 11758
}