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