From 9d12fb8204b8a4811c2e1e0823440ecf96d7ec6f Mon Sep 17 00:00:00 2001 From: Luiz Irber Date: Thu, 17 May 2018 12:32:49 -0700 Subject: [PATCH] Starting wasm --- Cargo.toml | 5 +++++ Makefile | 4 ++++ src/lib.rs | 57 ++++++++++++++++++++++++++++++++++++++++++----------- src/wasm.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 12 deletions(-) create mode 100644 src/wasm.rs diff --git a/Cargo.toml b/Cargo.toml index 563d9b9..e7c1212 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ cbindgen = "0.6.0" [dependencies] backtrace = "0.3.4" +cfg-if = "0.1" error-chain = "0.12" finch = { version = "0.1.6", optional = true } lazy_static = "1.0.0" @@ -32,3 +33,7 @@ ordslice = "0.2.0" serde = "1.0" serde_derive = "1.0" serde_json = "1.0.2" + +#TODO: wasm-pack can't check optionals or this kind of config yet... +# [target. 'cfg(target_arch = "wasm32")'.dependencies] +wasm-bindgen = "0.2" diff --git a/Makefile b/Makefile index 13b258b..b2d7b7f 100644 --- a/Makefile +++ b/Makefile @@ -8,4 +8,8 @@ target/sourmash.h: src/lib.rs src/ffi.rs src/errors.rs RUST_BACKTRACE=1 CARGO_EXPAND_TARGET_DIR=${tempdir} cbindgen -c cbindgen.toml -o $@ -rm -rf ${tempdir} +wasm: +# wasm-pack init --mode no-installs + wasm-pack init + .phony: test diff --git a/src/lib.rs b/src/lib.rs index 1b828c5..f2b1061 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,12 @@ +#![cfg_attr( + target_arch = "wasm32", + feature(use_extern_macros, wasm_custom_section, wasm_import_module) +)] + extern crate backtrace; +#[macro_use] +extern crate cfg_if; + extern crate md5; extern crate murmurhash3; extern crate ordslice; @@ -29,9 +37,6 @@ pub mod ffi; #[cfg(feature = "from-finch")] pub mod from; -use serde::de::{Deserialize, Deserializer}; -use serde::ser::{Serialize, SerializeStruct, Serializer}; - use std::collections::HashMap; use std::collections::HashSet; use std::hash::{BuildHasherDefault, Hasher}; @@ -40,6 +45,8 @@ use std::str; use murmurhash3::murmurhash3_x64_128; use ordslice::Ext; +use serde::de::{Deserialize, Deserializer}; +use serde::ser::{Serialize, SerializeStruct, Serializer}; use errors::{ErrorKind, Result}; @@ -72,15 +79,37 @@ impl Hasher for NoHashHasher { } } -#[derive(Debug, Clone, PartialEq)] -pub struct KmerMinHash { - pub num: u32, - pub ksize: u32, - pub is_protein: bool, - pub seed: u64, - pub max_hash: u64, - pub mins: Vec, - pub abunds: Option>, +cfg_if! { + if #[cfg(target_arch = "wasm32")] { + extern crate wasm_bindgen; + + use wasm_bindgen::prelude::*; + + pub mod wasm; + + #[wasm_bindgen] + #[derive(Debug, Clone, PartialEq)] + pub struct KmerMinHash { + pub num: u32, + pub ksize: u32, + pub is_protein: bool, + pub seed: u64, + pub max_hash: u64, + mins: Vec, + abunds: Option>, + } + } else { + #[derive(Debug, Clone, PartialEq)] + pub struct KmerMinHash { + pub num: u32, + pub ksize: u32, + pub is_protein: bool, + pub seed: u64, + pub max_hash: u64, + pub mins: Vec, + pub abunds: Option>, + } + } } impl Default for KmerMinHash { @@ -531,6 +560,10 @@ impl KmerMinHash { return Ok(0.0); } } + + pub fn to_vec(&self) -> Vec { + self.mins.clone() + } } #[derive(Serialize, Deserialize, Debug)] diff --git a/src/wasm.rs b/src/wasm.rs new file mode 100644 index 0000000..757635d --- /dev/null +++ b/src/wasm.rs @@ -0,0 +1,50 @@ +use wasm_bindgen::prelude::*; + +use serde_json; + +use KmerMinHash; + +#[wasm_bindgen] +impl KmerMinHash { + #[wasm_bindgen(constructor)] + pub fn new_with_scaled( + num: u32, + ksize: u32, + is_protein: bool, + seed: u32, + scaled: u32, + track_abundance: bool, + ) -> KmerMinHash { + let max_hash = if num != 0 { + 0 + } else if scaled == 0 { + u64::max_value() + } else { + u64::max_value() / scaled as u64 + }; + + KmerMinHash::new( + num, + ksize, + is_protein, + seed as u64, + max_hash, + track_abundance, + ) + } + + #[wasm_bindgen] + pub fn add_sequence_js(&mut self, buf: &str) { + self.add_sequence(buf.as_bytes(), true); + } + + #[wasm_bindgen] + pub fn add_hash_js(&mut self, h: u64) { + self.add_hash(h); + } + + #[wasm_bindgen] + pub fn to_json(&mut self) -> String { + serde_json::to_string(self).unwrap() + } +}