diff --git a/Cargo.lock b/Cargo.lock index 69ffde3e..6ae31bbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -176,16 +176,6 @@ name = "constant_time_eq" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "cpython" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cranelift-bforest" version = "0.30.0" @@ -287,6 +277,15 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ctor" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "digest" version = "0.8.0" @@ -369,6 +368,16 @@ dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ghost" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "glob" version = "0.2.11" @@ -402,6 +411,26 @@ name = "indexmap" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "inventory" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ctor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ghost 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "inventory-impl 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inventory-impl" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.4.3" @@ -452,6 +481,24 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mashup" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mashup-impl" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "memchr" version = "2.2.0" @@ -566,6 +613,19 @@ name = "peeking_take_while" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "proc-macro-hack" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-hack-impl" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" version = "0.4.27" @@ -575,12 +635,39 @@ dependencies = [ ] [[package]] -name = "python3-sys" -version = "0.2.1" +name = "pyo3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "inventory 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pyo3cls 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pyo3-derive-backend" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pyo3cls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "pyo3-derive-backend 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -847,6 +934,11 @@ name = "smallvec" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "spin" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -966,14 +1058,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "wasmer" version = "0.1.4" dependencies = [ - "cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-runtime 0.2.1 (git+https://github.com/wasmerio/wasmer)", + "pyo3 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmer-clif-backend" -version = "0.2.0" -source = "git+https://github.com/wasmerio/wasmer#870faf983868b5c017537df49d2fc5ab9c0e1d28" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "cranelift-codegen 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -989,27 +1082,27 @@ dependencies = [ "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-runtime-core 0.2.1 (git+https://github.com/wasmerio/wasmer)", - "wasmer-win-exception-handler 0.2.0 (git+https://github.com/wasmerio/wasmer)", + "wasmer-runtime-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-win-exception-handler 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmer-runtime" -version = "0.2.1" -source = "git+https://github.com/wasmerio/wasmer#870faf983868b5c017537df49d2fc5ab9c0e1d28" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-clif-backend 0.2.0 (git+https://github.com/wasmerio/wasmer)", - "wasmer-runtime-core 0.2.1 (git+https://github.com/wasmerio/wasmer)", + "wasmer-clif-backend 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmer-runtime-core" -version = "0.2.1" -source = "git+https://github.com/wasmerio/wasmer#870faf983868b5c017537df49d2fc5ab9c0e1d28" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "blake2b_simd 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1022,6 +1115,7 @@ dependencies = [ "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1032,14 +1126,14 @@ dependencies = [ [[package]] name = "wasmer-win-exception-handler" -version = "0.2.0" -source = "git+https://github.com/wasmerio/wasmer#870faf983868b5c017537df49d2fc5ab9c0e1d28" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-runtime-core 0.2.1 (git+https://github.com/wasmerio/wasmer)", + "wasmer-runtime-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1130,7 +1224,6 @@ dependencies = [ "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "96210eec534fc3fbfc0452a63769424eaa80205fda6cea98e5b61cb3d97bcec8" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b489034e723e7f5109fecd19b719e664f89ef925be785885252469e9822fa940" "checksum cranelift-bforest 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5a357d20666bf4a8c2d626a19f1b59dbca66cd844fb1e66c5612254fd0f7505" "checksum cranelift-codegen 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab00cb149a5bb0f7e6dd391357356a5d71c335a431e8eece94f32da2d5a043f7" "checksum cranelift-codegen-meta 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3797a2f450ac71297e083dd440d0cdd0d3bceabe4a3ca6bcb9e4077e9c0327d" @@ -1141,6 +1234,7 @@ dependencies = [ "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum ctor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "e5cc1c7c759bf979c651ce1da82d06065375e2223b65c070190b8000787da58b" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" @@ -1151,11 +1245,14 @@ dependencies = [ "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum ghost 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5297b71943dc9fea26a3241b178c140ee215798b7f79f7773fd61683e25bca74" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum inventory 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21df85981fe094480bc2267723d3dc0fd1ae0d1f136affc659b7398be615d922" +"checksum inventory-impl 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a877ae8bce77402d5e9ed870730939e097aad827b2a932b361958fa9d6e75aa" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" @@ -1163,6 +1260,8 @@ dependencies = [ "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f2d82b34c7fb11bb41719465c060589e291d505ca4735ea30016a91f6fc79c3b" +"checksum mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "aa607bfb674b4efb310512527d64266b065de3f894fc52f84efcbf7eaa5965fb" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" @@ -1177,8 +1276,12 @@ dependencies = [ "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" +"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" -"checksum python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "61e4aac43f833fd637e429506cb2ac9d7df672c4b68f2eaaa163649b7fdc0444" +"checksum pyo3 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb313941bd4d3f422151b2b2d0d2d9e86f308c2ba2d08cf0375e7cfed202e7e8" +"checksum pyo3-derive-backend 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "783639e1c566f08b19e74956c3fff4d953c0c271b39de2db22a9102fbedbeab1" +"checksum pyo3cls 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4f91eb8e5394cabd1219c29ac99f7a93103a0daf3a71df0f0b6d9c395d08a86" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" @@ -1211,6 +1314,7 @@ dependencies = [ "checksum serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc82bec244f168b23d1963b45c8bf5726e9a15a9d146a067f9081aeed2de79" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)" = "66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2" @@ -1228,10 +1332,10 @@ dependencies = [ "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasmer-clif-backend 0.2.0 (git+https://github.com/wasmerio/wasmer)" = "" -"checksum wasmer-runtime 0.2.1 (git+https://github.com/wasmerio/wasmer)" = "" -"checksum wasmer-runtime-core 0.2.1 (git+https://github.com/wasmerio/wasmer)" = "" -"checksum wasmer-win-exception-handler 0.2.0 (git+https://github.com/wasmerio/wasmer)" = "" +"checksum wasmer-clif-backend 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0afacbd83b3897e59ac7686ebeed7c39bfae20bcf150869eb695e55afe19e91a" +"checksum wasmer-runtime 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "272c74d8494e4c59dba5df3a256e7661d1684ad7d8b425b80e9fe80124def568" +"checksum wasmer-runtime-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b9fd8e1f3c4eac86563394354aee2b8dfc59a8b9f7051478dfb27bff568b668" +"checksum wasmer-win-exception-handler 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46e37084fc382f419fa06e09ffd388aa1e2eaeeb6bfa3b8edd311f3f857751e9" "checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060" "checksum wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)" = "981a8797cf89762e0233ec45fae731cb79a4dfaee12d9f0fe6cee01e4ac58d00" "checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" diff --git a/Cargo.toml b/Cargo.toml index 6862d3e7..eb97c047 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,9 @@ name = "wasmer" crate-type = ["cdylib"] [dependencies] -cpython = { version = "0.2", features = ["extension-module"] } -wasmer-runtime = { git = "https://github.com/wasmerio/wasmer", branch = "master" } +wasmer-runtime = "0.3.0" +wasmer-runtime-core = "0.3.0" +pyo3 = { version = "0.6.0", features = ["extension-module"] } [package.metadata.pyo3-pack] classifier = [ diff --git a/README.md b/README.md index 785073ad..a3f798fa 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ from wasmer import Instance, Value wasm_bytes = open('simple.wasm', 'rb').read() instance = Instance(wasm_bytes) -result = instance.call('sum', [Value.i32(5), Value.i32(37)]) +result = instance.exports.sum(5, 37) print(result) # 42! ``` @@ -88,11 +88,18 @@ wasm_bytes = open('my_program.wasm', 'rb').read() instance = Instance(wasm_bytes) # Call a function on it. -result = instance.call('sum', [Value.i32(1), Value.i32(2)]) +result = instance.exports.sum(1, 2) print(result) # 3 ``` +All exported functions are accessible on the `exports` getter. +Arguments of these functions are automatically casted to WebAssembly +values. If one wants to explicitely pass a value of a particular type, +it is possible to use the `Value` class, +e.g. `instance.exports.sum(Value.i32(1), Value.i32(2))`. Note that for +most usecases, this is not necessary. + ### The `Value` class Builds WebAssembly values with the correct types: @@ -141,7 +148,8 @@ All these classes share the same implementation. Taking the example of ```python class Uint8MemoryView: - BYTES_PER_ELEMENT = 1 + @property + def bytes_per_element() def __len__() def __getitem__(index) @@ -160,7 +168,7 @@ wasm_bytes = open('my_program.wasm', 'rb').read() instance = Instance(wasm_bytes) # Call a function that returns a pointer to a string for instance. -pointer = instance.call('return_string') +pointer = instance.exports.return_string() # Get the memory view, with the offset set to `pointer` (default is 0). memory = instance.uint8_memory_view(pointer) diff --git a/examples/memory.py b/examples/memory.py index 6a55f71e..9414adc8 100644 --- a/examples/memory.py +++ b/examples/memory.py @@ -5,7 +5,7 @@ wasm_bytes = open(__dir__ + '/memory.wasm', 'rb').read() instance = Instance(wasm_bytes) -pointer = instance.call('return_hello') +pointer = instance.exports.return_hello() memory = instance.uint8_memory_view(pointer) nth = 0; diff --git a/examples/simple.py b/examples/simple.py index ff47302e..30faeff4 100644 --- a/examples/simple.py +++ b/examples/simple.py @@ -1,10 +1,11 @@ -from wasmer import Instance, Value +from wasmer import Instance, Value, Uint8MemoryView import os __dir__ = os.path.dirname(os.path.realpath(__file__)) wasm_bytes = open(__dir__ + '/simple.wasm', 'rb').read() instance = Instance(wasm_bytes) -result = instance.call('sum', [Value.i32(5), Value.i32(37)]) + +result = instance.exports.sum(1, 2) print(result) # 42! diff --git a/justfile b/justfile index bd86d0d9..063e07f1 100644 --- a/justfile +++ b/justfile @@ -1,9 +1,9 @@ # Install the environment to develop the extension. prelude: - pip3 install pyo3-pack - cargo install pyo3-pack pip3 install virtualenv virtualenv -p $(which python3) .env + source .env/bin/activate + pip3 install pyo3-pack pytest pytest-benchmark # Setup the environment to develop the extension. wakeup: @@ -17,19 +17,19 @@ sleep: rust: export PYTHON_SYS_EXECUTABLE=$(which python3) cargo check - pyo3-pack develop --release --strip + pyo3-pack develop --binding_crate pyo3 --release --strip # Run Python. python-run file='': - .env/bin/python {{file}} + @python {{file}} # Run the tests. test: - @.env/bin/python tests/init.py + @py.test tests # Inspect the `python-ext-wasm` extension. inspect: - .env/bin/python -c "help('wasmer')" + @python -c "help('wasmer')" # Local Variables: # mode: makefile diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 00000000..07ade694 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +nightly \ No newline at end of file diff --git a/src/error.rs b/src/error.rs deleted file mode 100644 index 9e42dfcf..00000000 --- a/src/error.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! Utils to manipulate Python errors.o - -use cpython::{exc::RuntimeError, PyErr, Python, PythonObject, ToPyObject}; - -/// Create a `RuntimeError` error in Python. -/// -/// # Examples -/// -/// ```rs,ignore -/// fn f(py: Python) -> PyResult<()> { -/// let error = new_runtime_error(py, "foobar"); -/// Err(error) -/// } -/// ``` -pub fn new_runtime_error(py: Python, error_message: &str) -> PyErr { - PyErr::new_lazy_init( - py.get_type::(), - Some(error_message.to_py_object(py).into_object()), - ) -} diff --git a/src/instance.rs b/src/instance.rs index a86bb3b2..885fa95b 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -1,124 +1,252 @@ //! The `Instance` Python object to build WebAssembly instances. -use crate::{ - error::new_runtime_error, - memory_view, - value::{get_wasm_value, wasm_value_into_python_object, Value}, - Shell, -}; -use cpython::{PyBytes, PyObject, PyResult, Python}; -use wasmer_runtime::{ - self as runtime, imports, instantiate, validate as wasm_validate, Export, Memory, - Value as WasmValue, +use crate::{memory_view, value::Value}; +use pyo3::{ + class::basic::PyObjectProtocol, + exceptions::{LookupError, RuntimeError}, + prelude::*, + types::{PyAny, PyBytes, PyFloat, PyLong, PyTuple}, + PyNativeType, PyTryFrom, ToPyObject, }; +use std::rc::Rc; +use wasmer_runtime::{self as runtime, imports, instantiate, Export, Memory, Value as WasmValue}; +use wasmer_runtime_core::types::Type; + +#[pyclass] +pub struct ExportedFunction { + function_name: String, + instance: Rc, +} -/// The Python `Instance` class. -/// -/// # Examples -/// -/// ```python,ignore -/// from wasmer import Instance, Value -/// -/// file = open('my_program.wasm', 'rb') # note the mode contains `b` to get bytes, and not UTF-8 characters. -/// bytes = file.read() -/// -/// instance = Instance(bytes) -/// result = instance.call('add_one', [Value::from_i32(1)]) -/// ``` -py_class!(pub class Instance |py| { - data instance: Shell; - - def __new__(_cls, bytes: PyBytes) -> PyResult { - let bytes = bytes.data(py); - let imports = imports! {}; - let instance = match instantiate(bytes, &imports) { - Ok(instance) => instance, - Err(e) => return Err(new_runtime_error(py, &format!("Failed to instantiate the module:\n {}", e))) +#[pymethods] +impl ExportedFunction { + #[call] + #[args(arguments = "*")] + fn __call__(&self, py: Python, arguments: &PyTuple) -> PyResult { + let function = match self.instance.dyn_func(&self.function_name) { + Ok(function) => function, + Err(_) => { + return Err(RuntimeError::py_err(format!( + "Function `{}` does not exist.", + self.function_name + ))) + } }; - Instance::create_instance(py, Shell::new(instance)) + let signature = function.signature(); + let parameters = signature.params(); + let number_of_parameters = parameters.len() as isize; + let number_of_arguments = arguments.len() as isize; + let diff: isize = number_of_parameters - number_of_arguments; + + if diff > 0 { + return Err(RuntimeError::py_err(format!( + "Missing {} argument(s) when calling `{}`: Expect {} argument(s), given {}.", + diff, self.function_name, number_of_parameters, number_of_arguments + ))); + } else if diff < 0 { + return Err(RuntimeError::py_err(format!( + "Given {} extra argument(s) when calling `{}`: Expect {} argument(s), given {}.", + diff.abs(), + self.function_name, + number_of_parameters, + number_of_arguments + ))); + } + + let mut function_arguments = Vec::::with_capacity(number_of_parameters as usize); + + for (parameter, argument) in parameters.iter().zip(arguments.iter()) { + let value = match argument.downcast_ref::() { + Ok(value) => value.value.clone(), + Err(_) => match parameter { + Type::I32 => { + WasmValue::I32(argument.downcast_ref::()?.extract::()?) + } + Type::I64 => { + WasmValue::I64(argument.downcast_ref::()?.extract::()?) + } + Type::F32 => { + WasmValue::F32(argument.downcast_ref::()?.extract::()?) + } + Type::F64 => { + WasmValue::F64(argument.downcast_ref::()?.extract::()?) + } + }, + }; + + function_arguments.push(value); + } + + let results = match function.call(function_arguments.as_slice()) { + Ok(results) => results, + Err(e) => return Err(RuntimeError::py_err(format!("{}", e))), + }; + + Ok(match results[0] { + WasmValue::I32(result) => result.to_object(py), + WasmValue::I64(result) => result.to_object(py), + WasmValue::F32(result) => result.to_object(py), + WasmValue::F64(result) => result.to_object(py), + }) + } +} + +#[pyclass] +pub struct ExportedFunctions { + instance: Rc, + functions: Vec, +} + +#[pyproto] +impl PyObjectProtocol for ExportedFunctions { + fn __getattr__(&self, key: String) -> PyResult { + if self.functions.contains(&key) { + Ok(ExportedFunction { + function_name: key, + instance: self.instance.clone(), + }) + } else { + Err(LookupError::py_err(format!( + "Function `{}` does not exist.", + key + ))) + } } - def call(&self, function_name: &str, function_arguments: Vec = Vec::new()) -> PyResult { - let function_arguments: Vec = - function_arguments - .into_iter() - .map(|value_object| get_wasm_value(py, &value_object)) - .collect(); + fn __repr__(&self) -> PyResult { + Ok(format!("{:?}", self.functions)) + } +} - let instance = self.instance(py); - let function = match instance.dyn_func(function_name) { - Ok(function) => function, - Err(_) => return Err(new_runtime_error(py, &format!("Function `{}` does not exist.", function_name))) - }; +#[pyclass] +pub struct Instance { + instance: Rc, + exports: Py, +} - let results = match function.call(function_arguments.as_slice()) { - Ok(results) => results, - Err(e) => return Err(new_runtime_error(py, &format!("{}", e))) +#[pymethods] +impl Instance { + #[new] + fn new(object: &PyRawObject, bytes: &PyAny) -> PyResult<()> { + let bytes = ::try_from(bytes)?.as_bytes(); + let imports = imports! {}; + let instance = match instantiate(bytes, &imports) { + Ok(instance) => Rc::new(instance), + Err(e) => { + return Err(RuntimeError::py_err(format!( + "Failed to instantiate the module:\n {}", + e + ))) + } }; - Ok(wasm_value_into_python_object(py, &results[0])) + let py = object.py(); + let mut exported_functions = Vec::new(); + + for (export_name, export) in instance.exports() { + if let Export::Function { .. } = export { + exported_functions.push(export_name); + } + } + + object.init({ + Self { + instance: instance.clone(), + exports: Py::new( + py, + ExportedFunctions { + instance: instance.clone(), + functions: exported_functions, + }, + )?, + } + }); + + Ok(()) } - def uint8_memory_view(&self, offset: usize = 0) -> PyResult { - get_instance_memory(&self, py) - .map_or_else( - || Err(new_runtime_error(py, "No memory exported.")), - |memory| Ok(memory_view::new_uint8_memory_view(py, memory, offset)) - ) + #[getter] + fn exports(&self) -> PyResult<&Py> { + Ok(&self.exports) } - def int8_memory_view(&self, offset: usize = 0) -> PyResult { - get_instance_memory(&self, py) - .map_or_else( - || Err(new_runtime_error(py, "No memory exported.")), - |memory| Ok(memory_view::new_int8_memory_view(py, memory, offset)) - ) + #[args(offset = 0)] + fn uint8_memory_view( + &self, + py: Python, + offset: usize, + ) -> PyResult> { + get_instance_memory(&self).map_or_else( + || Err(RuntimeError::py_err("No memory exported.")), + |memory| Py::new(py, memory_view::Uint8MemoryView { memory, offset }), + ) } - def uint16_memory_view(&self, offset: usize = 0) -> PyResult { - get_instance_memory(&self, py) - .map_or_else( - || Err(new_runtime_error(py, "No memory exported.")), - |memory| Ok(memory_view::new_uint16_memory_view(py, memory, offset)) - ) + #[args(offset = 0)] + fn int8_memory_view( + &self, + py: Python, + offset: usize, + ) -> PyResult> { + get_instance_memory(&self).map_or_else( + || Err(RuntimeError::py_err("No memory exported.")), + |memory| Py::new(py, memory_view::Int8MemoryView { memory, offset }), + ) } - def int16_memory_view(&self, offset: usize = 0) -> PyResult { - get_instance_memory(&self, py) - .map_or_else( - || Err(new_runtime_error(py, "No memory exported.")), - |memory| Ok(memory_view::new_int16_memory_view(py, memory, offset)) - ) + #[args(offset = 0)] + fn uint16_memory_view( + &self, + py: Python, + offset: usize, + ) -> PyResult> { + get_instance_memory(&self).map_or_else( + || Err(RuntimeError::py_err("No memory exported.")), + |memory| Py::new(py, memory_view::Uint16MemoryView { memory, offset }), + ) } - def uint32_memory_view(&self, offset: usize = 0) -> PyResult { - get_instance_memory(&self, py) - .map_or_else( - || Err(new_runtime_error(py, "No memory exported.")), - |memory| Ok(memory_view::new_uint32_memory_view(py, memory, offset)) - ) + #[args(offset = 0)] + fn int16_memory_view( + &self, + py: Python, + offset: usize, + ) -> PyResult> { + get_instance_memory(&self).map_or_else( + || Err(RuntimeError::py_err("No memory exported.")), + |memory| Py::new(py, memory_view::Int16MemoryView { memory, offset }), + ) } - def int32_memory_view(&self, offset: usize = 0) -> PyResult { - get_instance_memory(&self, py) - .map_or_else( - || Err(new_runtime_error(py, "No memory exported.")), - |memory| Ok(memory_view::new_int32_memory_view(py, memory, offset)) - ) + #[args(offset = 0)] + fn uint32_memory_view( + &self, + py: Python, + offset: usize, + ) -> PyResult> { + get_instance_memory(&self).map_or_else( + || Err(RuntimeError::py_err("No memory exported.")), + |memory| Py::new(py, memory_view::Uint32MemoryView { memory, offset }), + ) } -}); -/// The Python `validate` function. -/// -/// -pub fn validate(py: Python, bytes: PyBytes) -> PyResult { - Ok(wasm_validate(bytes.data(py))) + #[args(offset = 0)] + fn int32_memory_view( + &self, + py: Python, + offset: usize, + ) -> PyResult> { + get_instance_memory(&self).map_or_else( + || Err(RuntimeError::py_err("No memory exported.")), + |memory| Py::new(py, memory_view::Int32MemoryView { memory, offset }), + ) + } } -fn get_instance_memory(instance: &Instance, py: Python) -> Option { +fn get_instance_memory(instance: &Instance) -> Option { instance - .instance(py) + .instance .exports() .find_map(|(_, export)| match export { Export::Memory(memory) => Some(memory), diff --git a/src/lib.rs b/src/lib.rs index d1dcad85..21132bf0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,75 +1,43 @@ #![deny(warnings)] -#[macro_use] -extern crate cpython; +use pyo3::{ + prelude::*, + types::{PyAny, PyBytes}, + wrap_pyfunction, PyTryFrom, +}; +use wasmer_runtime::validate as wasm_validate; -use cpython::PyBytes; -use std::{ops::Deref, thread}; - -mod error; mod instance; mod memory_view; mod value; -use instance::{validate, Instance}; +use instance::Instance; use value::Value; -/// A `Shell` is a thread-safe wrapper over a value `T` that will fail -/// if used in another thread. Why? All data used by Python must be -/// thread-safe. However some WebAssembly data cannot be thread-safe, -/// like unshared memory. With a `Shell`, the program will compile and -/// Python will be able to use the value `T`, but it must not be -/// passed between threads. The documentation will specify it. -pub struct Shell { - /// The thread ID where the datum has been created. - thread_id: thread::ThreadId, +/// This extension allows to manipulate and to execute WebAssembly binaries. +#[pymodule] +fn wasmer(_py: Python, module: &PyModule) -> PyResult<()> { + module.add_wrapped(wrap_pyfunction!(validate))?; + module.add_class::()?; + module.add_class::()?; + module.add_class::()?; + module.add_class::()?; + module.add_class::()?; + module.add_class::()?; + module.add_class::()?; + module.add_class::()?; - /// The datum. - value: T, + Ok(()) } -impl Shell { - pub fn new(value: T) -> Self { - Self { - thread_id: thread::current().id(), - value, - } +/// validate(bytes, /) +/// -- +/// +/// Check a WebAssembly module is valid. +#[pyfunction] +pub fn validate(bytes: &PyAny) -> PyResult { + match ::try_from(bytes) { + Ok(bytes) => Ok(wasm_validate(bytes.as_bytes())), + _ => Ok(false), } } - -/// A `Shell` is sendable. -unsafe impl Send for Shell {} - -/// Dereferences the value if it's inside the same thread than the -/// creation thread. -impl Deref for Shell { - type Target = T; - - fn deref(&self) -> &Self::Target { - if thread::current().id() != self.thread_id { - panic!("The current `Shell` cannot be dereferenced in a different thread."); - } - - &self.value - } -} - -// Declare the module. -py_module_initializer!(libwasmer, initlibwasmer, PyInit_wasmer, |python, module| { - module.add( - python, - "__doc__", - "This extension allows to manipulate and to execute WebAssembly binaries.", - )?; - module.add_class::(python)?; - module.add_class::(python)?; - module.add_class::(python)?; - module.add_class::(python)?; - module.add_class::(python)?; - module.add_class::(python)?; - module.add_class::(python)?; - module.add_class::(python)?; - module.add(python, "validate", py_fn!(python, validate(bytes: PyBytes)))?; - - Ok(()) -}); diff --git a/src/memory_view.rs b/src/memory_view.rs index 5da1de64..334019ce 100644 --- a/src/memory_view.rs +++ b/src/memory_view.rs @@ -1,79 +1,85 @@ //! The `Buffer` Python object to build WebAssembly values. -use crate::{error::new_runtime_error, Shell}; -use cpython::{PyResult, Python}; +use pyo3::{class::PyMappingProtocol, exceptions::IndexError, prelude::*}; use std::mem::size_of; use wasmer_runtime::memory::Memory; macro_rules! memory_view { - ($class_name:ident over $wasm_type:ty [$bytes_per_element:expr], with $constructor_name:ident) => { - /// A `MemoryView` Python object represents a view over the memory - /// of a WebAssembly instance. - py_class!(pub class $class_name |py| { - static BYTES_PER_ELEMENT = $bytes_per_element; - - data memory: Shell; - data offset: usize; + ($class_name:ident over $wasm_type:ty | $bytes_per_element:expr) => { + #[pyclass] + pub struct $class_name { + pub memory: Memory, + pub offset: usize, + } - def __len__(&self) -> PyResult { - let offset = *self.offset(py); + #[pymethods] + impl $class_name { + #[getter] + fn bytes_per_element(&self) -> PyResult { + Ok($bytes_per_element) + } + } - Ok(self.memory(py).view::<$wasm_type>()[offset..].len() / size_of::<$wasm_type>()) + #[pyproto] + impl PyMappingProtocol for $class_name { + fn __len__(&self) -> PyResult { + Ok(self.memory.view::<$wasm_type>()[self.offset..].len() / size_of::<$wasm_type>()) } - def __getitem__(&self, index: usize) -> PyResult<$wasm_type> { - let offset = *self.offset(py); - let view = self.memory(py).view::<$wasm_type>(); + fn __getitem__(&self, index: isize) -> PyResult<$wasm_type> { + let offset = self.offset; + let view = self.memory.view::<$wasm_type>(); + + if index < 0 { + return Err(IndexError::py_err( + "Out of bound: Index cannot be negative.", + )); + } + + let index = index as usize; if view.len() <= offset + index { - Err( - new_runtime_error( - py, - &format!( - "Out of bound: Absolute index {} is larger than the memory size {}.", - offset + index, - view.len() - ) - ) - ) + Err(IndexError::py_err(format!( + "Out of bound: Absolute index {} is larger than the memory size {}.", + offset + index, + view.len() + ))) } else { Ok(view[offset + index].get()) } } - def __setitem__(&self, index: usize, value: $wasm_type) -> PyResult<()> { - let offset = *self.offset(py); - let view = self.memory(py).view::<$wasm_type>(); + fn __setitem__(&mut self, index: isize, value: u8) -> PyResult<()> { + let offset = self.offset; + let view = self.memory.view::(); + + if index < 0 { + return Err(IndexError::py_err( + "Out of bound: Index cannot be negative.", + )); + } + + let index = index as usize; if view.len() <= offset + index { - Err( - new_runtime_error( - py, - &format!( - "Out of bound: Absolute index {} is larger than the memory size {}.", - offset + index, - view.len() - ) - ) - ) + Err(IndexError::py_err(format!( + "Out of bound: Absolute index {} is larger than the memory size {}.", + offset + index, + view.len() + ))) } else { view[offset + index].set(value); Ok(()) } } - }); - - /// Construct a `MemoryView` Python object. - pub fn $constructor_name(py: Python, memory: Memory, offset: usize) -> $class_name { - $class_name::create_instance(py, Shell::new(memory), offset).unwrap() } }; } -memory_view!(Uint8MemoryView over u8 [1], with new_uint8_memory_view); -memory_view!(Int8MemoryView over i8 [1], with new_int8_memory_view); -memory_view!(Uint16MemoryView over u16 [2], with new_uint16_memory_view); -memory_view!(Int16MemoryView over i16 [2], with new_int16_memory_view); -memory_view!(Uint32MemoryView over u32 [4], with new_uint32_memory_view); -memory_view!(Int32MemoryView over i32 [4], with new_int32_memory_view); +memory_view!(Uint8MemoryView over u8|1); +memory_view!(Int8MemoryView over i8|1); +memory_view!(Uint16MemoryView over u16|2); +memory_view!(Int16MemoryView over i16|2); +memory_view!(Uint32MemoryView over u32|4); +memory_view!(Int32MemoryView over i32|4); diff --git a/src/value.rs b/src/value.rs index 44322677..4220ea0a 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,76 +1,48 @@ -//! The `Value` Python object to build WebAssembly values. +//! The `Value` Python class to build WebAssembly values. -use cpython::{PyObject, PyResult, Python, PythonObject, ToPyObject}; +use pyo3::{class::basic::PyObjectProtocol, prelude::*}; use wasmer_runtime::Value as WasmValue; -/// The `Value` Python object represents a WebAssembly value. -/// -/// # Examples -/// -/// ```python,ignore -/// from wasmer import Value -/// -/// value1 = Value.from_i32(42) -/// value2 = Value.from_i64(42) -/// value3 = Value.from_f32(4.2) -/// value4 = Value.from_f64(4.2) -/// -/// print(repr(value1)) // "I32(42)" -/// print(repr(value2)) // "I64(42)" -/// print(repr(value3)) // "F32(4.2)" -/// print(repr(value4)) // "F64(4.2)" -/// ``` -py_class!(pub class Value |py| { - data value: WasmValue; - - @staticmethod - def i32(value: i32) -> PyResult { - Value::create_instance( - py, - WasmValue::I32(value) - ) - } +#[pyclass] +/// The `Value` class represents a WebAssembly value. +pub struct Value { + pub value: WasmValue, +} - @staticmethod - def i64(value: i64) -> PyResult { - Value::create_instance( - py, - WasmValue::I64(value) - ) +#[pymethods] +impl Value { + #[staticmethod] + fn i32(value: i32) -> PyResult { + Ok(Self { + value: WasmValue::I32(value), + }) } - @staticmethod - def f32(value: f32) -> PyResult { - Value::create_instance( - py, - WasmValue::F32(value) - ) + #[staticmethod] + fn i64(value: i64) -> PyResult { + Ok(Self { + value: WasmValue::I64(value), + }) } - @staticmethod - def f64(value: f64) -> PyResult { - Value::create_instance( - py, - WasmValue::F64(value) - ) + #[staticmethod] + fn f32(value: f32) -> PyResult { + Ok(Self { + value: WasmValue::F32(value), + }) } - def __repr__(&self) -> PyResult { - Ok(format!("{:?}", self.value(py))) + #[staticmethod] + fn f64(value: f64) -> PyResult { + Ok(Self { + value: WasmValue::F64(value), + }) } -}); - -/// Getter to access the private `value` attribute of the `Value` Python object. -pub(crate) fn get_wasm_value(py: Python, value: &Value) -> WasmValue { - value.value(py).clone() } -/// Transform a `WasmValue` into a `PyObject`. -pub(crate) fn wasm_value_into_python_object(py: Python, wasm_value: &WasmValue) -> PyObject { - match wasm_value { - WasmValue::I32(value) => value.into_py_object(py).into_object(), - WasmValue::I64(value) => value.into_py_object(py).into_object(), - WasmValue::F32(value) => value.into_py_object(py).into_object(), - WasmValue::F64(value) => value.into_py_object(py).into_object(), +#[pyproto] +impl PyObjectProtocol for Value { + fn __repr__(&self) -> PyResult { + Ok(format!("{:?}", self.value)) } } diff --git a/tests/init.py b/tests/init.py deleted file mode 100644 index 24d5d9d4..00000000 --- a/tests/init.py +++ /dev/null @@ -1,18 +0,0 @@ -import instance -import memory_view -import unittest -import value - -def add_tests_from(suite, test_case): - suite.addTests(unittest.defaultTestLoader.loadTestsFromTestCase(test_case)) - -def suite(): - suite = unittest.TestSuite() - add_tests_from(suite, instance.TestWasmInstance) - add_tests_from(suite, memory_view.TestWasmMemoryView) - add_tests_from(suite, value.TestWasmValue) - return suite - -if __name__ == '__main__': - runner = unittest.TextTestRunner(verbosity=2); - runner.run(suite()) diff --git a/tests/instance.py b/tests/instance.py deleted file mode 100644 index 7dd6699d..00000000 --- a/tests/instance.py +++ /dev/null @@ -1,117 +0,0 @@ -from wasmer import Instance, Uint8MemoryView, Value, validate -import inspect -import os -import unittest - -here = os.path.dirname(os.path.realpath(__file__)) -TEST_BYTES = open(here + '/tests.wasm', 'rb').read() -INVALID_TEST_BYTES = open(here + '/invalid.wasm', 'rb').read() - -class TestWasmInstance(unittest.TestCase): - def test_is_a_class(self): - self.assertTrue(inspect.isclass(Instance)) - - def test_can_construct(self): - self.assertIsInstance(Instance(TEST_BYTES), Instance) - - def test_failed_to_instantiate(self): - with self.assertRaises(RuntimeError) as context_manager: - Instance(INVALID_TEST_BYTES) - - exception = context_manager.exception - self.assertEqual( - str(exception), - 'Failed to instantiate the module:\n compile error: Validation error "Invalid type"' - ) - - def test_function_does_not_exist(self): - with self.assertRaises(RuntimeError) as context_manager: - Instance(TEST_BYTES).call("foo") - - exception = context_manager.exception - self.assertEqual( - str(exception), - 'Function `foo` does not exist.' - ) - - def test_basic_sum(self): - self.assertEqual( - Instance(TEST_BYTES) - .call( - 'sum', - [ - Value.i32(1), - Value.i32(2) - ] - ), - 3 - ) - - def test_call_arity_0(self): - self.assertEqual( - Instance(TEST_BYTES).call('arity_0'), - 42 - ) - - def test_call_i32_i32(self): - self.assertEqual( - Instance(TEST_BYTES).call('i32_i32', [Value.i32(7)]), - 7 - ) - - def test_call_i64_i64(self): - self.assertEqual( - Instance(TEST_BYTES).call('i64_i64', [Value.i64(7)]), - 7 - ) - - def test_call_f32_f32(self): - self.assertEqual( - Instance(TEST_BYTES).call('f32_f32', [Value.f32(7.)]), - 7. - ) - - def test_call_f64_f64(self): - self.assertEqual( - Instance(TEST_BYTES).call('f64_f64', [Value.f64(7.)]), - 7. - ) - - def test_call_i32_i64_f32_f64_f64(self): - self.assertEqual( - round( - Instance(TEST_BYTES) - .call( - 'i32_i64_f32_f64_f64', - [ - Value.i32(1), - Value.i64(2), - Value.f32(3.4), - Value.f64(5.6) - ] - ), - 6 - ), - 1 + 2 + 3.4 + 5.6 - ) - - def test_call_bool_casted_to_i32(self): - self.assertEqual( - Instance(TEST_BYTES).call('bool_casted_to_i32'), - 1 - ) - - def test_call_string(self): - self.assertEqual( - Instance(TEST_BYTES).call('string'), - 1048576 - ) - - def test_validate(self): - self.assertTrue(validate(TEST_BYTES)) - - def test_validate_invalid(self): - self.assertFalse(validate(INVALID_TEST_BYTES)) - - def test_memory_view(self): - self.assertIsInstance(Instance(TEST_BYTES).uint8_memory_view(), Uint8MemoryView) diff --git a/tests/memory_view.py b/tests/memory_view.py deleted file mode 100644 index e8eadf57..00000000 --- a/tests/memory_view.py +++ /dev/null @@ -1,96 +0,0 @@ -from wasmer import Instance, Uint8MemoryView, Int8MemoryView, Uint16MemoryView, Int16MemoryView, Uint32MemoryView, Int32MemoryView -import inspect -import os -import unittest - -here = os.path.dirname(os.path.realpath(__file__)) -TEST_BYTES = open(here + '/tests.wasm', 'rb').read() - -class TestWasmMemoryView(unittest.TestCase): - def test_is_a_class(self): - self.assertTrue(inspect.isclass(Uint8MemoryView)) - self.assertTrue(inspect.isclass(Int8MemoryView)) - self.assertTrue(inspect.isclass(Uint16MemoryView)) - self.assertTrue(inspect.isclass(Int16MemoryView)) - self.assertTrue(inspect.isclass(Uint32MemoryView)) - self.assertTrue(inspect.isclass(Int32MemoryView)) - - def test_bytes_per_element(self): - self.assertEqual(Uint8MemoryView.BYTES_PER_ELEMENT, 1) - self.assertEqual(Int8MemoryView.BYTES_PER_ELEMENT, 1) - self.assertEqual(Uint16MemoryView.BYTES_PER_ELEMENT, 2) - self.assertEqual(Int16MemoryView.BYTES_PER_ELEMENT, 2) - self.assertEqual(Uint32MemoryView.BYTES_PER_ELEMENT, 4) - self.assertEqual(Int32MemoryView.BYTES_PER_ELEMENT, 4) - - @unittest.expectedFailure - def test_cannot_construct(self): - self.assertIsInstance(Uint8MemoryView(0), Uint8MemoryView) - - def test_length(self): - self.assertEqual( - len(Instance(TEST_BYTES).uint8_memory_view()), - 1114112 - ) - - def test_get(self): - memory = Instance(TEST_BYTES).uint8_memory_view() - index = 7 - value = 42 - memory[index] = value - - self.assertEqual(memory[index], value) - - def test_get_out_of_range(self): - with self.assertRaises(RuntimeError) as context_manager: - memory = Instance(TEST_BYTES).uint8_memory_view() - memory[len(memory) + 1] - - exception = context_manager.exception - self.assertEqual( - str(exception), - 'Out of bound: Absolute index 1114113 is larger than the memory size 1114112.' - ) - - def test_set_out_of_range(self): - with self.assertRaises(RuntimeError) as context_manager: - memory = Instance(TEST_BYTES).uint8_memory_view() - memory[len(memory) + 1] = 42 - - exception = context_manager.exception - self.assertEqual( - str(exception), - 'Out of bound: Absolute index 1114113 is larger than the memory size 1114112.' - ) - - def test_hello_world(self): - instance = Instance(TEST_BYTES) - pointer = instance.call('string') - memory = instance.uint8_memory_view(pointer) - nth = 0 - string = '' - - while (0 != memory[nth]): - string += chr(memory[nth]) - nth += 1 - - self.assertEqual(string, 'Hello, World!') - - def test_memory_views_share_the_same_buffer(self): - instance = Instance(TEST_BYTES) - int8 = instance.int8_memory_view() - int16 = instance.int16_memory_view() - int32 = instance.int32_memory_view() - - int8[0] = 0b00000001 - int8[1] = 0b00000100 - int8[2] = 0b00010000 - int8[3] = 0b01000000 - - self.assertEqual(int8[0], 0b00000001) - self.assertEqual(int8[1], 0b00000100) - self.assertEqual(int8[2], 0b00010000) - self.assertEqual(int8[3], 0b01000000) - self.assertEqual(int16[0], 0b00000100_00000001) - self.assertEqual(int16[1], 0b01000000_00010000) - self.assertEqual(int32[0], 0b01000000_00010000_00000100_00000001) diff --git a/tests/test_benchmarks.py b/tests/test_benchmarks.py new file mode 100644 index 00000000..677e6552 --- /dev/null +++ b/tests/test_benchmarks.py @@ -0,0 +1,16 @@ +from wasmer import Instance, Uint8MemoryView, Value, validate +import inspect +import os +import pytest + +here = os.path.dirname(os.path.realpath(__file__)) +TEST_BYTES = open(here + '/tests.wasm', 'rb').read() + +def test_sum_benchmark(benchmark): + instance = Instance(TEST_BYTES) + sum = instance.exports.sum + + def bench(): + return sum(1, 2) + + assert benchmark(bench) == 3 diff --git a/tests/test_instance.py b/tests/test_instance.py new file mode 100644 index 00000000..261d10d5 --- /dev/null +++ b/tests/test_instance.py @@ -0,0 +1,68 @@ +from wasmer import Instance, Uint8MemoryView, Value, validate +import inspect +import os +import pytest + +here = os.path.dirname(os.path.realpath(__file__)) +TEST_BYTES = open(here + '/tests.wasm', 'rb').read() +INVALID_TEST_BYTES = open(here + '/invalid.wasm', 'rb').read() + +def test_is_a_class(): + assert inspect.isclass(Instance) + +def test_can_construct(): + assert isinstance(Instance(TEST_BYTES), Instance) + +def test_failed_to_instantiate(): + with pytest.raises(RuntimeError) as context_manager: + Instance(INVALID_TEST_BYTES) + + exception = context_manager.value + assert str(exception) == ( + 'Failed to instantiate the module:\n compile error: Validation error "Invalid type"' + ) + +def test_function_does_not_exist(): + with pytest.raises(LookupError) as context_manager: + Instance(TEST_BYTES).exports.foo + + exception = context_manager.value + assert str(exception) == 'Function `foo` does not exist.' + +def test_basic_sum(): + assert Instance(TEST_BYTES).exports.sum(1, 2) == 3 + +def test_call_arity_0(): + assert Instance(TEST_BYTES).exports.arity_0() == 42 + +def test_call_i32_i32(): + assert Instance(TEST_BYTES).exports.i32_i32(7) == 7 + +def test_call_i64_i64(): + assert Instance(TEST_BYTES).exports.i64_i64(7) == 7 + +def test_call_f32_f32(): + assert Instance(TEST_BYTES).exports.f32_f32(7.) == 7. + +def test_call_f64_f64(): + assert Instance(TEST_BYTES).exports.f64_f64(7.) == 7. + +def test_call_i32_i64_f32_f64_f64(): + assert round(Instance(TEST_BYTES).exports.i32_i64_f32_f64_f64(1, 2, 3.4, 5.6), 6) == ( + 1 + 2 + 3.4 + 5.6 + ) + +def test_call_bool_casted_to_i32(): + assert Instance(TEST_BYTES).exports.bool_casted_to_i32() == 1 + +def test_call_string(): + assert Instance(TEST_BYTES).exports.string() == 1048576 + +def test_validate(): + assert validate(TEST_BYTES) + +def test_validate_invalid(): + assert not validate(INVALID_TEST_BYTES) + +def test_memory_view(): + assert isinstance(Instance(TEST_BYTES).uint8_memory_view(), Uint8MemoryView) diff --git a/tests/test_memory_view.py b/tests/test_memory_view.py new file mode 100644 index 00000000..2ac8c6cb --- /dev/null +++ b/tests/test_memory_view.py @@ -0,0 +1,92 @@ +from wasmer import Instance, Uint8MemoryView, Int8MemoryView, Uint16MemoryView, Int16MemoryView, Uint32MemoryView, Int32MemoryView +import inspect +import os +import pytest + +here = os.path.dirname(os.path.realpath(__file__)) +TEST_BYTES = open(here + '/tests.wasm', 'rb').read() + +def test_is_a_class(): + assert inspect.isclass(Uint8MemoryView) + assert inspect.isclass(Int8MemoryView) + assert inspect.isclass(Uint16MemoryView) + assert inspect.isclass(Int16MemoryView) + assert inspect.isclass(Uint32MemoryView) + assert inspect.isclass(Int32MemoryView) + +def test_bytes_per_element(): + assert Instance(TEST_BYTES).uint8_memory_view().bytes_per_element == 1 + assert Instance(TEST_BYTES).int8_memory_view().bytes_per_element == 1 + assert Instance(TEST_BYTES).uint16_memory_view().bytes_per_element == 2 + assert Instance(TEST_BYTES).int16_memory_view().bytes_per_element == 2 + assert Instance(TEST_BYTES).uint32_memory_view().bytes_per_element == 4 + assert Instance(TEST_BYTES).int32_memory_view().bytes_per_element == 4 + +@pytest.mark.xfail() +def test_cannot_construct(): + assert isinstance(Uint8MemoryView(0), Uint8MemoryView) + +def test_length(): + assert len(Instance(TEST_BYTES).uint8_memory_view()) == ( + 1114112 + ) + +def test_get(): + memory = Instance(TEST_BYTES).uint8_memory_view() + index = 7 + value = 42 + memory[index] = value + + assert memory[index] == value + +def test_get_out_of_range(): + with pytest.raises(IndexError) as context_manager: + memory = Instance(TEST_BYTES).uint8_memory_view() + memory[len(memory) + 1] + + exception = context_manager.value + assert str(exception) == ( + 'Out of bound: Absolute index 1114113 is larger than the memory size 1114112.' + ) + +def test_set_out_of_range(): + with pytest.raises(IndexError) as context_manager: + memory = Instance(TEST_BYTES).uint8_memory_view() + memory[len(memory) + 1] = 42 + + exception = context_manager.value + assert str(exception) == ( + 'Out of bound: Absolute index 1114113 is larger than the memory size 1114112.' + ) + +def test_hello_world(): + instance = Instance(TEST_BYTES) + pointer = instance.exports.string() + memory = instance.uint8_memory_view(pointer) + nth = 0 + string = '' + + while (0 != memory[nth]): + string += chr(memory[nth]) + nth += 1 + + assert string, 'Hello == World!' + +def test_memory_views_share_the_same_buffer(): + instance = Instance(TEST_BYTES) + int8 = instance.int8_memory_view() + int16 = instance.int16_memory_view() + int32 = instance.int32_memory_view() + + int8[0] = 0b00000001 + int8[1] = 0b00000100 + int8[2] = 0b00010000 + int8[3] = 0b01000000 + + assert int8[0] == 0b00000001 + assert int8[1] == 0b00000100 + assert int8[2] == 0b00010000 + assert int8[3] == 0b01000000 + assert int16[0] == 0b00000100_00000001 + assert int16[1] == 0b01000000_00010000 + assert int32[0] == 0b01000000_00010000_00000100_00000001 diff --git a/tests/test_value.py b/tests/test_value.py new file mode 100644 index 00000000..65f03b16 --- /dev/null +++ b/tests/test_value.py @@ -0,0 +1,28 @@ +from wasmer import Value +import inspect +import pytest + +def test_is_a_class(): + assert inspect.isclass(Value) + +@pytest.mark.xfail() +def test_cannot_construct(): + Value() + +def test_i32(): + assert repr(Value.i32(42)) == 'I32(42)' + +def test_i64(): + assert repr(Value.i64(42)) == 'I64(42)' + +def test_f32(): + assert repr(Value.f32(4.2)) == 'F32(4.2)' + +def test_f32_auto_cast(): + assert repr(Value.f32(42)) == 'F32(42.0)' + +def test_f64(): + assert repr(Value.f64(4.2)) == 'F64(4.2)' + +def test_f64_auto_cast(): + assert repr(Value.f64(42)) == 'F64(42.0)' diff --git a/tests/value.py b/tests/value.py deleted file mode 100644 index 8e8acff9..00000000 --- a/tests/value.py +++ /dev/null @@ -1,29 +0,0 @@ -from wasmer import Value -import inspect -import unittest - -class TestWasmValue(unittest.TestCase): - def test_is_a_class(self): - self.assertTrue(inspect.isclass(Value)) - - @unittest.expectedFailure - def test_cannot_construct(self): - Value() - - def test_i32(self): - self.assertEqual(repr(Value.i32(42)), 'I32(42)') - - def test_i64(self): - self.assertEqual(repr(Value.i64(42)), 'I64(42)') - - def test_f32(self): - self.assertEqual(repr(Value.f32(4.2)), 'F32(4.2)') - - def test_f32_auto_cast(self): - self.assertEqual(repr(Value.f32(42)), 'F32(42.0)') - - def test_f64(self): - self.assertEqual(repr(Value.f64(4.2)), 'F64(4.2)') - - def test_f64_auto_cast(self): - self.assertEqual(repr(Value.f64(42)), 'F64(42.0)')