1 // Copyright 2018 Developers of the Rand project.
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
9 //! Implementation for WASM via stdweb
12 use stdweb
::unstable
::TryInto
;
13 use stdweb
::web
::error
::Error
as WebError
;
14 use rand_core
::{Error, ErrorKind}
;
17 #[derive(Clone, Debug)]
23 #[derive(Clone, Debug)]
24 pub struct OsRng(OsRngMethod
);
26 impl OsRngImpl
for OsRng
{
27 fn new() -> Result
<OsRng
, Error
> {
31 typeof self === "object" &&
32 typeof self.crypto
=== "object" &&
33 typeof self.crypto
.getRandomValues
=== "function"
35 return { success: true, ty: 1 }
;
38 if (typeof require("crypto").randomBytes
=== "function") {
39 return { success: true, ty: 2 }
;
42 return { success: false, error: new Error("not supported") }
;
44 return { success: false, error: err }
;
48 if js
!{ return @{ result.as_ref() }
.success
} == true {
49 let ty
= js
!{ return @{ result }
.ty
};
51 if ty
== 1 { Ok(OsRng(OsRngMethod::Browser)) }
52 else if ty
== 2 { Ok(OsRng(OsRngMethod::Node)) }
53 else { unreachable!() }
55 let err
: WebError
= js
!{ return @{ result }
.error
}.try_into().unwrap();
56 Err(Error
::with_cause(ErrorKind
::Unavailable
, "WASM Error", err
))
61 fn fill_chunk(&mut self, dest
: &mut [u8]) -> Result
<(), Error
> {
62 assert_eq
!(mem
::size_of
::<usize>(), 4);
64 let len
= dest
.len() as u32;
65 let ptr
= dest
.as_mut_ptr() as i32;
67 let result
= match self.0 {
68 OsRngMethod
::Browser
=> js
! {
70 let array
= new
Uint8Array(@{ len }
);
71 self.crypto
.getRandomValues(array
);
72 HEAPU8
.set(array
, @{ ptr }
);
74 return { success: true }
;
76 return { success: false, error: err }
;
79 OsRngMethod
::Node
=> js
! {
81 let bytes
= require("crypto").randomBytes(@{ len }
);
82 HEAPU8
.set(new
Uint8Array(bytes
), @{ ptr }
);
84 return { success: true }
;
86 return { success: false, error: err }
;
91 if js
!{ return @{ result.as_ref() }
.success
} == true {
94 let err
: WebError
= js
!{ return @{ result }
.error
}.try_into().unwrap();
95 Err(Error
::with_cause(ErrorKind
::Unexpected
, "WASM Error", err
))
99 fn max_chunk_size(&self) -> usize { 65536 }
101 fn method_str(&self) -> &'
static str {
103 OsRngMethod
::Browser
=> "Crypto.getRandomValues",
104 OsRngMethod
::Node
=> "crypto.randomBytes",