artichoke_backend/extn/stdlib/securerandom/
trampoline.rs

1//! Glue between mruby FFI and `securerandom` Rust implementation.
2
3use crate::convert::implicitly_convert_to_int;
4use crate::extn::prelude::*;
5use crate::extn::stdlib::securerandom;
6
7#[inline]
8pub fn alphanumeric(interp: &mut Artichoke, len: Option<Value>) -> Result<Value, Error> {
9    let alpha = if let Some(len) = len {
10        let len = implicitly_convert_to_int(interp, len)?;
11        securerandom::alphanumeric(Some(len))?
12    } else {
13        securerandom::alphanumeric(None)?
14    };
15    let alpha = spinoso_string::String::ascii(alpha);
16    spinoso_string::String::alloc_value(alpha, interp)
17}
18
19#[inline]
20pub fn base64(interp: &mut Artichoke, len: Option<Value>) -> Result<Value, Error> {
21    let base64 = if let Some(len) = len {
22        let len = implicitly_convert_to_int(interp, len)?;
23        securerandom::base64(Some(len))?
24    } else {
25        securerandom::base64(None)?
26    };
27    let base64 = spinoso_string::String::ascii(base64.into_bytes());
28    spinoso_string::String::alloc_value(base64, interp)
29}
30
31#[inline]
32pub fn urlsafe_base64(interp: &mut Artichoke, len: Option<Value>, padding: Option<Value>) -> Result<Value, Error> {
33    let padding = match padding {
34        None => false,
35        Some(val) if val.is_nil() => false,
36        Some(padding) => {
37            // All truthy values evaluate to `true` for this argument. So either
38            // `padding` is a `bool` and we can extract it, or we default to
39            // `true` since only `nil` (handled above) and `false` are falsy.
40            padding.try_convert_into::<bool>(interp).unwrap_or(true)
41        }
42    };
43    let base64 = if let Some(len) = len {
44        let len = implicitly_convert_to_int(interp, len)?;
45        securerandom::urlsafe_base64(Some(len), padding)?
46    } else {
47        securerandom::urlsafe_base64(None, padding)?
48    };
49    let base64 = spinoso_string::String::ascii(base64.into_bytes());
50    spinoso_string::String::alloc_value(base64, interp)
51}
52
53#[inline]
54pub fn hex(interp: &mut Artichoke, len: Option<Value>) -> Result<Value, Error> {
55    let hex = if let Some(len) = len {
56        let len = implicitly_convert_to_int(interp, len)?;
57        securerandom::hex(Some(len))?
58    } else {
59        securerandom::hex(None)?
60    };
61    let hex = spinoso_string::String::ascii(hex.into_bytes());
62    spinoso_string::String::alloc_value(hex, interp)
63}
64
65#[inline]
66pub fn random_bytes(interp: &mut Artichoke, len: Option<Value>) -> Result<Value, Error> {
67    let bytes = if let Some(len) = len {
68        // Upstream uses `n.to_int`, which means we must implicitly convert to
69        // int.
70        //
71        // <https://github.com/ruby/ruby/blob/v2_6_3/lib/securerandom.rb#L135>
72        let len = implicitly_convert_to_int(interp, len)?;
73        securerandom::random_bytes(Some(len))?
74    } else {
75        securerandom::random_bytes(None)?
76    };
77    let bytes = spinoso_string::String::binary(bytes);
78    spinoso_string::String::alloc_value(bytes, interp)
79}
80
81#[inline]
82pub fn random_number(interp: &mut Artichoke, max: Option<Value>) -> Result<Value, Error> {
83    let max = interp.try_convert_mut(max)?;
84    let num = securerandom::random_number(max)?;
85    interp.try_convert_mut(num)
86}
87
88#[inline]
89pub fn uuid(interp: &mut Artichoke) -> Result<Value, Error> {
90    let uuid = securerandom::uuid()?;
91    let uuid = spinoso_string::String::ascii(uuid.into_bytes());
92    spinoso_string::String::alloc_value(uuid, interp)
93}