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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//! # gwasm-api - gWasm API for Rust apps
//! [gWasm](https://docs.golem.network/#/Products/Brass-Beta/gWASM) is Golem's new
//! meta use-case which allows Golem's developers/users to deploy their Wasm apps
//! on Golem Network. This API providers convenience structures and functions for
//! creating a gWasm task and connecting with Golem Network all from native Rust code.
//!
//! ## Example
//!
//! ```rust,no_run
//! use gwasm_api::prelude::*;
//! use anyhow::Result;
//! use std::path::Path;
//!
//! struct ProgressTracker;
//!
//! impl ProgressUpdate for ProgressTracker {
//!     fn update(&mut self, progress: f64) {
//!         println!("Current progress = {}", progress);
//!     }
//! }
//!
//! fn main() -> Result<()> {
//!     let binary = GWasmBinary {
//!         js: &[0u8; 100],   // JavaScript file generated by Emscripten
//!         wasm: &[0u8; 100], // Wasm binary generated by Emscripten
//!     };
//!     let task = TaskBuilder::new("workspace", binary)
//!         .push_subtask_data(vec![0u8; 100])
//!         .build()?;
//!     let computed_task = compute(
//!         Path::new("datadir"),
//!         "127.0.0.1",
//!         61000,
//!         Net::TestNet,
//!         task,
//!         ProgressTracker,
//!     )?;
//!
//!     for subtask in computed_task.subtasks {
//!         for (_, reader) in subtask.data {
//!             assert!(!reader.buffer().is_empty());
//!         }
//!     }
//!
//!     Ok(())
//! }
//! ```
//!
//! ## More examples
//! * [g-flite](https://github.com/golemfactory/g-flite) is a CLI which uses `gwasm-api`
//!   internally
#![deny(
    missing_docs,
    trivial_numeric_casts,
    unused_extern_crates,
    unstable_features
)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../clippy.toml")))]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        clippy::float_arithmetic,
        clippy::mut_mut,
        clippy::nonminimal_bool,
        clippy::option_map_unwrap_or,
        clippy::option_map_unwrap_or_else,
        clippy::unicode_not_nfc,
        clippy::use_self
    )
)]

pub mod error;
pub mod golem;
pub mod task;
pub mod timeout;

use actix::System;
use error::Error;
pub use golem_rpc_api::Net;
use std::path::Path;
use task::{ComputedTask, Task};

pub(crate) type Result<T> = std::result::Result<T, Error>;

/// Trait specifying the required interface for an object tracking the computation's
/// progress
///
/// Note that progress is tracked via active polling thus it might be prudent to store
/// the value of current progress in the struct implementing the trait and update it
/// only when the new reported progress value has actually risen
/// (see [Example: ProgressBar](#example-progressbar)).
///
/// # Example: simple tracker
/// ```
/// use gwasm_api::ProgressUpdate;
///
/// struct SimpleTracker;
///
/// impl ProgressUpdate for SimpleTracker {
///     fn update(&mut self, progress: f64) {
///         println!("Current progress = {}", progress);
///     }
/// }
/// ```
///
/// # Example: ProgressBar
/// ```
/// use gwasm_api::ProgressUpdate;
/// use indicatif::ProgressBar;
///
/// struct ProgressBarTracker {
///     bar: ProgressBar,
///     progress: f64,
/// }
///
/// impl ProgressBarTracker {
///     fn new(num_subtasks: u64) -> Self {
///         Self {
///             bar: ProgressBar::new(num_subtasks),
///             progress: 0.0,
///         }
///     }
/// }
///
/// impl ProgressUpdate for ProgressBarTracker {
///     fn update(&mut self, progress: f64) {
///         if progress > self.progress {
///             self.progress = progress;
///             self.bar.inc(1);
///         }
///     }
///
///     fn start(&mut self) {
///         self.bar.inc(0);
///     }
///
///     fn stop(&mut self) {
///         self.bar.finish_and_clear()
///     }
/// }
/// ```
pub trait ProgressUpdate {
    /// Called when progress value was polled from Golem
    fn update(&mut self, progress: f64);
    /// Called when progress updates started
    fn start(&mut self) {}
    /// Called when progress updates finished
    fn stop(&mut self) {}
}

/// A convenience function for running a gWasm [`Task`] on Golem
///
/// The function uses actix's `System` to spawn an event loop in the current thread,
/// and blocks until either a gWasm [`Task`] is computed, or it registers a Ctrl-C event,
/// or there was an [`Error`].
///
/// [`Task`]: task/struct.Task.html
/// [`Error`]: error/enum.Error.html
pub fn compute<P, S>(
    datadir: P,
    address: S,
    port: u16,
    net: Net,
    task: Task,
    progress_handler: impl ProgressUpdate + 'static,
) -> Result<ComputedTask>
where
    P: AsRef<Path>,
    S: AsRef<str>,
{
    let mut system = System::new(task.name());
    system.block_on(golem::compute(
        datadir,
        address,
        port,
        task,
        net,
        progress_handler,
        None,
    ))
}

pub mod prelude {
    //! The `gwasm-api` prelude
    //!
    //! The purpose of this module is to alleviate imports of common structures and functions
    //! by adding a glob import to the top of the `gwasm-api` heavy modules:
    //!
    //! ```
    //! # #![allow(unused_imports)]
    //! use gwasm_api::prelude::*;
    //! ```
    pub use super::error::Error;
    pub use super::task::{
        ComputedSubtask, ComputedTask, GWasmBinary, Options, Subtask, Task, TaskBuilder,
    };
    pub use super::timeout::Timeout;
    pub use super::{compute, Net, ProgressUpdate};
}