]> git.proxmox.com Git - cargo.git/blob - vendor/rand_os/src/wasm32_stdweb.rs
New upstream version 0.33.0
[cargo.git] / vendor / rand_os / src / wasm32_stdweb.rs
1 // Copyright 2018 Developers of the Rand project.
2 //
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.
8
9 //! Implementation for WASM via stdweb
10
11 use std::mem;
12 use stdweb::unstable::TryInto;
13 use stdweb::web::error::Error as WebError;
14 use rand_core::{Error, ErrorKind};
15 use super::OsRngImpl;
16
17 #[derive(Clone, Debug)]
18 enum OsRngMethod {
19 Browser,
20 Node
21 }
22
23 #[derive(Clone, Debug)]
24 pub struct OsRng(OsRngMethod);
25
26 impl OsRngImpl for OsRng {
27 fn new() -> Result<OsRng, Error> {
28 let result = js! {
29 try {
30 if (
31 typeof self === "object" &&
32 typeof self.crypto === "object" &&
33 typeof self.crypto.getRandomValues === "function"
34 ) {
35 return { success: true, ty: 1 };
36 }
37
38 if (typeof require("crypto").randomBytes === "function") {
39 return { success: true, ty: 2 };
40 }
41
42 return { success: false, error: new Error("not supported") };
43 } catch(err) {
44 return { success: false, error: err };
45 }
46 };
47
48 if js!{ return @{ result.as_ref() }.success } == true {
49 let ty = js!{ return @{ result }.ty };
50
51 if ty == 1 { Ok(OsRng(OsRngMethod::Browser)) }
52 else if ty == 2 { Ok(OsRng(OsRngMethod::Node)) }
53 else { unreachable!() }
54 } else {
55 let err: WebError = js!{ return @{ result }.error }.try_into().unwrap();
56 Err(Error::with_cause(ErrorKind::Unavailable, "WASM Error", err))
57 }
58 }
59
60
61 fn fill_chunk(&mut self, dest: &mut [u8]) -> Result<(), Error> {
62 assert_eq!(mem::size_of::<usize>(), 4);
63
64 let len = dest.len() as u32;
65 let ptr = dest.as_mut_ptr() as i32;
66
67 let result = match self.0 {
68 OsRngMethod::Browser => js! {
69 try {
70 let array = new Uint8Array(@{ len });
71 self.crypto.getRandomValues(array);
72 HEAPU8.set(array, @{ ptr });
73
74 return { success: true };
75 } catch(err) {
76 return { success: false, error: err };
77 }
78 },
79 OsRngMethod::Node => js! {
80 try {
81 let bytes = require("crypto").randomBytes(@{ len });
82 HEAPU8.set(new Uint8Array(bytes), @{ ptr });
83
84 return { success: true };
85 } catch(err) {
86 return { success: false, error: err };
87 }
88 }
89 };
90
91 if js!{ return @{ result.as_ref() }.success } == true {
92 Ok(())
93 } else {
94 let err: WebError = js!{ return @{ result }.error }.try_into().unwrap();
95 Err(Error::with_cause(ErrorKind::Unexpected, "WASM Error", err))
96 }
97 }
98
99 fn max_chunk_size(&self) -> usize { 65536 }
100
101 fn method_str(&self) -> &'static str {
102 match self.0 {
103 OsRngMethod::Browser => "Crypto.getRandomValues",
104 OsRngMethod::Node => "crypto.randomBytes",
105 }
106 }
107 }