1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use super::{Random, Rng, Seed};
use crate::convert::implicitly_convert_to_int;
use crate::extn::prelude::*;
pub fn initialize(interp: &mut Artichoke, seed: Option<Value>, into: Value) -> Result<Value, Error> {
let seed: Seed = interp.try_convert_mut(seed)?;
let random = if let Some(seed) = seed.to_mt_seed() {
Random::with_array_seed(seed)
} else {
Random::new()?
};
let random = Rng::Instance(Box::new(random));
let random = Rng::box_into_value(random, into, interp)?;
Ok(random)
}
pub fn equal(interp: &mut Artichoke, mut rand: Value, mut other: Value) -> Result<Value, Error> {
let random = unsafe { Rng::unbox_from_value(&mut rand, interp)? };
let other = unsafe { Rng::unbox_from_value(&mut other, interp)? };
let eql = *random == *other;
Ok(interp.convert(eql))
}
pub fn bytes(interp: &mut Artichoke, mut rand: Value, size: Value) -> Result<Value, Error> {
let mut random = unsafe { Rng::unbox_from_value(&mut rand, interp)? };
let size = implicitly_convert_to_int(interp, size)?;
let mut buf = match usize::try_from(size) {
Ok(0) => return interp.try_convert_mut(Vec::<u8>::new()),
Ok(len) => vec![0; len],
Err(_) => return Err(ArgumentError::with_message("negative string size (or size too big)").into()),
};
match &mut *random {
Rng::Global => interp.prng_mut()?.fill_bytes(&mut buf),
Rng::Instance(random) => random.fill_bytes(&mut buf),
}
interp.try_convert_mut(buf)
}
pub fn rand(interp: &mut Artichoke, mut rand: Value, max: Option<Value>) -> Result<Value, Error> {
let mut random = unsafe { Rng::unbox_from_value(&mut rand, interp)? };
let max = interp.try_convert_mut(max)?;
let num = match &mut *random {
Rng::Global => spinoso_random::rand(interp.prng_mut()?, max)?,
Rng::Instance(random) => spinoso_random::rand(random, max)?,
};
Ok(interp.convert_mut(num))
}
pub fn seed(interp: &mut Artichoke, mut rand: Value) -> Result<Value, Error> {
let random = unsafe { Rng::unbox_from_value(&mut rand, interp)? };
let seed = match &*random {
Rng::Global => interp.prng()?.seed(),
Rng::Instance(random) => random.seed(),
};
let seed = seed
.try_into()
.map_err(|_| Fatal::with_message("Got random seed larger than i128"))?;
interp.try_convert(Seed::from_mt_seed_lossy(seed))
}
pub fn new_seed(interp: &mut Artichoke) -> Result<Value, Error> {
let seed = spinoso_random::new_seed()?;
let seed = Seed::from_mt_seed_lossy(seed);
interp.try_convert(seed)
}
pub fn srand(interp: &mut Artichoke, seed: Option<Value>) -> Result<Value, Error> {
let seed: Seed = interp.try_convert_mut(seed)?;
let old_seed = interp
.prng()?
.seed()
.try_into()
.map_err(|_| Fatal::with_message("Got random seed larger than i128"))?;
let old_seed = Seed::from_mt_seed_lossy(old_seed);
let new_random = if let Some(seed) = seed.to_mt_seed() {
Random::with_array_seed(seed)
} else {
Random::new()?
};
let prng = interp.prng_mut()?;
*prng = new_random;
interp.try_convert(old_seed)
}
pub fn urandom(interp: &mut Artichoke, size: Value) -> Result<Value, Error> {
let size = implicitly_convert_to_int(interp, size)?;
let mut buf = match usize::try_from(size) {
Ok(0) => return interp.try_convert_mut(Vec::<u8>::new()),
Ok(len) => vec![0; len],
Err(_) => return Err(ArgumentError::with_message("negative string size (or size too big)").into()),
};
spinoso_random::urandom(&mut buf)?;
interp.try_convert_mut(buf)
}