Add runtime.Random_Generator interface

This commit is contained in:
gingerBill
2024-06-15 14:45:57 +01:00
parent 94ec647923
commit dc4ec8638c
3 changed files with 66 additions and 0 deletions
+19
View File
@@ -397,11 +397,30 @@ Logger :: struct {
options: Logger_Options,
}
Random_Generator_Mode :: enum {
Read,
Query_Info,
}
Random_Generator_Query_Info_Flag :: enum u32 {
Cryptographic,
Uniform,
External_Entropy,
}
Random_Generator_Query_Info :: distinct bit_set[Random_Generator_Query_Info_Flag; u32]
Random_Generator :: struct {
procedure: proc(data: rawptr, mode: Random_Generator_Mode, p: []byte),
data: rawptr,
}
Context :: struct {
allocator: Allocator,
temp_allocator: Allocator,
assertion_failure_proc: Assertion_Failure_Proc,
logger: Logger,
random_generator: Random_Generator,
user_ptr: rawptr,
user_index: int,
+20
View File
@@ -4,6 +4,7 @@ helper routines.
*/
package crypto
import "base:runtime"
import "core:mem"
// compare_constant_time returns 1 iff a and b are equal, 0 otherwise.
@@ -58,3 +59,22 @@ rand_bytes :: proc (dst: []byte) {
_rand_bytes(dst)
}
to_random_generator :: proc() -> runtime.Random_Generator {
return {
procedure = proc(data: rawptr, mode: runtime.Random_Generator_Mode, p: []byte) {
switch mode {
case .Read:
rand_bytes(p)
case .Query_Info:
if len(p) != size_of(runtime.Random_Generator_Query_Info) {
return
}
info := (^runtime.Random_Generator_Query_Info)(raw_data(p))
info^ += {.Uniform, .Cryptographic, .External_Entropy}
}
},
data = nil,
}
}
+27
View File
@@ -5,6 +5,7 @@ Package core:math/rand implements various random number generators
package rand
import "base:intrinsics"
import "base:runtime"
import "core:crypto"
import "core:math"
import "core:mem"
@@ -15,6 +16,28 @@ Rand :: struct {
is_system: bool,
}
to_random_generator :: proc(r: ^Rand) -> runtime.Random_Generator {
return {
procedure = proc(data: rawptr, mode: runtime.Random_Generator_Mode, p: []byte) {
r := (^Rand)(data)
switch mode {
case .Read:
_ = read(p, r)
case .Query_Info:
if len(p) != size_of(runtime.Random_Generator_Query_Info) {
return
}
info := (^runtime.Random_Generator_Query_Info)(raw_data(p))
info^ += {.Uniform}
if r.is_system {
info^ += {.External_Entropy}
}
}
},
data = r,
}
}
@(private)
global_rand := create(u64(intrinsics.read_cycle_counter()))
@@ -150,6 +173,10 @@ _random_u64 :: proc(r: ^Rand) -> u64 {
r := r
switch {
case r == nil:
if res: u64; runtime.random_generator_read_ptr(context.random_generator, &res, size_of(res)) {
return res
}
r = &global_rand
case r.is_system:
value: u64