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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
//! This is an experimental implementation of a web-based async runtime. Web as
//! in "browser".
//!
//! Ideally, with this crate, the only JavaScript code you'll need to write
//! would be something like this:
//!
//! ```javascript
//! import * as wasm from "my-wasm-crate";
//! import * as style from "./style.css";
//!
//! wasm.main();
//! ```
//!
//! That's it (ignoring webpack configuration file, of course).
//!
//! # Examples
//!
//! ## Asynchronous "Is Prime" Test
//!
//! I know this is not the best example, because primality test is CPU-bound,
//! but I wanted to show an example of CPU-bound tasks running fast in WASM
//! without blocking the browser, i.e. by pausing periodically and giving
//! control back to browser by a few milliseconds.
//!
//! The full example can be seen in `examples/isprime` directory.
//!
//! A few numbers to try: `7399329281`, `2199023255551`, `9410454606139`,
//! `64954802446103`, `340845657750593`, `576460752303423487`,
//! `2305843009213693951`.
//!
//! ```no_run
//! use std::time::Duration;
//! use num::{BigUint, Zero};
//! use wasm_bindgen::JsValue;
//! use webio::event::{self, EventType};
//!
//! /// Number of steps before yielding control back to browser when testing
//! /// whether a number is prime or not, in order not to freeze the browser with
//! /// computations on large numbers. Of course, yielding back to the browser is
//! /// just a pause, so after a few milliseconds later, WASM can resume its job on
//! /// the current number.
//! ///
//! /// However, note that this applies only when a number is being tested,
//! /// otherwise WASM sleeps and won't wake up until the button is pressed.
//! const YIELD_STEPS: u16 = 20000;
//!
//! /// Tests if the given number is prime, asynchronous because it will pause the
//! /// execution after some steps.
//! async fn is_prime(number: &BigUint) -> bool {
//! let two = BigUint::from(2u8);
//! if *number < two {
//! return false;
//! }
//! if *number == two {
//! return true;
//! }
//! if (number % &two).is_zero() {
//! return false;
//! }
//! let mut attempt = BigUint::from(3u8);
//! let mut square = &attempt * &attempt;
//!
//! while square <= *number {
//! if (number % &attempt).is_zero() {
//! return false;
//! }
//! if (&attempt / &two % YIELD_STEPS).is_zero() {
//! webio::time::timeout(Duration::from_millis(10)).await;
//! }
//! attempt += &two;
//! square = &attempt * &attempt;
//! }
//!
//! true
//! }
//!
//! /// Main function of this WASM application.
//! #[webio::main]
//! pub async fn app_main() {
//! // Gets all necessary HTML elements.
//! let document = web_sys::window().unwrap().document().unwrap();
//! let input_raw = document.get_element_by_id("input").unwrap();
//! let input = web_sys::HtmlInputElement::from(JsValue::from(input_raw));
//! let button = document.get_element_by_id("button").unwrap();
//! let answer_elem = document.get_element_by_id("answer").unwrap();
//!
//! // Sets a listener for the click event on the button.
//! let listener = event::Click.add_listener(&button);
//!
//! loop {
//! // No problem being an infinite loop because it is asynchronous.
//! // It won't block the browser.
//! //
//! // This will sleep until the user press a button.
//! listener.listen_next().await.unwrap();
//!
//! // Cleans up previous message.
//! answer_elem.set_text_content(Some("Loading..."));
//! // Gets and validates input.
//! let number: BigUint = match input.value().parse() {
//! Ok(number) => number,
//! Err(_) => {
//! answer_elem.set_text_content(Some("Invalid input!"));
//! continue;
//! },
//! };
//!
//! // Runs and tells the user the correct answer.
//! if is_prime(&number).await {
//! answer_elem.set_text_content(Some("Yes"));
//! } else {
//! answer_elem.set_text_content(Some("No"));
//! }
//! }
//! }
//! ```
#![warn(missing_docs)]
#![cfg_attr(feature = "feature-doc-cfg", feature(doc_cfg))]
#[doc(hidden)]
#[cfg(feature = "macros")]
#[cfg_attr(feature = "feature-doc-cfg", doc(cfg(feature = "macros")))]
extern crate self as webio;
#[doc(hidden)]
#[cfg(feature = "macros")]
#[cfg_attr(feature = "feature-doc-cfg", doc(cfg(feature = "macros")))]
pub use console_error_panic_hook::set_once as set_test_panic_hook;
#[cfg(feature = "macros")]
#[cfg_attr(feature = "feature-doc-cfg", doc(cfg(feature = "macros")))]
pub use webio_macros::{console, join, main, select, test, try_join};
#[cfg(all(feature = "macros", feature = "event"))]
#[cfg_attr(
feature = "feature-doc-cfg",
doc(cfg(all(feature = "macros", feature = "event")))
)]
pub use webio_macros::EventType;
#[doc(hidden)]
#[cfg(feature = "macros")]
#[cfg_attr(feature = "feature-doc-cfg", doc(cfg(feature = "macros")))]
pub use js_sys;
#[doc(hidden)]
#[cfg(feature = "macros")]
#[cfg_attr(feature = "feature-doc-cfg", doc(cfg(feature = "macros")))]
pub use wasm_bindgen;
#[doc(hidden)]
#[cfg(feature = "macros")]
#[cfg_attr(feature = "feature-doc-cfg", doc(cfg(feature = "macros")))]
pub use wasm_bindgen_futures;
#[doc(hidden)]
#[cfg(feature = "macros")]
#[cfg_attr(feature = "feature-doc-cfg", doc(cfg(feature = "macros")))]
pub use wasm_bindgen_test;
#[doc(hidden)]
#[cfg(feature = "macros")]
#[cfg_attr(feature = "feature-doc-cfg", doc(cfg(feature = "macros")))]
pub use web_sys;
#[macro_use]
mod macros;
pub mod task;
pub mod callback;
pub mod sync;
#[cfg(feature = "time")]
#[cfg_attr(feature = "feature-doc-cfg", doc(cfg(feature = "time")))]
pub mod time;
#[cfg(feature = "event")]
#[cfg_attr(feature = "feature-doc-cfg", doc(cfg(feature = "event")))]
pub mod event;