├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── assets ├── butwhy.gif └── serverless-wasm.jpg ├── rustfmt.toml ├── samples ├── config.toml ├── testbackend.wasm ├── testbackend │ ├── Cargo.lock │ ├── Cargo.toml │ ├── build.sh │ ├── config.toml │ └── src │ │ └── lib.rs ├── testfunc.wasm └── testfunc │ ├── Cargo.lock │ ├── Cargo.toml │ ├── build.sh │ ├── config.toml │ └── src │ └── lib.rs ├── serverless-api ├── Cargo.lock ├── Cargo.toml ├── src │ └── lib.rs └── target │ ├── .rustc_info.json │ └── debug │ ├── .cargo-lock │ ├── .fingerprint │ ├── serverless-api-58a0200541263288 │ │ ├── dep-lib-serverless_api-58a0200541263288 │ │ ├── lib-serverless_api-58a0200541263288 │ │ └── lib-serverless_api-58a0200541263288.json │ └── serverless-api-81a9cad5d43bde63 │ │ ├── dep-lib-serverless_api-81a9cad5d43bde63 │ │ ├── lib-serverless_api-81a9cad5d43bde63 │ │ └── lib-serverless_api-81a9cad5d43bde63.json │ ├── deps │ ├── libserverless_api-58a0200541263288.rlib │ ├── libserverless_api-81a9cad5d43bde63.rmeta │ ├── serverless_api-58a0200541263288.d │ └── serverless_api-81a9cad5d43bde63.d │ ├── incremental │ ├── serverless_api-101jg2fs4zen3 │ │ ├── s-f15by5smxq-136cfpy-1gc3dqcx796yx │ │ │ ├── 16u6js6g0l3k1ic6.bc.z │ │ │ ├── 16u6js6g0l3k1ic6.o │ │ │ ├── 181cuta0v63atwcm.bc.z │ │ │ ├── 181cuta0v63atwcm.o │ │ │ ├── 1im38lueib99jsk0.bc.z │ │ │ ├── 1im38lueib99jsk0.o │ │ │ ├── 1mvmz58owquyropc.bc.z │ │ │ ├── 1mvmz58owquyropc.o │ │ │ ├── 1w44dretk843l467.bc.z │ │ │ ├── 1w44dretk843l467.o │ │ │ ├── 1y16o1qfye96o7m0.bc.z │ │ │ ├── 1y16o1qfye96o7m0.o │ │ │ ├── 23tqyymcb18u96mb.bc.z │ │ │ ├── 23tqyymcb18u96mb.o │ │ │ ├── 2jqywn86b2gsqohu.bc.z │ │ │ ├── 2jqywn86b2gsqohu.o │ │ │ ├── 2lyh15q6cjwzy18c.bc.z │ │ │ ├── 2lyh15q6cjwzy18c.o │ │ │ ├── 2q5257pdh5222n7q.bc.z │ │ │ ├── 2q5257pdh5222n7q.o │ │ │ ├── 3ayaeypdcro9d6yk.bc.z │ │ │ ├── 3ayaeypdcro9d6yk.o │ │ │ ├── 3wq0rk2lqn1zrv77.bc.z │ │ │ ├── 3wq0rk2lqn1zrv77.o │ │ │ ├── 3wta9ctgdrpkmlpr.bc.z │ │ │ ├── 3wta9ctgdrpkmlpr.o │ │ │ ├── 40mv2bo8bxf7ur21.bc.z │ │ │ ├── 40mv2bo8bxf7ur21.o │ │ │ ├── 43v6g0y2xsxoggnt.bc.z │ │ │ ├── 43v6g0y2xsxoggnt.o │ │ │ ├── 48721dc4k5qxei0u.bc.z │ │ │ ├── 48721dc4k5qxei0u.o │ │ │ ├── 49a7n47po4ttqjl7.bc.z │ │ │ ├── 49a7n47po4ttqjl7.o │ │ │ ├── 49lx1q7cxvpykyv0.bc.z │ │ │ ├── 49lx1q7cxvpykyv0.o │ │ │ ├── 4ezmh1vbs95c5ack.bc.z │ │ │ ├── 4ezmh1vbs95c5ack.o │ │ │ ├── 4i7tkntav6hyd03k.bc.z │ │ │ ├── 4i7tkntav6hyd03k.o │ │ │ ├── 4xq48u46a1pwiqn7.bc.z │ │ │ ├── 4xq48u46a1pwiqn7.o │ │ │ ├── 4yh8x2b62dcih00t.bc.z │ │ │ ├── 4yh8x2b62dcih00t.o │ │ │ ├── 4ypvbwho0bu5tnww.bc.z │ │ │ ├── 4ypvbwho0bu5tnww.o │ │ │ ├── 56dly8q07ws8ucdq.bc.z │ │ │ ├── 56dly8q07ws8ucdq.o │ │ │ ├── 8xzrsc1ux72v29j.bc.z │ │ │ ├── 8xzrsc1ux72v29j.o │ │ │ ├── 98g0d9x8aw3akpe.bc.z │ │ │ ├── 98g0d9x8aw3akpe.o │ │ │ ├── 9elsx31vb4it187.bc.z │ │ │ ├── 9elsx31vb4it187.o │ │ │ ├── c6lbtaiefvx3wya.bc.z │ │ │ ├── c6lbtaiefvx3wya.o │ │ │ ├── dep-graph.bin │ │ │ ├── mz7vgmcf23rofcc.bc.z │ │ │ ├── mz7vgmcf23rofcc.o │ │ │ ├── query-cache.bin │ │ │ ├── work-products.bin │ │ │ ├── y08g5q2x813c4wx.bc.z │ │ │ ├── y08g5q2x813c4wx.o │ │ │ ├── z9ox7biyn1otfln.bc.z │ │ │ └── z9ox7biyn1otfln.o │ │ └── s-f15by5smxq-136cfpy.lock │ └── serverless_api-zlkio54lnw8e │ │ ├── s-f15bj5roo7-7kyxij-vdva6ywejcmk │ │ ├── dep-graph.bin │ │ ├── query-cache.bin │ │ └── work-products.bin │ │ └── s-f15bj5roo7-7kyxij.lock │ ├── libserverless_api.d │ ├── libserverless_api.rlib │ └── libserverless_api.rmeta └── src ├── async ├── host.rs ├── mod.rs └── session.rs ├── config.rs ├── interpreter.rs ├── jit ├── env.rs └── mod.rs ├── main.rs └── sync ├── host.rs └── mod.rs /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "adler32" 3 | version = "1.0.2" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "ascii" 8 | version = "0.7.1" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | 11 | [[package]] 12 | name = "backtrace" 13 | version = "0.3.8" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "backtrace-sys 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", 17 | "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 18 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 19 | "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 20 | "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 21 | ] 22 | 23 | [[package]] 24 | name = "backtrace-sys" 25 | version = "0.1.21" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | dependencies = [ 28 | "cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", 29 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 30 | ] 31 | 32 | [[package]] 33 | name = "base64" 34 | version = "0.7.0" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | dependencies = [ 37 | "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 38 | "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 39 | ] 40 | 41 | [[package]] 42 | name = "bitflags" 43 | version = "0.7.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | 46 | [[package]] 47 | name = "bitflags" 48 | version = "1.0.1" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | 51 | [[package]] 52 | name = "brotli-sys" 53 | version = "0.2.1" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | dependencies = [ 56 | "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", 57 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 58 | ] 59 | 60 | [[package]] 61 | name = "brotli2" 62 | version = "0.2.2" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | dependencies = [ 65 | "brotli-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 66 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 67 | ] 68 | 69 | [[package]] 70 | name = "buf_redux" 71 | version = "0.6.3" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | dependencies = [ 74 | "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 75 | "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 76 | ] 77 | 78 | [[package]] 79 | name = "build_const" 80 | version = "0.2.1" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | 83 | [[package]] 84 | name = "byteorder" 85 | version = "1.2.2" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | 88 | [[package]] 89 | name = "cc" 90 | version = "1.0.15" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | 93 | [[package]] 94 | name = "cfg-if" 95 | version = "0.1.2" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | 98 | [[package]] 99 | name = "chrono" 100 | version = "0.2.25" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | dependencies = [ 103 | "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 104 | "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", 105 | ] 106 | 107 | [[package]] 108 | name = "chrono" 109 | version = "0.4.2" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | dependencies = [ 112 | "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", 113 | "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 114 | "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", 115 | ] 116 | 117 | [[package]] 118 | name = "chunked_transfer" 119 | version = "0.3.1" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | 122 | [[package]] 123 | name = "crc" 124 | version = "1.7.0" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | dependencies = [ 127 | "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 128 | ] 129 | 130 | [[package]] 131 | name = "cretonne" 132 | version = "0.8.0" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | dependencies = [ 135 | "cretonne-codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 136 | "cretonne-frontend 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 137 | ] 138 | 139 | [[package]] 140 | name = "cretonne-codegen" 141 | version = "0.8.0" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | dependencies = [ 144 | "cretonne-entity 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 145 | "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 146 | "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 147 | ] 148 | 149 | [[package]] 150 | name = "cretonne-entity" 151 | version = "0.8.0" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | 154 | [[package]] 155 | name = "cretonne-frontend" 156 | version = "0.8.0" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | dependencies = [ 159 | "cretonne-codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 160 | ] 161 | 162 | [[package]] 163 | name = "cretonne-module" 164 | version = "0.8.0" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | dependencies = [ 167 | "cretonne-codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 168 | "cretonne-entity 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 169 | "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 170 | ] 171 | 172 | [[package]] 173 | name = "cretonne-native" 174 | version = "0.8.0" 175 | source = "registry+https://github.com/rust-lang/crates.io-index" 176 | dependencies = [ 177 | "cretonne-codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 178 | "raw-cpuid 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 179 | ] 180 | 181 | [[package]] 182 | name = "cretonne-simplejit" 183 | version = "0.8.0" 184 | source = "registry+https://github.com/rust-lang/crates.io-index" 185 | dependencies = [ 186 | "cretonne-codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 187 | "cretonne-module 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 188 | "cretonne-native 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 189 | "errno 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 190 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 191 | "region 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 192 | ] 193 | 194 | [[package]] 195 | name = "cretonne-wasm" 196 | version = "0.8.0" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | dependencies = [ 199 | "cretonne-codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 200 | "cretonne-frontend 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 201 | "wasmparser 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", 202 | ] 203 | 204 | [[package]] 205 | name = "deflate" 206 | version = "0.7.18" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | dependencies = [ 209 | "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 210 | "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 211 | "gzip-header 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 212 | ] 213 | 214 | [[package]] 215 | name = "dtoa" 216 | version = "0.4.2" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | 219 | [[package]] 220 | name = "encoding" 221 | version = "0.2.33" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | dependencies = [ 224 | "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", 225 | "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", 226 | "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", 227 | "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", 228 | "encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", 229 | ] 230 | 231 | [[package]] 232 | name = "encoding-index-japanese" 233 | version = "1.20141219.5" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | dependencies = [ 236 | "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 237 | ] 238 | 239 | [[package]] 240 | name = "encoding-index-korean" 241 | version = "1.20141219.5" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | dependencies = [ 244 | "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 245 | ] 246 | 247 | [[package]] 248 | name = "encoding-index-simpchinese" 249 | version = "1.20141219.5" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | dependencies = [ 252 | "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 253 | ] 254 | 255 | [[package]] 256 | name = "encoding-index-singlebyte" 257 | version = "1.20141219.5" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | dependencies = [ 260 | "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 261 | ] 262 | 263 | [[package]] 264 | name = "encoding-index-tradchinese" 265 | version = "1.20141219.5" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | dependencies = [ 268 | "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 269 | ] 270 | 271 | [[package]] 272 | name = "encoding_index_tests" 273 | version = "0.1.4" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | 276 | [[package]] 277 | name = "enum_primitive" 278 | version = "0.1.1" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | dependencies = [ 281 | "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", 282 | ] 283 | 284 | [[package]] 285 | name = "errno" 286 | version = "0.2.3" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | dependencies = [ 289 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 290 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 291 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 292 | ] 293 | 294 | [[package]] 295 | name = "failure" 296 | version = "0.1.1" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | dependencies = [ 299 | "backtrace 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 300 | "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 301 | ] 302 | 303 | [[package]] 304 | name = "failure_derive" 305 | version = "0.1.1" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | dependencies = [ 308 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 309 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 310 | "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 311 | ] 312 | 313 | [[package]] 314 | name = "filetime" 315 | version = "0.1.15" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | dependencies = [ 318 | "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 319 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 320 | "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 321 | ] 322 | 323 | [[package]] 324 | name = "fuchsia-zircon" 325 | version = "0.3.3" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | dependencies = [ 328 | "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 329 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 330 | ] 331 | 332 | [[package]] 333 | name = "fuchsia-zircon-sys" 334 | version = "0.3.3" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | 337 | [[package]] 338 | name = "gcc" 339 | version = "0.3.54" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | 342 | [[package]] 343 | name = "gzip-header" 344 | version = "0.1.2" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | dependencies = [ 347 | "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 348 | "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 349 | ] 350 | 351 | [[package]] 352 | name = "httparse" 353 | version = "1.2.4" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | 356 | [[package]] 357 | name = "idna" 358 | version = "0.1.4" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | dependencies = [ 361 | "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 362 | "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 363 | "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 364 | ] 365 | 366 | [[package]] 367 | name = "iovec" 368 | version = "0.1.2" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | dependencies = [ 371 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 372 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 373 | ] 374 | 375 | [[package]] 376 | name = "itoa" 377 | version = "0.4.1" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | 380 | [[package]] 381 | name = "kernel32-sys" 382 | version = "0.2.2" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | dependencies = [ 385 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 386 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 387 | ] 388 | 389 | [[package]] 390 | name = "lazycell" 391 | version = "0.6.0" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | 394 | [[package]] 395 | name = "libc" 396 | version = "0.2.40" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | 399 | [[package]] 400 | name = "log" 401 | version = "0.3.9" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | dependencies = [ 404 | "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 405 | ] 406 | 407 | [[package]] 408 | name = "log" 409 | version = "0.4.1" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | dependencies = [ 412 | "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 413 | ] 414 | 415 | [[package]] 416 | name = "mach" 417 | version = "0.1.2" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | dependencies = [ 420 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 421 | ] 422 | 423 | [[package]] 424 | name = "matches" 425 | version = "0.1.6" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | 428 | [[package]] 429 | name = "memchr" 430 | version = "1.0.2" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | dependencies = [ 433 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 434 | ] 435 | 436 | [[package]] 437 | name = "memchr" 438 | version = "2.0.1" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | dependencies = [ 441 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 442 | ] 443 | 444 | [[package]] 445 | name = "memory_units" 446 | version = "0.3.0" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | 449 | [[package]] 450 | name = "mime" 451 | version = "0.2.6" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | dependencies = [ 454 | "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 455 | ] 456 | 457 | [[package]] 458 | name = "mime_guess" 459 | version = "1.8.4" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | dependencies = [ 462 | "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 463 | "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", 464 | "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", 465 | "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 466 | ] 467 | 468 | [[package]] 469 | name = "mio" 470 | version = "0.6.14" 471 | source = "registry+https://github.com/rust-lang/crates.io-index" 472 | dependencies = [ 473 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 474 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 475 | "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 476 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 477 | "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 478 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 479 | "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 480 | "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 481 | "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", 482 | "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 483 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 484 | ] 485 | 486 | [[package]] 487 | name = "miow" 488 | version = "0.2.1" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | dependencies = [ 491 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 492 | "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", 493 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 494 | "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 495 | ] 496 | 497 | [[package]] 498 | name = "multipart" 499 | version = "0.13.6" 500 | source = "registry+https://github.com/rust-lang/crates.io-index" 501 | dependencies = [ 502 | "buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 503 | "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", 504 | "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 505 | "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 506 | "mime_guess 1.8.4 (registry+https://github.com/rust-lang/crates.io-index)", 507 | "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", 508 | "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 509 | "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 510 | "twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 511 | ] 512 | 513 | [[package]] 514 | name = "net2" 515 | version = "0.2.32" 516 | source = "registry+https://github.com/rust-lang/crates.io-index" 517 | dependencies = [ 518 | "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 519 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 520 | "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 521 | ] 522 | 523 | [[package]] 524 | name = "num" 525 | version = "0.1.42" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | dependencies = [ 528 | "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", 529 | "num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", 530 | "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 531 | ] 532 | 533 | [[package]] 534 | name = "num-integer" 535 | version = "0.1.36" 536 | source = "registry+https://github.com/rust-lang/crates.io-index" 537 | dependencies = [ 538 | "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 539 | ] 540 | 541 | [[package]] 542 | name = "num-iter" 543 | version = "0.1.35" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | dependencies = [ 546 | "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", 547 | "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 548 | ] 549 | 550 | [[package]] 551 | name = "num-traits" 552 | version = "0.1.43" 553 | source = "registry+https://github.com/rust-lang/crates.io-index" 554 | dependencies = [ 555 | "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 556 | ] 557 | 558 | [[package]] 559 | name = "num-traits" 560 | version = "0.2.2" 561 | source = "registry+https://github.com/rust-lang/crates.io-index" 562 | 563 | [[package]] 564 | name = "num_cpus" 565 | version = "1.8.0" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | dependencies = [ 568 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 569 | ] 570 | 571 | [[package]] 572 | name = "owning_ref" 573 | version = "0.3.3" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | dependencies = [ 576 | "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 577 | ] 578 | 579 | [[package]] 580 | name = "parity-wasm" 581 | version = "0.27.6" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | dependencies = [ 584 | "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 585 | "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 586 | "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", 587 | ] 588 | 589 | [[package]] 590 | name = "parking_lot" 591 | version = "0.5.4" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | dependencies = [ 594 | "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 595 | "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", 596 | ] 597 | 598 | [[package]] 599 | name = "parking_lot_core" 600 | version = "0.2.13" 601 | source = "registry+https://github.com/rust-lang/crates.io-index" 602 | dependencies = [ 603 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 604 | "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 605 | "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 606 | "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 607 | ] 608 | 609 | [[package]] 610 | name = "percent-encoding" 611 | version = "1.0.1" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | 614 | [[package]] 615 | name = "phf" 616 | version = "0.7.21" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | dependencies = [ 619 | "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", 620 | ] 621 | 622 | [[package]] 623 | name = "phf_codegen" 624 | version = "0.7.21" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | dependencies = [ 627 | "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", 628 | "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", 629 | ] 630 | 631 | [[package]] 632 | name = "phf_generator" 633 | version = "0.7.21" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | dependencies = [ 636 | "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", 637 | "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", 638 | ] 639 | 640 | [[package]] 641 | name = "phf_shared" 642 | version = "0.7.21" 643 | source = "registry+https://github.com/rust-lang/crates.io-index" 644 | dependencies = [ 645 | "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 646 | "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 647 | ] 648 | 649 | [[package]] 650 | name = "proc-macro2" 651 | version = "0.3.6" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | dependencies = [ 654 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 655 | ] 656 | 657 | [[package]] 658 | name = "quote" 659 | version = "0.3.15" 660 | source = "registry+https://github.com/rust-lang/crates.io-index" 661 | 662 | [[package]] 663 | name = "quote" 664 | version = "0.5.2" 665 | source = "registry+https://github.com/rust-lang/crates.io-index" 666 | dependencies = [ 667 | "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 668 | ] 669 | 670 | [[package]] 671 | name = "rand" 672 | version = "0.3.22" 673 | source = "registry+https://github.com/rust-lang/crates.io-index" 674 | dependencies = [ 675 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 676 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 677 | "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 678 | ] 679 | 680 | [[package]] 681 | name = "rand" 682 | version = "0.4.2" 683 | source = "registry+https://github.com/rust-lang/crates.io-index" 684 | dependencies = [ 685 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 686 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 687 | "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 688 | ] 689 | 690 | [[package]] 691 | name = "raw-cpuid" 692 | version = "3.1.0" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | dependencies = [ 695 | "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 696 | "cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", 697 | ] 698 | 699 | [[package]] 700 | name = "redox_syscall" 701 | version = "0.1.37" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | 704 | [[package]] 705 | name = "region" 706 | version = "0.2.0" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | dependencies = [ 709 | "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 710 | "errno 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 711 | "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 712 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 713 | "mach 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 714 | "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 715 | ] 716 | 717 | [[package]] 718 | name = "remove_dir_all" 719 | version = "0.5.1" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | dependencies = [ 722 | "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 723 | ] 724 | 725 | [[package]] 726 | name = "rouille" 727 | version = "2.1.0" 728 | source = "registry+https://github.com/rust-lang/crates.io-index" 729 | dependencies = [ 730 | "base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 731 | "brotli2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 732 | "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 733 | "deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)", 734 | "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", 735 | "multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", 736 | "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 737 | "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", 738 | "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", 739 | "serde_derive 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", 740 | "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", 741 | "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 742 | "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", 743 | "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 744 | "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", 745 | "tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", 746 | "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 747 | ] 748 | 749 | [[package]] 750 | name = "rustc-demangle" 751 | version = "0.1.8" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | 754 | [[package]] 755 | name = "rustc-serialize" 756 | version = "0.3.24" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | 759 | [[package]] 760 | name = "safemem" 761 | version = "0.2.0" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | 764 | [[package]] 765 | name = "serde" 766 | version = "1.0.42" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | 769 | [[package]] 770 | name = "serde_derive" 771 | version = "1.0.42" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | dependencies = [ 774 | "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 775 | "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 776 | "serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)", 777 | "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", 778 | ] 779 | 780 | [[package]] 781 | name = "serde_derive_internals" 782 | version = "0.23.1" 783 | source = "registry+https://github.com/rust-lang/crates.io-index" 784 | dependencies = [ 785 | "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 786 | "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", 787 | ] 788 | 789 | [[package]] 790 | name = "serde_json" 791 | version = "1.0.16" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | dependencies = [ 794 | "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 795 | "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 796 | "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", 797 | ] 798 | 799 | [[package]] 800 | name = "serverless-wasm" 801 | version = "0.1.0" 802 | dependencies = [ 803 | "cretonne 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 804 | "cretonne-module 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 805 | "cretonne-simplejit 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 806 | "cretonne-wasm 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 807 | "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", 808 | "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", 809 | "parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)", 810 | "rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 811 | "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", 812 | "serde_derive 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", 813 | "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 814 | "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 815 | "wasmi 0.1.3 (git+https://github.com/geal/wasmi)", 816 | ] 817 | 818 | [[package]] 819 | name = "sha1" 820 | version = "0.2.0" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | 823 | [[package]] 824 | name = "siphasher" 825 | version = "0.2.2" 826 | source = "registry+https://github.com/rust-lang/crates.io-index" 827 | 828 | [[package]] 829 | name = "slab" 830 | version = "0.3.0" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | 833 | [[package]] 834 | name = "slab" 835 | version = "0.4.0" 836 | source = "registry+https://github.com/rust-lang/crates.io-index" 837 | 838 | [[package]] 839 | name = "smallvec" 840 | version = "0.6.0" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | 843 | [[package]] 844 | name = "stable_deref_trait" 845 | version = "1.0.0" 846 | source = "registry+https://github.com/rust-lang/crates.io-index" 847 | 848 | [[package]] 849 | name = "syn" 850 | version = "0.11.11" 851 | source = "registry+https://github.com/rust-lang/crates.io-index" 852 | dependencies = [ 853 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 854 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", 855 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 856 | ] 857 | 858 | [[package]] 859 | name = "syn" 860 | version = "0.13.1" 861 | source = "registry+https://github.com/rust-lang/crates.io-index" 862 | dependencies = [ 863 | "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 864 | "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 865 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 866 | ] 867 | 868 | [[package]] 869 | name = "synom" 870 | version = "0.11.3" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | dependencies = [ 873 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 874 | ] 875 | 876 | [[package]] 877 | name = "synstructure" 878 | version = "0.6.1" 879 | source = "registry+https://github.com/rust-lang/crates.io-index" 880 | dependencies = [ 881 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 882 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 883 | ] 884 | 885 | [[package]] 886 | name = "tempdir" 887 | version = "0.3.7" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | dependencies = [ 890 | "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 891 | "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 892 | ] 893 | 894 | [[package]] 895 | name = "term" 896 | version = "0.2.14" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | dependencies = [ 899 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 900 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 901 | ] 902 | 903 | [[package]] 904 | name = "threadpool" 905 | version = "1.7.1" 906 | source = "registry+https://github.com/rust-lang/crates.io-index" 907 | dependencies = [ 908 | "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 909 | ] 910 | 911 | [[package]] 912 | name = "time" 913 | version = "0.1.39" 914 | source = "registry+https://github.com/rust-lang/crates.io-index" 915 | dependencies = [ 916 | "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", 917 | "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 918 | "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 919 | ] 920 | 921 | [[package]] 922 | name = "tiny_http" 923 | version = "0.5.9" 924 | source = "registry+https://github.com/rust-lang/crates.io-index" 925 | dependencies = [ 926 | "ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 927 | "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", 928 | "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 929 | "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 930 | "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 931 | "url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)", 932 | ] 933 | 934 | [[package]] 935 | name = "toml" 936 | version = "0.4.6" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | dependencies = [ 939 | "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", 940 | ] 941 | 942 | [[package]] 943 | name = "twoway" 944 | version = "0.1.8" 945 | source = "registry+https://github.com/rust-lang/crates.io-index" 946 | dependencies = [ 947 | "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 948 | ] 949 | 950 | [[package]] 951 | name = "unicase" 952 | version = "1.4.2" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | dependencies = [ 955 | "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 956 | ] 957 | 958 | [[package]] 959 | name = "unicode-bidi" 960 | version = "0.3.4" 961 | source = "registry+https://github.com/rust-lang/crates.io-index" 962 | dependencies = [ 963 | "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 964 | ] 965 | 966 | [[package]] 967 | name = "unicode-normalization" 968 | version = "0.1.5" 969 | source = "registry+https://github.com/rust-lang/crates.io-index" 970 | 971 | [[package]] 972 | name = "unicode-xid" 973 | version = "0.0.4" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | 976 | [[package]] 977 | name = "unicode-xid" 978 | version = "0.1.0" 979 | source = "registry+https://github.com/rust-lang/crates.io-index" 980 | 981 | [[package]] 982 | name = "url" 983 | version = "0.2.38" 984 | source = "registry+https://github.com/rust-lang/crates.io-index" 985 | dependencies = [ 986 | "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 987 | "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", 988 | "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", 989 | ] 990 | 991 | [[package]] 992 | name = "url" 993 | version = "1.7.0" 994 | source = "registry+https://github.com/rust-lang/crates.io-index" 995 | dependencies = [ 996 | "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 997 | "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 998 | "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 999 | ] 1000 | 1001 | [[package]] 1002 | name = "uuid" 1003 | version = "0.1.18" 1004 | source = "registry+https://github.com/rust-lang/crates.io-index" 1005 | dependencies = [ 1006 | "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", 1007 | "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", 1008 | ] 1009 | 1010 | [[package]] 1011 | name = "version_check" 1012 | version = "0.1.3" 1013 | source = "registry+https://github.com/rust-lang/crates.io-index" 1014 | 1015 | [[package]] 1016 | name = "wasmi" 1017 | version = "0.1.3" 1018 | source = "git+https://github.com/geal/wasmi#f107c644a92c14e7040dba5862ada6d7aae0885f" 1019 | dependencies = [ 1020 | "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 1021 | "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 1022 | "parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)", 1023 | ] 1024 | 1025 | [[package]] 1026 | name = "wasmparser" 1027 | version = "0.16.1" 1028 | source = "registry+https://github.com/rust-lang/crates.io-index" 1029 | 1030 | [[package]] 1031 | name = "winapi" 1032 | version = "0.2.8" 1033 | source = "registry+https://github.com/rust-lang/crates.io-index" 1034 | 1035 | [[package]] 1036 | name = "winapi" 1037 | version = "0.3.4" 1038 | source = "registry+https://github.com/rust-lang/crates.io-index" 1039 | dependencies = [ 1040 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1041 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1042 | ] 1043 | 1044 | [[package]] 1045 | name = "winapi-build" 1046 | version = "0.1.1" 1047 | source = "registry+https://github.com/rust-lang/crates.io-index" 1048 | 1049 | [[package]] 1050 | name = "winapi-i686-pc-windows-gnu" 1051 | version = "0.4.0" 1052 | source = "registry+https://github.com/rust-lang/crates.io-index" 1053 | 1054 | [[package]] 1055 | name = "winapi-x86_64-pc-windows-gnu" 1056 | version = "0.4.0" 1057 | source = "registry+https://github.com/rust-lang/crates.io-index" 1058 | 1059 | [[package]] 1060 | name = "ws2_32-sys" 1061 | version = "0.2.1" 1062 | source = "registry+https://github.com/rust-lang/crates.io-index" 1063 | dependencies = [ 1064 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 1065 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 1066 | ] 1067 | 1068 | [metadata] 1069 | "checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45" 1070 | "checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" 1071 | "checksum backtrace 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbdd17cd962b570302f5297aea8648d5923e22e555c2ed2d8b2e34eca646bf6d" 1072 | "checksum backtrace-sys 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "b46a4e68c24954dfc8a0e515b069f695481d2997b840356db013ff9e52cdb8fe" 1073 | "checksum base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5032d51da2741729bfdaeb2664d9b8c6d9fd1e2b90715c660b6def36628499c2" 1074 | "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" 1075 | "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" 1076 | "checksum brotli-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cb50f54b2e0c671b7ef1637a76237ebacbb293be179440d5d65ca288e42116bb" 1077 | "checksum brotli2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea9d0bbab1235017a09226b079ed733bca4bf9ecb6b6102bd01aac79ea082dca" 1078 | "checksum buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" 1079 | "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" 1080 | "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" 1081 | "checksum cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebb87d1116151416c0cf66a0e3fb6430cccd120fd6300794b4dfaa050ac40ba" 1082 | "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" 1083 | "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" 1084 | "checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" 1085 | "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" 1086 | "checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7" 1087 | "checksum cretonne 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b4f5fc9fa306fce4a22b3f4fea5d16b25c9f028c858d0120b120f3d0a05cf4f" 1088 | "checksum cretonne-codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a121d1eb7a438f5c34d1a923fa7caa92281f73a1eb568413f62e47c8499f984" 1089 | "checksum cretonne-entity 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2509a2dab127908b1b21826a82b5bed2f1ac426ffce2960ac75e5a7ee7d7ba0b" 1090 | "checksum cretonne-frontend 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bfccdaee075f7f5717c9929e59492c7d7213be0c227e3b7252f17aa4f22646e" 1091 | "checksum cretonne-module 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa230ec99dca5146c5128c9dacb3bbbc9238cebcab6768ac6f4f20f3a7fcdeaa" 1092 | "checksum cretonne-native 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13ec6e7d3a2daf233f507384a8966ad68b0f5ca1760c8a4dd5d844fbec063610" 1093 | "checksum cretonne-simplejit 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a1edd946ffa6c0aa67e0eb681842cac3a7eb9bcd214406f1112d4546e54916c" 1094 | "checksum cretonne-wasm 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70c8f8c98b506a6307df29a5565b3281d2963d61f799ed5b2ff00212dc5e7468" 1095 | "checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31" 1096 | "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" 1097 | "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" 1098 | "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" 1099 | "checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" 1100 | "checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" 1101 | "checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" 1102 | "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" 1103 | "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" 1104 | "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" 1105 | "checksum errno 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2c858c42ac0b88532f48fca88b0ed947cad4f1f64d904bcd6c9f138f7b95d70" 1106 | "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" 1107 | "checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" 1108 | "checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f" 1109 | "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 1110 | "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 1111 | "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" 1112 | "checksum gzip-header 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9fcfe1c9ee125342355b2467bc29b9dfcb2124fcae27edb9cee6f4cc5ecd40" 1113 | "checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" 1114 | "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" 1115 | "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" 1116 | "checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" 1117 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 1118 | "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" 1119 | "checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" 1120 | "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" 1121 | "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" 1122 | "checksum mach 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2fd13ee2dd61cc82833ba05ade5a30bb3d63f7ced605ef827063c63078302de9" 1123 | "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" 1124 | "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" 1125 | "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" 1126 | "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" 1127 | "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" 1128 | "checksum mime_guess 1.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b7e2b09d08313f84e0fb82d13a4d859109a17543fe9af3b6d941dc1431f7de79" 1129 | "checksum mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "6d771e3ef92d58a8da8df7d6976bfca9371ed1de6619d9d5a5ce5b1f29b85bfe" 1130 | "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" 1131 | "checksum multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92f54eb45230c3aa20864ccf0c277eeaeadcf5e437e91731db498dbf7fbe0ec6" 1132 | "checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0" 1133 | "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" 1134 | "checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe" 1135 | "checksum num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "4b226df12c5a59b63569dd57fafb926d91b385dfce33d8074a412411b689d593" 1136 | "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" 1137 | "checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" 1138 | "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" 1139 | "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" 1140 | "checksum parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bd4dc02a80a0315b109e48992c46942c79bcdb8fac416dd575d330ed9ced6cbd" 1141 | "checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd" 1142 | "checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79" 1143 | "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" 1144 | "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" 1145 | "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" 1146 | "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" 1147 | "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" 1148 | "checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" 1149 | "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" 1150 | "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" 1151 | "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" 1152 | "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" 1153 | "checksum raw-cpuid 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "233ec1847057cf4d4591a0d76908aa12812140b11ea7d7d05b4c38cadb069c31" 1154 | "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" 1155 | "checksum region 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e594bf753d31f4fa15dbf6fd20219cd30dbf11efa8ffcb01f72a59942082fb02" 1156 | "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" 1157 | "checksum rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc1f8407af80b0630983b2c1f1860dda1960fdec8d3ee75ba8db14937756d3a0" 1158 | "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" 1159 | "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" 1160 | "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" 1161 | "checksum serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "a73973861352c932ed1365ce22b32467ce260ac4c8db11cf750ce56334ff2dcf" 1162 | "checksum serde_derive 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b392c5a0cebb98121454531c50e60e2ffe0fbeb1a44da277da2d681d08d7dc0b" 1163 | "checksum serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d30c4596450fd7bbda79ef15559683f9a79ac0193ea819db90000d7e1cae794" 1164 | "checksum serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6c4e049dc657a99e394bd85c22acbf97356feeec6dbf44150f2dcf79fb3118" 1165 | "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" 1166 | "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" 1167 | "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" 1168 | "checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" 1169 | "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" 1170 | "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" 1171 | "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" 1172 | "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" 1173 | "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" 1174 | "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" 1175 | "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" 1176 | "checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" 1177 | "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" 1178 | "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" 1179 | "checksum tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f4d55c9a213880d1f0c89ded183f209c6e45b912ca6c7df6f93c163773572e1" 1180 | "checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" 1181 | "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" 1182 | "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" 1183 | "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 1184 | "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" 1185 | "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" 1186 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 1187 | "checksum url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)" = "cbaa8377a162d88e7d15db0cf110c8523453edcbc5bc66d2b6fffccffa34a068" 1188 | "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" 1189 | "checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f" 1190 | "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" 1191 | "checksum wasmi 0.1.3 (git+https://github.com/geal/wasmi)" = "" 1192 | "checksum wasmparser 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e58becacade32185edd389bc18fed36000d6c208d92cb46d5f93fa4c08a2e67" 1193 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 1194 | "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" 1195 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 1196 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1197 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1198 | "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" 1199 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serverless-wasm" 3 | version = "0.1.0" 4 | license = "MIT" 5 | repository = "https://github.com/Geal/serverless-wasm" 6 | readme = "README.md" 7 | authors = ["Geoffroy Couprie "] 8 | 9 | [dependencies] 10 | parity-wasm = "^0.27" 11 | rouille = "^2.1" 12 | slab = "^0.3" 13 | toml = "^0.4" 14 | serde = "^1.0" 15 | serde_derive = "^1.0" 16 | mio = "^0.6" 17 | httparse = "^1.2" 18 | #wasmi = "^0.1" 19 | wasmi = { git = "https://github.com/geal/wasmi" } 20 | #wasmi = { path = "../wasmi" } 21 | cretonne = "*" 22 | cretonne-wasm = "^0.8" 23 | cretonne-module = "*" 24 | cretonne-simplejit = "^0.8" 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Geoffroy Couprie 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Serverless Web Assembly framework 2 | 3 | ![Serverless WASM](https://raw.githubusercontent.com/geal/serverless-wasm/master/assets/serverless-wasm.jpg) 4 | 5 | ## Why? 6 | 7 | For fun. 8 | 9 | ## But why? 10 | 11 | ![but why?](https://raw.githubusercontent.com/geal/serverless-wasm/master/assets/butwhy.gif) 12 | 13 | This is a small demo of Web Assembly's potential outside of browsers. 14 | It has been designed with client side execution in mind, but there's 15 | nothing preventing it from running in other platforms. 16 | There are people working on running WASM binaries from a shell, and 17 | putting WASM code inside kernels. 18 | 19 | Here are some benefits of Web Assembly's design: 20 | 21 | - maps well to CPU assembly (with Just In Time compilation in mind) 22 | - the virtual machine does not require garbage collection, only small memory areas 23 | that will be handled by the guest code 24 | - meant to be sandboxed 25 | 26 | And here's the best part: it is meant to be a target language, a lot of other 27 | languages will compile to WASM. You can already write C or C++ and compile 28 | to WASM with emscripten. Rust's compiler natively supports it. There are demos 29 | in Go, Haskell and Ruby. 30 | 31 | The network effects are huge: the major browsers implement it and can run any 32 | WASM app, and every language wants to run on the client side. 33 | 34 | Now, what happens when you leverage these advantages to build a server platform? 35 | You get a system that can run a lot of small, sandboxed, resource limited 36 | applications, written in a lot of different languages. 37 | 38 | You do not care about how to start it, you don't need to map it to filesystems 39 | and common runtimes like containers do. You just have some bytecode that imports 40 | a few functions, and runs well isolated. 41 | 42 | This is a bit like the serverless promise, the ability to run arbitrarily small 43 | functions, but without even caring about the startup time or the state size, 44 | this will be the smallest you can think of. 45 | 46 | ## What works 47 | 48 | Currently, the server is able to load a pre built web assembly binary, exports 49 | some function that it can use for logging, to build a response and connect to 50 | other servers, and handle requests using that wasm file (as long as it exports 51 | a "handle" function). 52 | 53 | ## How to run it 54 | 55 | ### Requirements for WASM applications 56 | 57 | the WASM application must export a `handle` function that takes no arguments and 58 | returns no arguments. 59 | 60 | The virtual machine currently exposes the following functions, that you can use 61 | to build your response: 62 | 63 | ```rust 64 | extern { 65 | fn log(ptr: *const u8, size: u64); 66 | 67 | fn response_set_status_line(status: u32, ptr: *const u8, size: u64); 68 | fn response_set_header(name_ptr: *const u8, name_size: u64, value_ptr: *const u8, value_size: u64); 69 | fn response_set_body(ptr: *const u8, size: u64); 70 | 71 | fn tcp_connect(ptr: *const u8, size: u64) -> i32; 72 | fn tcp_read(fd: i32, ptr: *mut u8, size: u64) -> i64; 73 | fn tcp_write(fd: i32, ptr: *const u8, size: u64) -> i64; 74 | } 75 | ``` 76 | 77 | ### Configuration file 78 | 79 | You define which WASM binary will handle which requests through a TOML configuration 80 | file: 81 | 82 | ```toml 83 | listen_address = "127.0.0.1:8080" 84 | 85 | [[applications]] 86 | file_path = "./samples/testfunc.wasm" 87 | method = "GET" 88 | url_path = "/hello" 89 | 90 | [[applications]] 91 | file_path = "./samples/testbackend.wasm" 92 | method = "GET" 93 | url_path = "/backend" 94 | ``` 95 | 96 | ### Running it 97 | 98 | You can build and launch the server as follows: 99 | 100 | ```rust 101 | cargo build && ./target/debug/serverless-wasm ./samples/config.toml 102 | ``` 103 | 104 | ## Current features 105 | 106 | - [x] load web assembly file to handle requests 107 | - [x] logging function available from WASM 108 | - [x] API to build a response from WASM 109 | - [x] (blocking) TCP connections to backend servers or databases 110 | - [x] routing to mutiple apps depending on the request 111 | - [x] set up initial state via "environment variables" 112 | - [ ] proper error handling (the server will panic even if you give it the side eye) 113 | - [ ] (in progress) asynchronous event loop to receive connections and handle backend TCP connections 114 | - [ ] file system abstraction (loading files from S3 or other providers?) 115 | - [ ] (in progress) "standard API" for functions exported by the VM 116 | 117 | ## Prior art 118 | 119 | While I was building this, I heard of [IceCore](https://github.com/losfair/IceCore), 120 | which looks quite cool, with JIT support, etc. 121 | It's quite nice to see multiple platforms attempting this. Maybe we'll be able to 122 | agree onthe "web assembly standard API" so WASM apps can run on any of those :) 123 | -------------------------------------------------------------------------------- /assets/butwhy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/assets/butwhy.gif -------------------------------------------------------------------------------- /assets/serverless-wasm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/assets/serverless-wasm.jpg -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | tab_spaces = 2 2 | struct_field_align_threshold = 100 3 | max_width = 140 4 | -------------------------------------------------------------------------------- /samples/config.toml: -------------------------------------------------------------------------------- 1 | listen_address = "127.0.0.1:8080" 2 | 3 | [[applications]] 4 | file_path = "./samples/testfunc.wasm" 5 | method = "GET" 6 | url_path = "/hello" 7 | function = "hello" 8 | 9 | [[applications]] 10 | file_path = "./samples/testfunc.wasm" 11 | method = "GET" 12 | url_path = "/bonjour" 13 | function = "bonjour" 14 | 15 | [[applications]] 16 | file_path = "./samples/testbackend.wasm" 17 | method = "GET" 18 | url_path = "/backend" 19 | function = "handle" 20 | env = { "/env/backend"= "127.0.0.1:8181"} 21 | -------------------------------------------------------------------------------- /samples/testbackend.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/samples/testbackend.wasm -------------------------------------------------------------------------------- /samples/testbackend/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "serverless-api" 3 | version = "0.1.0" 4 | 5 | [[package]] 6 | name = "testbackend" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "serverless-api 0.1.0", 10 | ] 11 | 12 | -------------------------------------------------------------------------------- /samples/testbackend/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "testbackend" 3 | version = "0.1.0" 4 | authors = ["Geoffroy Couprie "] 5 | 6 | [lib] 7 | path = "src/lib.rs" 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | serverless-api = { path = "../../serverless-api/" } 12 | -------------------------------------------------------------------------------- /samples/testbackend/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | RUSTFLAGS="-Clink-args=--import-memory" cargo +nightly build -v --target wasm32-unknown-unknown --release 3 | cp target/wasm32-unknown-unknown/release/testbackend.wasm .. 4 | 5 | -------------------------------------------------------------------------------- /samples/testbackend/config.toml: -------------------------------------------------------------------------------- 1 | rustflags = ["-Clink-args=--import-memory"] 2 | -------------------------------------------------------------------------------- /samples/testbackend/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::str; 2 | extern crate serverless_api as api; 3 | 4 | #[no_mangle] 5 | pub extern "C" fn handle() { 6 | api::log("Hello world with api!"); 7 | let body; 8 | 9 | let key = "/env/backend"; 10 | match api::db::get(key) { 11 | None => { 12 | body = format!("could not get value for key {}", key); 13 | }, 14 | Some(address) => { 15 | api::log(&format!("connecting to backend at {}", address)); 16 | 17 | match api::TcpStream::connect(&address) { 18 | None => { 19 | body = "could not connect to backend".to_string(); 20 | }, 21 | Some(mut socket) => { 22 | match socket.write(b"hello\n") { 23 | None => { 24 | body = "could not write to backend server".to_string(); 25 | }, 26 | Some(_) => { 27 | let mut res: [u8; 100] = [0u8; 100]; 28 | match socket.read(&mut res) { 29 | None => { 30 | body = "could not read from backend server".to_string(); 31 | }, 32 | Some(sz) => { 33 | api::log(&format!("read data from backend: \"{:?}\"", str::from_utf8(&res[..sz]).unwrap())); 34 | 35 | body = format!("Hello world from wasm!\nanswer from backend:\n{}\n", str::from_utf8(&res[..sz]).unwrap()); 36 | api::response::set_status(200, "Ok"); 37 | api::response::set_header("Content-length", &body.len().to_string()); 38 | api::response::set_body(body.as_bytes()); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | 48 | api::log(&body); 49 | api::response::set_status(500, "Server error"); 50 | api::response::set_header("Content-length", &body.len().to_string()); 51 | api::response::set_body(body.as_bytes()); 52 | } 53 | -------------------------------------------------------------------------------- /samples/testfunc.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/samples/testfunc.wasm -------------------------------------------------------------------------------- /samples/testfunc/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "serverless-api" 3 | version = "0.1.0" 4 | 5 | [[package]] 6 | name = "testfunc" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "serverless-api 0.1.0", 10 | ] 11 | 12 | -------------------------------------------------------------------------------- /samples/testfunc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "testfunc" 3 | version = "0.1.0" 4 | authors = ["Geoffroy Couprie "] 5 | 6 | [lib] 7 | path = "src/lib.rs" 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | serverless-api = { path = "../../serverless-api/" } 12 | -------------------------------------------------------------------------------- /samples/testfunc/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | RUSTFLAGS="-Clink-args=--import-memory" cargo +nightly build -v --target wasm32-unknown-unknown --release 3 | cp target/wasm32-unknown-unknown/release/testfunc.wasm .. 4 | 5 | -------------------------------------------------------------------------------- /samples/testfunc/config.toml: -------------------------------------------------------------------------------- 1 | rustflags = ["-Clink-args=--import-memory"] 2 | -------------------------------------------------------------------------------- /samples/testfunc/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::ptr; 2 | use std::str; 3 | extern crate serverless_api as api; 4 | 5 | #[no_mangle] 6 | pub extern "C" fn hello() { 7 | api::log("Hello world with api!"); 8 | 9 | api::response::set_status(200, "Ok"); 10 | 11 | let body = "Hello world from wasm!\n"; 12 | api::response::set_header("Content-length", &body.len().to_string()); 13 | api::response::set_body(body.as_bytes()); 14 | } 15 | 16 | #[no_mangle] 17 | pub extern "C" fn bonjour() { 18 | api::log("Bonjour tout le monde!"); 19 | 20 | api::response::set_status(200, "Ok"); 21 | 22 | let body = "Bonjour tout le monde depuis le monde merveilleux de WASM!\n"; 23 | api::response::set_header("Content-length", &body.len().to_string()); 24 | api::response::set_body(body.as_bytes()); 25 | } 26 | -------------------------------------------------------------------------------- /serverless-api/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "serverless-api" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /serverless-api/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serverless-api" 3 | version = "0.1.0" 4 | authors = ["Geoffroy Couprie "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /serverless-api/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::str; 2 | 3 | mod sys { 4 | extern { 5 | pub fn log(ptr: *const u8, size: u64); 6 | pub fn response_set_status_line(status: u32, ptr: *const u8, size: u64); 7 | pub fn response_set_header(name_ptr: *const u8, name_size: u64, value_ptr: *const u8, value_size: u64); 8 | pub fn response_set_body(ptr: *const u8, size: u64); 9 | pub fn tcp_connect(ptr: *const u8, size: u64) -> i32; 10 | pub fn tcp_read(fd: i32, ptr: *mut u8, size: u64) -> i64; 11 | pub fn tcp_write(fd: i32, ptr: *const u8, size: u64) -> i64; 12 | pub fn db_get(key_ptr: *const u8, key_size: u64, value_ptr: *const u8, value_size: u64) -> i64; 13 | } 14 | } 15 | 16 | pub fn log(s: &str) { 17 | unsafe { sys::log(s.as_ptr(), s.len() as u64) }; 18 | } 19 | 20 | pub mod db { 21 | use super::sys; 22 | use std::iter::repeat; 23 | 24 | pub fn get(key: &str) -> Option { 25 | let mut empty = vec![]; 26 | let read_sz = unsafe { 27 | sys::db_get(key.as_ptr(), key.len() as u64, (&mut empty).as_mut_ptr(), empty.len() as u64) 28 | }; 29 | 30 | if read_sz < 0 { 31 | return None; 32 | } else if read_sz == 0 { 33 | return Some(String::new()); 34 | } 35 | 36 | let mut v = Vec::with_capacity(read_sz as usize); 37 | v.extend(repeat(0).take(read_sz as usize)); 38 | 39 | let sz = unsafe { 40 | sys::db_get(key.as_ptr(), key.len() as u64, v.as_mut_ptr(), v.len() as u64) 41 | }; 42 | 43 | if sz < 0 { 44 | return None; 45 | } else if sz == 0 { 46 | return Some(String::new()); 47 | } 48 | 49 | if sz as usize != v.len() { 50 | None 51 | } else { 52 | String::from_utf8(v).ok() 53 | } 54 | } 55 | } 56 | 57 | pub mod response { 58 | use super::sys; 59 | 60 | pub fn set_status(status: u16, reason: &str) { 61 | unsafe { 62 | sys::response_set_status_line(status.into(), reason.as_ptr(), reason.len() as u64); 63 | } 64 | } 65 | 66 | pub fn set_header(name: &str, value: &str) { 67 | unsafe { 68 | sys::response_set_header(name.as_ptr(), name.len() as u64, value.as_ptr(), value.len() as u64); 69 | } 70 | } 71 | 72 | pub fn set_body(body: &[u8]) { 73 | unsafe { 74 | sys::response_set_body(body.as_ptr(), body.len() as u64); 75 | } 76 | } 77 | } 78 | 79 | pub struct TcpStream { 80 | fd: i32 81 | } 82 | 83 | impl TcpStream { 84 | pub fn connect(address: &str) -> Option { 85 | let fd = unsafe { sys::tcp_connect(address.as_ptr(), address.len() as u64) }; 86 | if fd < 0 { 87 | None 88 | } else { 89 | Some(TcpStream { fd }) 90 | } 91 | } 92 | 93 | pub fn write(&mut self, data: &[u8]) -> Option { 94 | let res = unsafe { sys::tcp_write(self.fd, data.as_ptr(), data.len() as u64) }; 95 | if res < 0 { 96 | None 97 | } else { 98 | Some(res as usize) 99 | } 100 | } 101 | 102 | pub fn read(&mut self, data: &mut [u8]) -> Option { 103 | let res = unsafe { sys::tcp_read(self.fd, data.as_mut_ptr(), data.len() as u64) }; 104 | if res < 0 { 105 | None 106 | } else { 107 | Some(res as usize) 108 | } 109 | } 110 | } 111 | 112 | -------------------------------------------------------------------------------- /serverless-api/target/.rustc_info.json: -------------------------------------------------------------------------------- 1 | {"rustc_fingerprint":10175240907518990213,"outputs":{"1617349019360157463":["___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/geal/.rustup/toolchains/nightly-x86_64-apple-darwin\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"mmx\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"sse3\"\ntarget_feature=\"ssse3\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"apple\"\nunix\n",""],"1164083562126845933":["rustc 1.27.0-nightly (9fae15374 2018-05-13)\nbinary: rustc\ncommit-hash: 9fae1537462bb10fd17d07816efc17cfe4786806\ncommit-date: 2018-05-13\nhost: x86_64-apple-darwin\nrelease: 1.27.0-nightly\nLLVM version: 6.0\n",""],"3144802570395919623":["___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/geal/.rustup/toolchains/nightly-x86_64-apple-darwin\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"mmx\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"sse3\"\ntarget_feature=\"ssse3\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"apple\"\nunix\n",""]}} -------------------------------------------------------------------------------- /serverless-api/target/debug/.cargo-lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/.cargo-lock -------------------------------------------------------------------------------- /serverless-api/target/debug/.fingerprint/serverless-api-58a0200541263288/dep-lib-serverless_api-58a0200541263288: -------------------------------------------------------------------------------- 1 | src/lib.rs -------------------------------------------------------------------------------- /serverless-api/target/debug/.fingerprint/serverless-api-58a0200541263288/lib-serverless_api-58a0200541263288: -------------------------------------------------------------------------------- 1 | 68e06764be0d3fe0 -------------------------------------------------------------------------------- /serverless-api/target/debug/.fingerprint/serverless-api-58a0200541263288/lib-serverless_api-58a0200541263288.json: -------------------------------------------------------------------------------- 1 | {"rustc":2983502972076547984,"features":"[]","target":12616003758275913516,"profile":16965165444893579269,"path":10872709659218687626,"deps":[],"local":[{"MtimeBased":[[1526638291,222510886],".fingerprint/serverless-api-58a0200541263288/dep-lib-serverless_api-58a0200541263288"]}],"rustflags":[],"edition":"Edition2015"} -------------------------------------------------------------------------------- /serverless-api/target/debug/.fingerprint/serverless-api-81a9cad5d43bde63/dep-lib-serverless_api-81a9cad5d43bde63: -------------------------------------------------------------------------------- 1 | src/lib.rs -------------------------------------------------------------------------------- /serverless-api/target/debug/.fingerprint/serverless-api-81a9cad5d43bde63/lib-serverless_api-81a9cad5d43bde63: -------------------------------------------------------------------------------- 1 | d109624b85f6a4ab -------------------------------------------------------------------------------- /serverless-api/target/debug/.fingerprint/serverless-api-81a9cad5d43bde63/lib-serverless_api-81a9cad5d43bde63.json: -------------------------------------------------------------------------------- 1 | {"rustc":2983502972076547984,"features":"[]","target":12616003758275913516,"profile":4101608828254088483,"path":10872709659218687626,"deps":[],"local":[{"MtimeBased":[[1526637383,987549318],".fingerprint/serverless-api-81a9cad5d43bde63/dep-lib-serverless_api-81a9cad5d43bde63"]}],"rustflags":[],"edition":"Edition2015"} -------------------------------------------------------------------------------- /serverless-api/target/debug/deps/libserverless_api-58a0200541263288.rlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/deps/libserverless_api-58a0200541263288.rlib -------------------------------------------------------------------------------- /serverless-api/target/debug/deps/libserverless_api-81a9cad5d43bde63.rmeta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/deps/libserverless_api-81a9cad5d43bde63.rmeta -------------------------------------------------------------------------------- /serverless-api/target/debug/deps/serverless_api-58a0200541263288.d: -------------------------------------------------------------------------------- 1 | /Users/geal/dev/rust/projects/serverless-wasm/serverless-api/target/debug/deps/libserverless_api-58a0200541263288.rlib: src/lib.rs 2 | 3 | /Users/geal/dev/rust/projects/serverless-wasm/serverless-api/target/debug/deps/serverless_api-58a0200541263288.d: src/lib.rs 4 | 5 | src/lib.rs: 6 | -------------------------------------------------------------------------------- /serverless-api/target/debug/deps/serverless_api-81a9cad5d43bde63.d: -------------------------------------------------------------------------------- 1 | /Users/geal/dev/rust/projects/serverless-wasm/serverless-api/target/debug/deps/serverless_api-81a9cad5d43bde63.rmeta: src/lib.rs 2 | 3 | /Users/geal/dev/rust/projects/serverless-wasm/serverless-api/target/debug/deps/serverless_api-81a9cad5d43bde63.d: src/lib.rs 4 | 5 | src/lib.rs: 6 | -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/16u6js6g0l3k1ic6.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/16u6js6g0l3k1ic6.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/16u6js6g0l3k1ic6.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/16u6js6g0l3k1ic6.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/181cuta0v63atwcm.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/181cuta0v63atwcm.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/181cuta0v63atwcm.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/181cuta0v63atwcm.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1im38lueib99jsk0.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1im38lueib99jsk0.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1im38lueib99jsk0.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1im38lueib99jsk0.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1mvmz58owquyropc.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1mvmz58owquyropc.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1mvmz58owquyropc.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1mvmz58owquyropc.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1w44dretk843l467.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1w44dretk843l467.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1w44dretk843l467.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1w44dretk843l467.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1y16o1qfye96o7m0.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1y16o1qfye96o7m0.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1y16o1qfye96o7m0.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/1y16o1qfye96o7m0.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/23tqyymcb18u96mb.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/23tqyymcb18u96mb.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/23tqyymcb18u96mb.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/23tqyymcb18u96mb.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2jqywn86b2gsqohu.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2jqywn86b2gsqohu.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2jqywn86b2gsqohu.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2jqywn86b2gsqohu.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2lyh15q6cjwzy18c.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2lyh15q6cjwzy18c.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2lyh15q6cjwzy18c.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2lyh15q6cjwzy18c.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2q5257pdh5222n7q.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2q5257pdh5222n7q.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2q5257pdh5222n7q.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/2q5257pdh5222n7q.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3ayaeypdcro9d6yk.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3ayaeypdcro9d6yk.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3ayaeypdcro9d6yk.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3ayaeypdcro9d6yk.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3wq0rk2lqn1zrv77.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3wq0rk2lqn1zrv77.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3wq0rk2lqn1zrv77.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3wq0rk2lqn1zrv77.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3wta9ctgdrpkmlpr.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3wta9ctgdrpkmlpr.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3wta9ctgdrpkmlpr.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/3wta9ctgdrpkmlpr.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/40mv2bo8bxf7ur21.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/40mv2bo8bxf7ur21.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/40mv2bo8bxf7ur21.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/40mv2bo8bxf7ur21.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/43v6g0y2xsxoggnt.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/43v6g0y2xsxoggnt.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/43v6g0y2xsxoggnt.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/43v6g0y2xsxoggnt.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/48721dc4k5qxei0u.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/48721dc4k5qxei0u.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/48721dc4k5qxei0u.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/48721dc4k5qxei0u.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/49a7n47po4ttqjl7.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/49a7n47po4ttqjl7.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/49a7n47po4ttqjl7.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/49a7n47po4ttqjl7.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/49lx1q7cxvpykyv0.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/49lx1q7cxvpykyv0.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/49lx1q7cxvpykyv0.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/49lx1q7cxvpykyv0.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4ezmh1vbs95c5ack.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4ezmh1vbs95c5ack.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4ezmh1vbs95c5ack.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4ezmh1vbs95c5ack.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4i7tkntav6hyd03k.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4i7tkntav6hyd03k.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4i7tkntav6hyd03k.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4i7tkntav6hyd03k.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4xq48u46a1pwiqn7.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4xq48u46a1pwiqn7.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4xq48u46a1pwiqn7.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4xq48u46a1pwiqn7.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4yh8x2b62dcih00t.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4yh8x2b62dcih00t.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4yh8x2b62dcih00t.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4yh8x2b62dcih00t.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4ypvbwho0bu5tnww.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4ypvbwho0bu5tnww.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4ypvbwho0bu5tnww.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/4ypvbwho0bu5tnww.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/56dly8q07ws8ucdq.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/56dly8q07ws8ucdq.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/56dly8q07ws8ucdq.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/56dly8q07ws8ucdq.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/8xzrsc1ux72v29j.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/8xzrsc1ux72v29j.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/8xzrsc1ux72v29j.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/8xzrsc1ux72v29j.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/98g0d9x8aw3akpe.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/98g0d9x8aw3akpe.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/98g0d9x8aw3akpe.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/98g0d9x8aw3akpe.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/9elsx31vb4it187.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/9elsx31vb4it187.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/9elsx31vb4it187.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/9elsx31vb4it187.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/c6lbtaiefvx3wya.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/c6lbtaiefvx3wya.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/c6lbtaiefvx3wya.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/c6lbtaiefvx3wya.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/dep-graph.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/dep-graph.bin -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/mz7vgmcf23rofcc.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/mz7vgmcf23rofcc.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/mz7vgmcf23rofcc.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/mz7vgmcf23rofcc.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/query-cache.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/query-cache.bin -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/work-products.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/work-products.bin -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/y08g5q2x813c4wx.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/y08g5q2x813c4wx.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/y08g5q2x813c4wx.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/y08g5q2x813c4wx.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/z9ox7biyn1otfln.bc.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/z9ox7biyn1otfln.bc.z -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/z9ox7biyn1otfln.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy-1gc3dqcx796yx/z9ox7biyn1otfln.o -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-101jg2fs4zen3/s-f15by5smxq-136cfpy.lock -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-zlkio54lnw8e/s-f15bj5roo7-7kyxij-vdva6ywejcmk/dep-graph.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-zlkio54lnw8e/s-f15bj5roo7-7kyxij-vdva6ywejcmk/dep-graph.bin -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-zlkio54lnw8e/s-f15bj5roo7-7kyxij-vdva6ywejcmk/query-cache.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-zlkio54lnw8e/s-f15bj5roo7-7kyxij-vdva6ywejcmk/query-cache.bin -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-zlkio54lnw8e/s-f15bj5roo7-7kyxij-vdva6ywejcmk/work-products.bin: -------------------------------------------------------------------------------- 1 | RSIC%1.27.0-nightly (9fae15374 2018-05-13) -------------------------------------------------------------------------------- /serverless-api/target/debug/incremental/serverless_api-zlkio54lnw8e/s-f15bj5roo7-7kyxij.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/incremental/serverless_api-zlkio54lnw8e/s-f15bj5roo7-7kyxij.lock -------------------------------------------------------------------------------- /serverless-api/target/debug/libserverless_api.d: -------------------------------------------------------------------------------- 1 | /Users/geal/dev/rust/projects/serverless-wasm/serverless-api/target/debug/libserverless_api.rlib: /Users/geal/dev/rust/projects/serverless-wasm/serverless-api/src/lib.rs 2 | -------------------------------------------------------------------------------- /serverless-api/target/debug/libserverless_api.rlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/libserverless_api.rlib -------------------------------------------------------------------------------- /serverless-api/target/debug/libserverless_api.rmeta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geal/serverless-wasm/1fab6e2fdb41d4bc23f420220c40259eff8fa928/serverless-api/target/debug/libserverless_api.rmeta -------------------------------------------------------------------------------- /src/async/host.rs: -------------------------------------------------------------------------------- 1 | //! from https://github.com/paritytech/wasmi/blob/master/src/tests/host.rs 2 | 3 | use slab::Slab; 4 | use std::collections::HashMap; 5 | use std::io::{Read, Write}; 6 | use std::iter::repeat; 7 | use mio::net::TcpStream; 8 | use std::net::SocketAddr; 9 | use std::str; 10 | use std::cmp; 11 | use std::rc::Rc; 12 | use std::cell::RefCell; 13 | use wasmi::memory_units::Pages; 14 | use wasmi::*; 15 | use interpreter::Host; 16 | 17 | #[derive(Debug)] 18 | pub enum AsyncHostError { 19 | Connecting(SocketAddr), 20 | TcpRead(i32, u32, u64), 21 | TcpWrite(i32, u32, u64, usize), 22 | } 23 | 24 | impl ::std::fmt::Display for AsyncHostError { 25 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { 26 | write!(f, "{:?}", self) 27 | } 28 | } 29 | 30 | impl HostError for AsyncHostError {} 31 | 32 | #[derive(Clone, Debug)] 33 | pub struct PreparedResponse { 34 | pub status_code: Option, 35 | pub reason: Option, 36 | pub headers: Vec<(String, String)>, 37 | pub body: Option>, 38 | } 39 | 40 | impl PreparedResponse { 41 | pub fn new() -> PreparedResponse { 42 | PreparedResponse { 43 | status_code: None, 44 | reason: None, 45 | headers: Vec::new(), 46 | body: None, 47 | } 48 | } 49 | } 50 | 51 | pub struct State { 52 | pub memory: Option, 53 | pub instance: Option, 54 | pub prepared_response: PreparedResponse, 55 | pub connections: Slab, 56 | pub db: HashMap, 57 | } 58 | 59 | impl State { 60 | pub fn new() -> State { 61 | State { 62 | memory: None,//Some(MemoryInstance::alloc(Pages(3), Some(Pages(100))).unwrap()), 63 | instance: None, 64 | prepared_response: PreparedResponse::new(), 65 | connections: Slab::with_capacity(100), 66 | db: HashMap::new(), 67 | } 68 | } 69 | } 70 | impl State { 71 | pub fn get_buf(&mut self, ptr: u32, size: usize) -> Option> { 72 | self.memory.as_ref().and_then(|mref| { 73 | mref.get(ptr, size).map_err(|e| println!("get buf error: {:?}", e)).ok() 74 | }) 75 | } 76 | 77 | pub fn write_buf(&mut self, ptr: u32, data: &[u8]) { 78 | self.memory.as_ref().map(|m| m.set(ptr, data)); 79 | } 80 | } 81 | 82 | 83 | pub struct AsyncHost { 84 | pub inner: Rc>, 85 | } 86 | 87 | impl Host for AsyncHost { 88 | type State = State; 89 | 90 | fn build(s: Rc>) -> Self { 91 | AsyncHost { inner: s } 92 | } 93 | } 94 | 95 | /// log(ptr: *mut u8, size: u64) 96 | /// 97 | /// Returns value at the given address in memory. This function 98 | /// requires attached memory. 99 | const LOG_INDEX: usize = 0; 100 | 101 | const RESPONSE_SET_STATUS_LINE: usize = 1; 102 | const RESPONSE_SET_HEADER: usize = 2; 103 | const RESPONSE_SET_BODY: usize = 3; 104 | const TCP_CONNECT: usize = 4; 105 | const TCP_READ: usize = 5; 106 | const TCP_WRITE: usize = 6; 107 | const DB_GET: usize = 7; 108 | 109 | impl Externals for AsyncHost { 110 | fn invoke_index(&mut self, index: usize, args: RuntimeArgs) -> Result, Trap> { 111 | match index { 112 | LOG_INDEX => { 113 | let ptr: u32 = args.nth(0); 114 | let sz: u64 = args.nth(1); 115 | 116 | let v = self 117 | .inner 118 | .borrow() 119 | .memory 120 | .as_ref() 121 | .expect("Function 'inc_mem' expects attached memory") 122 | .get(ptr, sz as usize) 123 | .unwrap(); 124 | 125 | println!("log({} bytes): {}", v.len(), str::from_utf8(&v).unwrap()); 126 | Ok(None) 127 | } 128 | RESPONSE_SET_STATUS_LINE => { 129 | let status: u32 = args.nth(0); 130 | let ptr: u32 = args.nth(1); 131 | let sz: u64 = args.nth(2); 132 | 133 | let reason = self 134 | .inner 135 | .borrow() 136 | .memory 137 | .as_ref() 138 | .expect("Function 'inc_mem' expects attached memory") 139 | .get(ptr, sz as usize) 140 | .unwrap(); 141 | 142 | self.inner.borrow_mut().prepared_response.status_code = Some(status as u16); 143 | self.inner.borrow_mut().prepared_response.reason = Some(String::from_utf8(reason).unwrap()); 144 | 145 | Ok(None) 146 | } 147 | RESPONSE_SET_HEADER => { 148 | let ptr1: u32 = args.nth(0); 149 | let sz1: u64 = args.nth(1); 150 | let ptr2: u32 = args.nth(2); 151 | let sz2: u64 = args.nth(3); 152 | let header_name = { 153 | self 154 | .inner 155 | .borrow() 156 | .memory 157 | .as_ref() 158 | .expect("Function 'inc_mem' expects attached memory") 159 | .get(ptr1, sz1 as usize) 160 | .unwrap() 161 | }; 162 | let header_value = { 163 | self 164 | .inner 165 | .borrow() 166 | .memory 167 | .as_ref() 168 | .expect("Function 'inc_mem' expects attached memory") 169 | .get(ptr2, sz2 as usize) 170 | .unwrap() 171 | }; 172 | 173 | self.inner.borrow_mut().prepared_response.headers.push(( 174 | String::from_utf8(header_name).unwrap(), 175 | String::from_utf8(header_value).unwrap(), 176 | )); 177 | Ok(None) 178 | } 179 | RESPONSE_SET_BODY => { 180 | let ptr: u32 = args.nth(0); 181 | let sz: u64 = args.nth(1); 182 | 183 | let body = self 184 | .inner 185 | .borrow() 186 | .memory 187 | .as_ref() 188 | .expect("Function 'inc_mem' expects attached memory") 189 | .get(ptr, sz as usize) 190 | .unwrap(); 191 | self.inner.borrow_mut().prepared_response.body = Some(body); 192 | Ok(None) 193 | } 194 | TCP_CONNECT => { 195 | let ptr: u32 = args.nth(0); 196 | let sz: u64 = args.nth(1); 197 | 198 | let v = self 199 | .inner 200 | .borrow() 201 | .memory 202 | .as_ref() 203 | .expect("Function 'inc_mem' expects attached memory") 204 | .get(ptr, sz as usize) 205 | .unwrap(); 206 | let address = String::from_utf8(v).unwrap(); 207 | println!("received tcp_connect for {:?}", address); 208 | let error = AsyncHostError::Connecting(address.parse().unwrap()); 209 | Err(Trap::new(TrapKind::Host(Box::new(error)))) 210 | } 211 | TCP_READ => { 212 | let fd: i32 = args.nth(0); 213 | let ptr: u32 = args.nth(1); 214 | let sz: u64 = args.nth(2); 215 | 216 | let error = AsyncHostError::TcpRead(fd, ptr, sz); 217 | Err(Trap::new(TrapKind::Host(Box::new(error)))) 218 | 219 | /* 220 | let mut v = Vec::with_capacity(sz as usize); 221 | v.extend(repeat(0).take(sz as usize)); 222 | 223 | let mut state = self.inner.borrow_mut(); 224 | if let Ok(sz) = state.connections[fd as usize].read(&mut v) { 225 | state.memory.as_ref().map(|m| m.set(ptr, &v[..sz])); 226 | 227 | Ok(Some(RuntimeValue::I64(sz as i64))) 228 | } else { 229 | Ok(Some(RuntimeValue::I64(-1))) 230 | } 231 | */ 232 | } 233 | TCP_WRITE => { 234 | let fd: i32 = args.nth(0); 235 | let ptr: u32 = args.nth(1); 236 | let sz: u64 = args.nth(2); 237 | 238 | let error = AsyncHostError::TcpWrite(fd, ptr, sz, 0); 239 | Err(Trap::new(TrapKind::Host(Box::new(error)))) 240 | 241 | /* 242 | let buf = self 243 | .inner 244 | .borrow() 245 | .memory 246 | .as_ref() 247 | .expect("Function 'inc_mem' expects attached memory") 248 | .get(ptr, sz as usize) 249 | .unwrap(); 250 | 251 | if let Ok(sz) = self.inner.borrow_mut().connections[fd as usize].write(&buf) { 252 | Ok(Some(RuntimeValue::I64(sz as i64))) 253 | } else { 254 | Ok(Some(RuntimeValue::I64(-1))) 255 | } 256 | */ 257 | } 258 | DB_GET => { 259 | let key_ptr: u32 = args.nth(0); 260 | let key_sz: u64 = args.nth(1); 261 | let value_ptr: u32 = args.nth(2); 262 | let value_sz: u64 = args.nth(3); 263 | 264 | let v = self 265 | .inner 266 | .borrow() 267 | .memory 268 | .as_ref() 269 | .expect("Function 'inc_mem' expects attached memory") 270 | .get(key_ptr, key_sz as usize) 271 | .unwrap(); 272 | let key = String::from_utf8(v).unwrap(); 273 | println!("requested value for key {}", key); 274 | 275 | match self.inner.borrow().db.get(&key) { 276 | None => Ok(Some(RuntimeValue::I64(-1))), 277 | Some(value) => { 278 | let to_write = cmp::min(value.len(), value_sz as usize); 279 | self 280 | .inner 281 | .borrow() 282 | .memory 283 | .as_ref() 284 | .map(|m| m.set(value_ptr, (&value[..to_write]).as_bytes())); 285 | Ok(Some(RuntimeValue::I64(value.len() as i64))) 286 | } 287 | } 288 | } 289 | _ => panic!("env doesn't provide function at index {}", index), 290 | } 291 | } 292 | } 293 | 294 | impl State { 295 | fn check_signature(&self, index: usize, signature: &Signature) -> bool { 296 | let (params, ret_ty): (&[ValueType], Option) = match index { 297 | LOG_INDEX => (&[ValueType::I32, ValueType::I64], None), 298 | RESPONSE_SET_STATUS_LINE => (&[ValueType::I32, ValueType::I32, ValueType::I64], None), 299 | RESPONSE_SET_HEADER => ( 300 | &[ 301 | ValueType::I32, 302 | ValueType::I64, 303 | ValueType::I32, 304 | ValueType::I64, 305 | ], 306 | None, 307 | ), 308 | RESPONSE_SET_BODY => (&[ValueType::I32, ValueType::I64], None), 309 | TCP_CONNECT => (&[ValueType::I32, ValueType::I64], Some(ValueType::I32)), 310 | TCP_READ => ( 311 | &[ValueType::I32, ValueType::I32, ValueType::I64], 312 | Some(ValueType::I64), 313 | ), 314 | TCP_WRITE => ( 315 | &[ValueType::I32, ValueType::I32, ValueType::I64], 316 | Some(ValueType::I64), 317 | ), 318 | DB_GET => ( 319 | &[ 320 | ValueType::I32, 321 | ValueType::I64, 322 | ValueType::I32, 323 | ValueType::I64, 324 | ], 325 | Some(ValueType::I64), 326 | ), 327 | _ => return false, 328 | }; 329 | 330 | signature.params() == params && signature.return_type() == ret_ty 331 | } 332 | } 333 | 334 | impl ModuleImportResolver for State { 335 | fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result { 336 | let index = match field_name { 337 | "log" => LOG_INDEX, 338 | "response_set_status_line" => RESPONSE_SET_STATUS_LINE, 339 | "response_set_header" => RESPONSE_SET_HEADER, 340 | "response_set_body" => RESPONSE_SET_BODY, 341 | "tcp_connect" => TCP_CONNECT, 342 | "tcp_read" => TCP_READ, 343 | "tcp_write" => TCP_WRITE, 344 | "db_get" => DB_GET, 345 | _ => { 346 | return Err(Error::Instantiation(format!( 347 | "Export {} not found", 348 | field_name 349 | ))) 350 | } 351 | }; 352 | 353 | if !self.check_signature(index, signature) { 354 | return Err(Error::Instantiation(format!( 355 | "Export `{}` doesnt match expected type {:?}", 356 | field_name, signature 357 | ))); 358 | } 359 | 360 | Ok(FuncInstance::alloc_host(signature.clone(), index)) 361 | } 362 | 363 | fn resolve_memory(&self, _field_name: &str, _memory_type: &MemoryDescriptor) -> Result { 364 | let Pages(initial1) = self.memory.as_ref().map(|m| m.initial()).unwrap(); 365 | let initial2 = _memory_type.initial() as usize; 366 | //println!("requested {} pages", initial2); 367 | if initial2 > initial1 { 368 | self.memory.as_ref().map(|_m| { 369 | //println!("grow res: {:?}", m.grow(Pages(initial2 - initial1)).unwrap()); 370 | }); 371 | } 372 | let Pages(_initial) = self.memory.as_ref().map(|m| m.current_size()).unwrap(); 373 | //println!("current number of pages: {}", initial); 374 | //println!("resolving memory at name: {}", field_name); 375 | let res = self.memory.as_ref().unwrap().clone(); 376 | 377 | Ok(res) 378 | } 379 | } 380 | 381 | pub struct StateResolver { 382 | pub inner: Rc>, 383 | } 384 | 385 | impl ModuleImportResolver for StateResolver { 386 | fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result { 387 | let index = match field_name { 388 | "log" => LOG_INDEX, 389 | "response_set_status_line" => RESPONSE_SET_STATUS_LINE, 390 | "response_set_header" => RESPONSE_SET_HEADER, 391 | "response_set_body" => RESPONSE_SET_BODY, 392 | "tcp_connect" => TCP_CONNECT, 393 | "tcp_read" => TCP_READ, 394 | "tcp_write" => TCP_WRITE, 395 | "db_get" => DB_GET, 396 | _ => { 397 | return Err(Error::Instantiation(format!( 398 | "Export {} not found", 399 | field_name 400 | ))) 401 | } 402 | }; 403 | 404 | if !self.inner.borrow().check_signature(index, signature) { 405 | return Err(Error::Instantiation(format!( 406 | "Export `{}` doesnt match expected type {:?}", 407 | field_name, signature 408 | ))); 409 | } 410 | 411 | Ok(FuncInstance::alloc_host(signature.clone(), index)) 412 | } 413 | 414 | fn resolve_memory(&self, _field_name: &str, _memory_type: &MemoryDescriptor) -> Result { 415 | self.inner.borrow_mut().memory = Some(MemoryInstance::alloc(Pages(_memory_type.initial() as usize), Some(Pages(100))).unwrap()); 416 | Ok(self.inner.borrow().memory.as_ref().unwrap().clone()) 417 | } 418 | } 419 | -------------------------------------------------------------------------------- /src/async/mod.rs: -------------------------------------------------------------------------------- 1 | use config::{ApplicationState, Config}; 2 | 3 | use mio::*; 4 | use mio::net::{TcpListener, TcpStream}; 5 | use mio::unix::UnixReady; 6 | use std::rc::Rc; 7 | use std::cell::RefCell; 8 | use std::collections::VecDeque; 9 | use slab::Slab; 10 | 11 | mod host; 12 | mod session; 13 | 14 | const SERVER: Token = Token(0); 15 | 16 | pub fn server(config: Config) { 17 | let state = ApplicationState::new(&config); 18 | 19 | let addr = (&config.listen_address).parse().unwrap(); 20 | let server = TcpListener::bind(&addr).unwrap(); 21 | 22 | let mut poll = Poll::new().unwrap(); 23 | 24 | poll 25 | .register(&server, SERVER, Ready::readable(), PollOpt::edge()) 26 | .unwrap(); 27 | 28 | let mut events = Events::with_capacity(1024); 29 | 30 | let state = Rc::new(RefCell::new(state)); 31 | let mut connections = Slab::with_capacity(1024); 32 | let mut ready = VecDeque::new(); 33 | 34 | loop { 35 | poll.poll(&mut events, None).unwrap(); 36 | println!("got events: {:?}", events); 37 | 38 | for event in events.iter() { 39 | match event.token() { 40 | SERVER => { 41 | if let Ok((sock, addr)) = server.accept() { 42 | match connections.vacant_entry() { 43 | None => { 44 | println!("error: no more room for new connections"); 45 | } 46 | Some(entry) => { 47 | let index = entry.index(); 48 | poll.register( 49 | &sock, 50 | Token(index + 1), 51 | Ready::readable() | Ready::writable() | Ready::from(UnixReady::hup() | UnixReady::error()), 52 | PollOpt::edge(), 53 | ); 54 | 55 | let client = Rc::new(RefCell::new(session::Session::new( 56 | state.clone(), 57 | sock, 58 | index, 59 | ))); 60 | entry.insert(client); 61 | } 62 | } 63 | } 64 | } 65 | Token(i) => { 66 | let client_token = i - 1; 67 | 68 | if let Some(ref mut client) = connections.get_mut(client_token) { 69 | if client 70 | .borrow_mut() 71 | .process_events(client_token, event.readiness()) 72 | { 73 | ready.push_back(client_token); 74 | } 75 | } else { 76 | println!( 77 | "non existing token {:?} got events {:?}", 78 | client_token, 79 | event.readiness() 80 | ); 81 | } 82 | } 83 | _ => unreachable!(), 84 | } 85 | } 86 | 87 | for client_token in ready.drain(..) { 88 | let mut cont = session::ExecutionResult::Continue; 89 | if let Some(ref mut client) = connections.get_mut(client_token) { 90 | cont = client.borrow_mut().execute(); 91 | } else { 92 | println!("non existing token {:?} was marked as ready", client_token); 93 | } 94 | 95 | match cont { 96 | session::ExecutionResult::Close(tokens) => { 97 | for t in tokens.iter() { 98 | connections.remove(client_token); 99 | } 100 | }, 101 | session::ExecutionResult::ConnectBackend(address) => { 102 | let client = connections.get(client_token).unwrap().clone(); 103 | 104 | match connections.vacant_entry() { 105 | None => { 106 | println!("error: no more room for new connections"); 107 | } 108 | Some(entry) => { 109 | let index = entry.index(); 110 | let stream = TcpStream::connect(&address).unwrap(); 111 | poll.register( 112 | &stream, 113 | Token(index + 1), 114 | Ready::readable() | Ready::writable() | Ready::from(UnixReady::hup() | UnixReady::error()), 115 | PollOpt::edge(), 116 | ); 117 | client.borrow_mut().add_backend(stream, index); 118 | 119 | entry.insert(client); 120 | } 121 | } 122 | }, 123 | _ => {} 124 | } 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/async/session.rs: -------------------------------------------------------------------------------- 1 | use mio::unix::UnixReady; 2 | use mio::net::TcpStream; 3 | use mio::{Poll, Ready}; 4 | use std::collections::HashMap; 5 | use std::iter::repeat; 6 | use std::rc::Rc; 7 | use std::io::{ErrorKind, Read, Write}; 8 | use std::cell::RefCell; 9 | use std::net::{SocketAddr, Shutdown}; 10 | use slab::Slab; 11 | 12 | use interpreter::WasmInstance; 13 | use super::host; 14 | use config::ApplicationState; 15 | use httparse; 16 | use wasmi::{ExternVal, ImportsBuilder, ModuleInstance, TrapKind, RuntimeValue}; 17 | 18 | #[derive(Debug, Clone, PartialEq)] 19 | pub enum ExecutionResult { 20 | WouldBlock, 21 | Close(Vec), 22 | Continue, 23 | ConnectBackend(SocketAddr), 24 | //Register(usize), 25 | //Remove(Vec), 26 | } 27 | 28 | #[derive(Debug)] 29 | pub struct Stream { 30 | pub readiness: UnixReady, 31 | pub interest: UnixReady, 32 | pub stream: TcpStream, 33 | pub index: usize, 34 | } 35 | 36 | pub struct Buf { 37 | buf: Vec, 38 | offset: usize, 39 | len: usize, 40 | } 41 | 42 | #[derive(Debug,Clone,PartialEq)] 43 | pub enum SessionState { 44 | WaitingForRequest, 45 | WaitingForBackendConnect(usize), 46 | TcpRead(i32, u32, usize), 47 | TcpWrite(i32, Vec, usize), 48 | Executing, 49 | Done, 50 | } 51 | 52 | pub struct Session { 53 | client: Stream, 54 | backends: HashMap, 55 | instance: Option>, 56 | config: Rc>, 57 | buffer: Buf, 58 | pub state: Option, 59 | method: Option, 60 | path: Option, 61 | env: Option>>, 62 | } 63 | 64 | impl Session { 65 | pub fn new(config: Rc>, stream: TcpStream, index: usize) -> Session { 66 | let client = Stream { 67 | readiness: UnixReady::from(Ready::empty()), 68 | interest: UnixReady::from(Ready::readable()) | UnixReady::hup() | UnixReady::error(), 69 | stream, 70 | index, 71 | }; 72 | 73 | let capacity = 8192; 74 | let mut v = Vec::with_capacity(capacity); 75 | v.extend(repeat(0).take(capacity)); 76 | let buffer = Buf { 77 | buf: v, 78 | offset: 0, 79 | len: 0, 80 | }; 81 | 82 | Session { 83 | client, 84 | backends: HashMap::new(), 85 | instance: None, 86 | config, 87 | buffer, 88 | state: Some(SessionState::WaitingForRequest), 89 | method: None, 90 | path: None, 91 | env: None, 92 | } 93 | } 94 | 95 | pub fn add_backend(&mut self, stream: TcpStream, index: usize) { 96 | let s = Stream { 97 | readiness: UnixReady::from(Ready::empty()), 98 | interest: UnixReady::from(Ready::writable()) | UnixReady::hup() | UnixReady::error(), 99 | stream, 100 | index, 101 | }; 102 | 103 | self.backends.insert(index, s); 104 | 105 | self.state = Some(SessionState::WaitingForBackendConnect(index)); 106 | } 107 | 108 | pub fn resume(&mut self) -> ExecutionResult { 109 | let res = self.instance.as_mut().map(|instance| instance.resume()).unwrap(); 110 | println!("resume result: {:?}", res); 111 | match res { 112 | Err(t) => match t.kind() { 113 | TrapKind::Host(ref err) => { 114 | match err.as_ref().downcast_ref() { 115 | Some(host::AsyncHostError::Connecting(address)) => { 116 | println!("returning connect to backend server: {}", address); 117 | return ExecutionResult::ConnectBackend(address.clone()); 118 | }, 119 | Some(host::AsyncHostError::TcpWrite(fd, ptr, sz, written)) => { 120 | self.backends.get_mut(&(*fd as usize)).map(|backend| backend.interest.insert(UnixReady::from(Ready::writable()))); 121 | let buf = self.env.as_mut().and_then(|env| env.borrow_mut().get_buf(*ptr, *sz as usize)).unwrap(); 122 | self.state = Some(SessionState::TcpWrite(*fd, buf, *written)); 123 | return ExecutionResult::Continue; 124 | }, 125 | Some(host::AsyncHostError::TcpRead(fd, ptr, sz)) => { 126 | self.backends.get_mut(&(*fd as usize)).map(|backend| backend.interest.insert(UnixReady::from(Ready::readable()))); 127 | self.state = Some(SessionState::TcpRead(*fd, *ptr, *sz as usize)); 128 | return ExecutionResult::Continue; 129 | }, 130 | _ => { panic!("got host error: {:?}", err) } 131 | } 132 | }, 133 | _ => { 134 | panic!("got trap: {:?}", t); 135 | } 136 | }, 137 | Ok(_) => if self 138 | .instance 139 | .as_mut() 140 | .map(|instance| { 141 | println!( 142 | "set up response: {:?}", 143 | instance.state.borrow().prepared_response 144 | ); 145 | instance 146 | .state 147 | .borrow() 148 | .prepared_response 149 | .status_code 150 | .is_some() && instance.state.borrow().prepared_response.body.is_some() 151 | }) 152 | .unwrap_or(false) 153 | { 154 | self.client.interest.insert(Ready::writable()); 155 | return ExecutionResult::Continue 156 | } 157 | } 158 | 159 | ExecutionResult::Continue 160 | } 161 | 162 | pub fn create_instance(&mut self) -> ExecutionResult { 163 | let method = self.method.as_ref().unwrap(); 164 | let path = self.path.as_ref().unwrap(); 165 | if let Some((func_name, module, ref opt_env)) = self.config.borrow().route(method, path) { 166 | let mut env = host::State::new(); 167 | if let Some(h) = opt_env { 168 | env.db.extend( 169 | h.iter() 170 | .map(|(ref k, ref v)| (k.to_string(), v.to_string())), 171 | ); 172 | } 173 | 174 | let env = Rc::new(RefCell::new(env)); 175 | self.env = Some(env.clone()); 176 | let resolver = host::StateResolver { inner: env.clone() }; 177 | 178 | let main = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &resolver)) 179 | .expect("Failed to instantiate module") 180 | .assert_no_start(); 181 | 182 | if let Some(ExternVal::Func(func_ref)) = main.export_by_name(func_name) { 183 | let instance = WasmInstance::new(env, &func_ref, &[]); 184 | self.instance = Some(instance); 185 | ExecutionResult::Continue 186 | } else { 187 | println!("function not found"); 188 | self 189 | .client 190 | .stream 191 | .write(b"HTTP/1.1 404 Not Found\r\nContent-length: 19\r\n\r\nFunction not found\n"); 192 | self.client.stream.shutdown(Shutdown::Both); 193 | self.client.interest = UnixReady::from(Ready::empty()); 194 | ExecutionResult::Close(vec![self.client.index]) 195 | } 196 | } else { 197 | println!("route not found"); 198 | self 199 | .client 200 | .stream 201 | .write(b"HTTP/1.1 404 Not Found\r\nContent-length: 16\r\n\r\nRoute not found\n"); 202 | self.client.stream.shutdown(Shutdown::Both); 203 | self.client.interest = UnixReady::from(Ready::empty()); 204 | ExecutionResult::Close(vec![self.client.index]) 205 | } 206 | } 207 | 208 | pub fn process_events(&mut self, token: usize, events: Ready) -> bool { 209 | println!("client[{}]: token {} got events {:?}", self.client.index, token, events); 210 | if token == self.client.index { 211 | self.client.readiness = self.client.readiness | UnixReady::from(events); 212 | 213 | self.client.readiness & self.client.interest != UnixReady::from(Ready::empty()) 214 | } else { 215 | if let Some(ref mut stream) = self.backends.get_mut(&token) { 216 | println!("state: {:?}", self.state); 217 | if self.state == Some(SessionState::WaitingForBackendConnect(token)) { 218 | self.instance.as_mut().map(|instance| instance.add_function_result(RuntimeValue::I32(token as i32))); 219 | self.state = Some(SessionState::Executing); 220 | } 221 | 222 | stream.readiness.insert(UnixReady::from(events)); 223 | stream.readiness & stream.interest != UnixReady::from(Ready::empty()) 224 | } else { 225 | println!("non existing backend {} got events {:?}", token, events); 226 | false 227 | } 228 | } 229 | } 230 | 231 | pub fn execute(&mut self) -> ExecutionResult { 232 | loop { 233 | let front_readiness = self.client.readiness & self.client.interest; 234 | 235 | if front_readiness.is_readable() { 236 | let res = self.front_readable(); 237 | if res != ExecutionResult::Continue { 238 | return res; 239 | } 240 | } 241 | 242 | if front_readiness.is_writable() { 243 | let res = self.front_writable(); 244 | if res != ExecutionResult::Continue { 245 | return res; 246 | } 247 | } 248 | 249 | let res = self.process(); 250 | if res != ExecutionResult::Continue { 251 | return res; 252 | } 253 | 254 | } 255 | } 256 | 257 | fn front_readable(&mut self) -> ExecutionResult { 258 | if self.state == Some(SessionState::WaitingForRequest) { 259 | loop { 260 | if self.buffer.offset + self.buffer.len == self.buffer.buf.len() { 261 | break; 262 | } 263 | 264 | match self 265 | .client 266 | .stream 267 | .read(&mut self.buffer.buf[self.buffer.offset + self.buffer.len..]) 268 | { 269 | Ok(0) => { 270 | return ExecutionResult::Close(vec![self.client.index]); 271 | } 272 | Ok(sz) => { 273 | self.buffer.len += sz; 274 | } 275 | Err(e) => { 276 | if e.kind() == ErrorKind::WouldBlock { 277 | self.client.readiness.remove(Ready::readable()); 278 | break; 279 | } 280 | } 281 | } 282 | } 283 | 284 | ExecutionResult::Continue 285 | } else { 286 | ExecutionResult::Close(vec![self.client.index]) 287 | } 288 | } 289 | 290 | fn process(&mut self) -> ExecutionResult { 291 | println!("[{}] process", self.client.index); 292 | 293 | let state = self.state.take().unwrap(); 294 | match state { 295 | SessionState::WaitingForRequest => { 296 | 297 | let (method, path) = { 298 | let mut headers = [httparse::Header { 299 | name: "", 300 | value: &[], 301 | }; 16]; 302 | let mut req = httparse::Request::new(&mut headers); 303 | match req.parse(&self.buffer.buf[self.buffer.offset..self.buffer.len]) { 304 | Err(e) => { 305 | println!("http parsing error: {:?}", e); 306 | self.state = Some(SessionState::WaitingForRequest); 307 | return ExecutionResult::Close(vec![self.client.index]); 308 | } 309 | Ok(httparse::Status::Partial) => { 310 | self.state = Some(SessionState::WaitingForRequest); 311 | return ExecutionResult::Continue; 312 | } 313 | Ok(httparse::Status::Complete(sz)) => { 314 | self.buffer.offset += sz; 315 | println!("got request: {:?}", req); 316 | ( 317 | req.method.unwrap().to_string(), 318 | req.path.unwrap().to_string(), 319 | ) 320 | } 321 | } 322 | }; 323 | 324 | self.client.interest.remove(Ready::readable()); 325 | self.method = Some(method); 326 | self.path = Some(path); 327 | self.state = Some(SessionState::Executing); 328 | ExecutionResult::Continue 329 | }, 330 | SessionState::Executing => { 331 | if self.instance.is_none() { 332 | let res = self.create_instance(); 333 | if res != ExecutionResult::Continue { 334 | self.state = Some(SessionState::Executing); 335 | return res; 336 | } 337 | } 338 | 339 | println!("resuming"); 340 | self.state = Some(SessionState::Executing); 341 | self.resume() 342 | }, 343 | SessionState::TcpRead(fd, ptr, sz) => { 344 | let readiness = self.backends[&(fd as usize)].readiness & self.backends[&(fd as usize)].interest; 345 | println!("tcpread({}): readiness: {:?}", fd, readiness); 346 | if readiness.is_readable() { 347 | let mut buffer = Vec::with_capacity(sz as usize); 348 | buffer.extend(repeat(0).take(sz as usize)); 349 | let mut read = 0usize; 350 | 351 | loop { 352 | match self.backends.get_mut(&(fd as usize)).unwrap().stream.read(&mut buffer[read..]) { 353 | Ok(0) => { 354 | println!("read 0"); 355 | self.backends.get_mut(&(fd as usize)).map(|backend| backend.readiness.remove(Ready::readable())); 356 | self.env.as_mut().map(|env| env.borrow_mut().write_buf(ptr, &buffer[..read])); 357 | self.instance.as_mut().map(|instance| instance.add_function_result(RuntimeValue::I64(read as i64))); 358 | self.state = Some(SessionState::Executing); 359 | return ExecutionResult::Continue; 360 | }, 361 | Ok(sz) => { 362 | read += sz; 363 | println!("read {} bytes", read); 364 | 365 | if read == sz { 366 | //FIXME: return result 367 | self.env.as_mut().map(|env| env.borrow_mut().write_buf(ptr, &buffer[..read])); 368 | self.instance.as_mut().map(|instance| instance.add_function_result(RuntimeValue::I64(read as i64))); 369 | self.state = Some(SessionState::Executing); 370 | return ExecutionResult::Continue; 371 | } 372 | }, 373 | Err(e) => match e.kind() { 374 | ErrorKind::WouldBlock => { 375 | println!("wouldblock"); 376 | self.backends.get_mut(&(fd as usize)).map(|backend| backend.readiness.remove(Ready::readable())); 377 | self.env.as_mut().map(|env| env.borrow_mut().write_buf(ptr, &buffer[..read])); 378 | self.instance.as_mut().map(|instance| instance.add_function_result(RuntimeValue::I64(read as i64))); 379 | self.state = Some(SessionState::Executing); 380 | return ExecutionResult::Continue; 381 | }, 382 | e => { 383 | println!("backend socket error: {:?}", e); 384 | self.instance.as_mut().map(|instance| instance.add_function_result(RuntimeValue::I64(-1))); 385 | self.state = Some(SessionState::Executing); 386 | //FIXME 387 | return ExecutionResult::Continue; 388 | } 389 | } 390 | } 391 | } 392 | } else { 393 | self.state = Some(SessionState::TcpRead(fd, ptr, sz)); 394 | ExecutionResult::WouldBlock 395 | } 396 | }, 397 | SessionState::TcpWrite(fd, buffer, mut written) => { 398 | let readiness = self.backends[&(fd as usize)].readiness & self.backends[&(fd as usize)].interest; 399 | if readiness.is_writable() { 400 | loop { 401 | match self.backends.get_mut(&(fd as usize)).unwrap().stream.write(&buffer[written..]) { 402 | Ok(0) => { 403 | self.backends.get_mut(&(fd as usize)).map(|backend| backend.readiness.remove(Ready::writable())); 404 | self.instance.as_mut().map(|instance| instance.add_function_result(RuntimeValue::I64(written as i64))); 405 | self.state = Some(SessionState::Executing); 406 | return ExecutionResult::Continue; 407 | }, 408 | Ok(sz) => { 409 | written += sz; 410 | println!("wrote {} bytes", sz); 411 | 412 | if written == buffer.len() { 413 | //FIXME: return result 414 | self.state = Some(SessionState::Executing); 415 | self.instance.as_mut().map(|instance| instance.add_function_result(RuntimeValue::I64(written as i64))); 416 | return ExecutionResult::Continue; 417 | } 418 | }, 419 | Err(e) => match e.kind() { 420 | ErrorKind::WouldBlock => { 421 | println!("wouldblock"); 422 | self.backends.get_mut(&(fd as usize)).map(|backend| backend.readiness.remove(Ready::writable())); 423 | self.state = Some(SessionState::TcpWrite(fd, buffer, written)); 424 | return ExecutionResult::Continue; 425 | }, 426 | e => { 427 | println!("backend socket error: {:?}", e); 428 | self.instance.as_mut().map(|instance| instance.add_function_result(RuntimeValue::I64(-1))); 429 | self.state = Some(SessionState::Executing); 430 | //FIXME 431 | return ExecutionResult::Continue; 432 | } 433 | } 434 | } 435 | } 436 | 437 | } else { 438 | self.state = Some(SessionState::TcpWrite(fd, buffer, written)); 439 | ExecutionResult::WouldBlock 440 | } 441 | 442 | 443 | //FIXME: handle error and hup 444 | 445 | }, 446 | SessionState::WaitingForBackendConnect(_) => { 447 | panic!("should not have called execute() in WaitingForBackendConnect"); 448 | }, 449 | SessionState::Done => { 450 | panic!("done"); 451 | } 452 | } 453 | } 454 | 455 | fn front_writable(&mut self) -> ExecutionResult { 456 | println!("[{}] front writable", self.client.index); 457 | let response = self 458 | .instance 459 | .as_mut() 460 | .map(|instance| instance.state.borrow().prepared_response.clone()) 461 | .unwrap(); 462 | 463 | self 464 | .client 465 | .stream 466 | .write_fmt(format_args!("HTTP/1.1 {} {}\r\n", response.status_code.unwrap(), response.reason.unwrap())); 467 | for header in response.headers.iter() { 468 | self 469 | .client 470 | .stream 471 | .write_fmt(format_args!("{}: {}\r\n", header.0, header.1)); 472 | } 473 | self.client.stream.write(b"\r\n"); 474 | self.client.stream.write(&response.body.unwrap()[..]); 475 | 476 | ExecutionResult::Close(vec![self.client.index]) 477 | } 478 | } 479 | -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | use interpreter::load_module; 2 | use std::collections::HashMap; 3 | use std::fs::File; 4 | use std::io::Read; 5 | use toml; 6 | use wasmi::Module; 7 | 8 | #[derive(Deserialize, Debug)] 9 | pub struct WasmApp { 10 | pub file_path: String, 11 | pub method: String, 12 | pub url_path: String, 13 | pub function: String, 14 | pub env: Option>, 15 | } 16 | 17 | #[derive(Deserialize, Debug)] 18 | pub struct Config { 19 | pub listen_address: String, 20 | pub applications: Vec, 21 | } 22 | 23 | pub fn load(file: &str) -> Option { 24 | if let Ok(mut file) = File::open(file) { 25 | let mut contents = String::new(); 26 | if let Ok(_) = file.read_to_string(&mut contents) { 27 | return toml::from_str(&contents) 28 | .map_err(|e| { 29 | println!("configuration deserialization error: {:?}", e); 30 | e 31 | }) 32 | .ok(); 33 | } 34 | } 35 | None 36 | } 37 | 38 | pub struct ApplicationState { 39 | /// (method, url path) -> (function name, module path, env) 40 | pub routes: HashMap<(String, String), (String, String, Option>)>, 41 | /// module path -> Module 42 | pub modules: HashMap, 43 | } 44 | 45 | impl ApplicationState { 46 | pub fn new(config: &Config) -> ApplicationState { 47 | let mut routes = HashMap::new(); 48 | let mut modules = HashMap::new(); 49 | 50 | for app in config.applications.iter() { 51 | //FIXME: it might be good to not panic when we don't find the function in the module 52 | let module = load_module(&app.file_path, &app.function); 53 | 54 | if !modules.contains_key(&app.file_path) { 55 | modules.insert(app.file_path.clone(), module); 56 | } 57 | 58 | routes.insert( 59 | (app.method.clone(), app.url_path.clone()), 60 | (app.function.clone(), app.file_path.clone(), app.env.clone()), 61 | ); 62 | } 63 | 64 | ApplicationState { 65 | routes: routes, 66 | modules: modules, 67 | } 68 | } 69 | 70 | pub fn route(&self, method: &str, url: &str) -> Option<(&str, &Module, &Option>)> { 71 | if let Some((func_name, module_path, ref opt_env)) = self.routes.get(&(method.to_string(), url.to_string())) { 72 | if let Some(module) = self.modules.get(module_path) { 73 | return Some((func_name, module, opt_env)); 74 | } 75 | } 76 | 77 | None 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/interpreter.rs: -------------------------------------------------------------------------------- 1 | use parity_wasm; 2 | use parity_wasm::elements::{External, FunctionType, Internal, Type, ValueType}; 3 | use std::collections::VecDeque; 4 | use wasmi::{self, Module}; 5 | use wasmi::{BlockFrameType, Externals, FuncInstance, FuncRef, FunctionContext, Interpreter, RunResult, RuntimeValue, Trap, TrapKind}; 6 | use std::marker; 7 | use std::rc::Rc; 8 | use std::cell::RefCell; 9 | 10 | pub const DEFAULT_VALUE_STACK_LIMIT: usize = 16384; 11 | pub const DEFAULT_FRAME_STACK_LIMIT: usize = 16384; 12 | 13 | pub trait HostBuilder<'a, S> { 14 | fn build(s: &'a mut S) -> Self; 15 | } 16 | 17 | pub trait Host { 18 | type State; 19 | 20 | fn build(s: Rc>) -> Self; 21 | } 22 | 23 | pub struct WasmInstance> { 24 | pub state: Rc>, 25 | pub stack: VecDeque, 26 | _marker: marker::PhantomData, 27 | } 28 | 29 | impl> WasmInstance { 30 | pub fn new(state: Rc>, func_ref: &FuncRef, args: &[RuntimeValue]) -> WasmInstance { 31 | let stack = create_stack(&func_ref, args); 32 | 33 | WasmInstance { 34 | state: state, 35 | stack, 36 | _marker: marker::PhantomData, 37 | } 38 | } 39 | 40 | pub fn resume(&mut self) -> Result, Trap> { 41 | let mut host = E::build(self.state.clone()); 42 | let mut interpreter = Interpreter::new(&mut host); 43 | 44 | println!("WasmInstance::resume: stack\n{:?}", self.stack); 45 | my_run_interpreter_loop(&mut interpreter, &mut self.stack) 46 | } 47 | 48 | pub fn add_function_result(&mut self, return_value: RuntimeValue) { 49 | self.stack.back_mut().map(|function_context| { 50 | function_context.value_stack_mut().push(return_value).expect("should have pushed the return value"); 51 | println!("adding return value to {:?} initialized: {}", 52 | function_context.function, function_context.is_initialized); 53 | }); 54 | println!("added function result {:?}, stack len:{}", return_value, self.stack.len()); 55 | } 56 | } 57 | 58 | pub fn create_stack(func: &FuncRef, args: &[RuntimeValue]) -> VecDeque { 59 | let context = FunctionContext::new( 60 | func.clone(), 61 | DEFAULT_VALUE_STACK_LIMIT, 62 | DEFAULT_FRAME_STACK_LIMIT, 63 | func.signature(), 64 | args.into_iter().cloned().collect(), 65 | ); 66 | 67 | let mut function_stack = VecDeque::new(); 68 | function_stack.push_back(context); 69 | 70 | function_stack 71 | } 72 | 73 | pub fn my_run_interpreter_loop( 74 | interpreter: &mut Interpreter, 75 | function_stack: &mut VecDeque, 76 | ) -> Result, Trap> 77 | where 78 | E: Externals, 79 | { 80 | loop { 81 | let mut function_context = function_stack 82 | .pop_back() 83 | .expect("on loop entry - not empty; on loop continue - checking for emptiness; qed"); 84 | let function_ref = function_context.function.clone(); 85 | let function_body = function_ref 86 | .body() 87 | .expect("Host functions checked in function_return below; Internal functions always have a body; qed"); 88 | if !function_context.is_initialized() { 89 | let return_type = function_context.return_type; 90 | function_context.initialize(&function_body.locals); 91 | function_context 92 | .push_frame(&function_body.labels, BlockFrameType::Function, return_type) 93 | .map_err(Trap::new)?; 94 | } 95 | 96 | let function_return = interpreter 97 | .do_run_function( 98 | &mut function_context, 99 | function_body.opcodes.elements(), 100 | &function_body.labels, 101 | ) 102 | .map_err(Trap::new)?; 103 | 104 | match function_return { 105 | RunResult::Return(return_value) => match function_stack.back_mut() { 106 | Some(caller_context) => if let Some(return_value) = return_value { 107 | caller_context 108 | .value_stack_mut() 109 | .push(return_value) 110 | .map_err(Trap::new)?; 111 | }, 112 | None => return Ok(return_value), 113 | }, 114 | RunResult::NestedCall(nested_func) => { 115 | //println!("calling nested func, stack len={}", function_stack.len()); 116 | match FuncInstance::invoke_context(&nested_func, &mut function_context, interpreter.externals) { 117 | Err(t) => { 118 | if let TrapKind::Host(_) = t.kind() { 119 | //function_context.value_stack_mut().push(RuntimeValue::I32(42)).expect("should have pushed the return value"); 120 | function_stack.push_back(function_context); 121 | println!("got host trapkind"); 122 | return Err(t); 123 | } else { 124 | println!("resume got error: {:?}", t); 125 | return Err(t); 126 | } 127 | }, 128 | Ok(None) => { 129 | function_stack.push_back(function_context); 130 | //println!("got ok(none) stack len={}", function_stack.len()); 131 | } 132 | Ok(Some(nested_context)) => { 133 | function_stack.push_back(function_context); 134 | function_stack.push_back(nested_context); 135 | //println!("got ok(some(nested_context)) stack len={}", function_stack.len()); 136 | } 137 | } 138 | } 139 | } 140 | } 141 | } 142 | 143 | pub fn load_module(file: &str, func_name: &str) -> Module { 144 | let module = parity_wasm::deserialize_file(file).expect("File to be deserialized"); 145 | 146 | // Extracts call arguments from command-line arguments 147 | let _args = { 148 | // Export section has an entry with a func_name with an index inside a module 149 | let export_section = module.export_section().expect("No export section found"); 150 | // It's a section with function declarations (which are references to the type section entries) 151 | let function_section = module 152 | .function_section() 153 | .expect("No function section found"); 154 | // Type section stores function types which are referenced by function_section entries 155 | let type_section = module.type_section().expect("No type section found"); 156 | 157 | // Given function name used to find export section entry which contains 158 | // an `internal` field which points to the index in the function index space 159 | let found_entry = export_section 160 | .entries() 161 | .iter() 162 | .find(|entry| func_name == entry.field()) 163 | .expect(&format!("No export with name {} found", func_name)); 164 | 165 | // Function index in the function index space (internally-defined + imported) 166 | let function_index: usize = match found_entry.internal() { 167 | &Internal::Function(index) => index as usize, 168 | _ => panic!("Founded export is not a function"), 169 | }; 170 | 171 | // We need to count import section entries (functions only!) to subtract it from function_index 172 | // and obtain the index within the function section 173 | let import_section_len: usize = match module.import_section() { 174 | Some(import) => import 175 | .entries() 176 | .iter() 177 | .map(|entry| { 178 | //println!("importing entry {:?}", entry); 179 | entry 180 | }) 181 | .filter(|entry| match entry.external() { 182 | &External::Function(_) => true, 183 | _ => false, 184 | }) 185 | .count(), 186 | None => 0, 187 | }; 188 | 189 | // Calculates a function index within module's function section 190 | let function_index_in_section = function_index - import_section_len; 191 | 192 | // Getting a type reference from a function section entry 193 | let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize; 194 | 195 | // Use the reference to get an actual function type 196 | let function_type: &FunctionType = match &type_section.types()[func_type_ref] { 197 | &Type::Function(ref func_type) => func_type, 198 | }; 199 | 200 | // Parses arguments and constructs runtime values in correspondence of their types 201 | function_type 202 | .params() 203 | .iter() 204 | .enumerate() 205 | .map(|(_i, value)| match value { 206 | &ValueType::I32 => RuntimeValue::I32( 207 | 0, /* program_args[i] 208 | .parse::() 209 | .expect(&format!("Can't parse arg #{} as i32", program_args[i])),*/ 210 | ), 211 | &ValueType::I64 => RuntimeValue::I64( 212 | 0, /* program_args[i] 213 | .parse::() 214 | .expect(&format!("Can't parse arg #{} as i64", program_args[i])),*/ 215 | ), 216 | &ValueType::F32 => RuntimeValue::F32( 217 | 0.0, /* program_args[i] 218 | .parse::() 219 | .expect(&format!("Can't parse arg #{} as f32", program_args[i])),*/ 220 | ), 221 | &ValueType::F64 => RuntimeValue::F64( 222 | 0.0, /* program_args[i] 223 | .parse::() 224 | .expect(&format!("Can't parse arg #{} as f64", program_args[i])),*/ 225 | ), 226 | }) 227 | .collect::>() 228 | }; 229 | 230 | wasmi::Module::from_parity_wasm_module(module).expect("Module to be valid") 231 | } 232 | -------------------------------------------------------------------------------- /src/jit/env.rs: -------------------------------------------------------------------------------- 1 | use cretonne_wasm::{ 2 | ModuleEnvironment, GlobalIndex, MemoryIndex, TableIndex, 3 | FunctionIndex, Table, Memory, Global, SignatureIndex, 4 | FuncTranslator, FuncEnvironment, GlobalValue 5 | }; 6 | use cretonne::prelude::{settings::{self, Flags}, types::*, InstBuilder, Signature}; 7 | use cretonne::codegen::{ 8 | ir::{self, ExternalName, Function}, 9 | cursor::FuncCursor 10 | }; 11 | 12 | pub struct Exportable { 13 | /// A wasm entity. 14 | pub entity: T, 15 | 16 | /// Names under which the entity is exported. 17 | pub export_names: Vec, 18 | } 19 | 20 | impl Exportable { 21 | pub fn new(entity: T) -> Self { 22 | Self { 23 | entity, 24 | export_names: Vec::new(), 25 | } 26 | } 27 | } 28 | 29 | pub struct ModuleInfo { 30 | pub flags: Flags, 31 | pub signatures: Vec, 32 | pub imported_funcs: Vec<(String, String)>, 33 | pub functions: Vec>, 34 | pub function_bodies: Vec, 35 | pub memories: Vec>, 36 | pub tables: Vec>, 37 | pub globals: Vec>, 38 | pub start_func: Option, 39 | } 40 | 41 | impl ModuleInfo { 42 | pub fn new() -> ModuleInfo { 43 | ModuleInfo { 44 | flags: settings::Flags::new(settings::builder()), 45 | signatures: Vec::new(), 46 | imported_funcs: Vec::new(), 47 | functions: Vec::new(), 48 | function_bodies: Vec::new(), 49 | memories: Vec::new(), 50 | tables: Vec::new(), 51 | globals: Vec::new(), 52 | start_func: None, 53 | } 54 | } 55 | } 56 | 57 | pub struct Env { 58 | pub info: ModuleInfo, 59 | trans: FuncTranslator, 60 | } 61 | 62 | impl Env { 63 | pub fn new() -> Env { 64 | Env { 65 | info: ModuleInfo::new(), 66 | trans: FuncTranslator::new(), 67 | } 68 | } 69 | } 70 | 71 | fn get_func_name(func_index: FunctionIndex) -> ir::ExternalName { 72 | ExternalName::user(0, func_index as u32) 73 | } 74 | 75 | impl<'data> ModuleEnvironment<'data> for Env { 76 | fn flags(&self) -> &Flags { 77 | &self.info.flags 78 | } 79 | 80 | fn get_func_name(&self, func_index: FunctionIndex) -> ExternalName { 81 | get_func_name(func_index) 82 | } 83 | 84 | fn declare_signature(&mut self, sig: &Signature) { 85 | self.info.signatures.push(sig.clone()); 86 | } 87 | 88 | fn get_signature(&self, sig_index: SignatureIndex) -> &Signature { 89 | &self.info.signatures[sig_index] 90 | } 91 | 92 | fn declare_func_import( 93 | &mut self, 94 | sig_index: SignatureIndex, 95 | module: &'data str, 96 | field: &'data str 97 | ) { 98 | assert_eq!( 99 | self.info.functions.len(), 100 | self.info.imported_funcs.len(), 101 | "Imported functions must be declared first" 102 | ); 103 | self.info.functions.push(Exportable::new(sig_index)); 104 | self.info.imported_funcs.push(( 105 | String::from(module), 106 | String::from(field), 107 | )); 108 | println!("declared function import {}:{}", module, field); 109 | } 110 | 111 | fn get_num_func_imports(&self) -> usize { 112 | self.info.imported_funcs.len() 113 | } 114 | 115 | fn declare_func_type(&mut self, sig_index: SignatureIndex) { 116 | self.info.functions.push(Exportable::new(sig_index)); 117 | } 118 | 119 | fn get_func_type(&self, func_index: FunctionIndex) -> SignatureIndex { 120 | self.info.functions[func_index].entity 121 | } 122 | 123 | fn declare_global(&mut self, global: Global) { 124 | self.info.globals.push(Exportable::new(global)); 125 | } 126 | 127 | fn get_global(&self, global_index: GlobalIndex) -> &Global { 128 | &self.info.globals[global_index].entity 129 | } 130 | 131 | fn declare_table(&mut self, table: Table) { 132 | self.info.tables.push(Exportable::new(table)); 133 | } 134 | 135 | fn declare_table_elements( 136 | &mut self, 137 | table_index: TableIndex, 138 | base: Option, 139 | offset: usize, 140 | elements: Vec 141 | ) { 142 | //println!("declaring table elements at table n°{} base {:?} offset {}:{:?}", table_index, base, offset, elements); 143 | } 144 | 145 | fn declare_memory(&mut self, memory: Memory) { 146 | println!("declaring new memory zone, min: {}, max: {:?}, shared: {}", memory.pages_count, memory.maximum, 147 | memory.shared); 148 | self.info.memories.push(Exportable::new(memory)); 149 | } 150 | 151 | fn declare_data_initialization( 152 | &mut self, 153 | memory_index: MemoryIndex, 154 | base: Option, 155 | offset: usize, 156 | data: &'data [u8] 157 | ) { 158 | println!("declaring data init for memory n°{}, base {:?}, offset {}, data: {:?}", 159 | memory_index, base, offset, data.len()); 160 | } 161 | 162 | fn declare_func_export( 163 | &mut self, 164 | func_index: FunctionIndex, 165 | name: &'data str 166 | ) { 167 | println!("exporting function n°{} at '{}'", func_index, name); 168 | self.info.functions[func_index].export_names.push( 169 | String::from(name) 170 | ) 171 | } 172 | 173 | fn declare_table_export( 174 | &mut self, 175 | table_index: TableIndex, 176 | name: &'data str 177 | ) { unimplemented!() } 178 | fn declare_memory_export( 179 | &mut self, 180 | memory_index: MemoryIndex, 181 | name: &'data str 182 | ) { unimplemented!() } 183 | fn declare_global_export( 184 | &mut self, 185 | global_index: GlobalIndex, 186 | name: &'data str 187 | ) { unimplemented!() } 188 | 189 | fn declare_start_func(&mut self, index: FunctionIndex) { 190 | debug_assert!(self.info.start_func.is_none()); 191 | self.info.start_func = Some(index); 192 | } 193 | 194 | fn define_function_body( 195 | &mut self, 196 | body_bytes: &'data [u8] 197 | ) -> Result<(), String> { 198 | let func = { 199 | let mut func_environ = FuncEnv::new(&self.info); 200 | let function_index = self.get_num_func_imports() + self.info.function_bodies.len(); 201 | let name = get_func_name(function_index); 202 | let sig = func_environ.vmctx_sig(self.get_func_type(function_index)); 203 | let mut func = Function::with_name_signature(name, sig); 204 | self.trans 205 | .translate(body_bytes, &mut func, &mut func_environ) 206 | .map_err(|e| format!("{}", e))?; 207 | func 208 | }; 209 | 210 | self.info.function_bodies.push(func); 211 | Ok(()) 212 | } 213 | } 214 | 215 | pub struct FuncEnv<'env> { 216 | pub mod_info: &'env ModuleInfo, 217 | } 218 | 219 | impl<'env> FuncEnv<'env> { 220 | pub fn new(mod_info: &'env ModuleInfo) -> Self { 221 | Self { mod_info } 222 | } 223 | 224 | // Create a signature for `sigidx` amended with a `vmctx` argument after the standard wasm 225 | // arguments. 226 | fn vmctx_sig(&self, sigidx: SignatureIndex) -> ir::Signature { 227 | let mut sig = self.mod_info.signatures[sigidx].clone(); 228 | sig.params.push(ir::AbiParam::special( 229 | self.native_pointer(), 230 | ir::ArgumentPurpose::VMContext, 231 | )); 232 | sig 233 | } 234 | } 235 | 236 | impl<'env> FuncEnvironment for FuncEnv<'env> { 237 | fn flags(&self) -> &settings::Flags { 238 | &self.mod_info.flags 239 | } 240 | 241 | fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalValue { 242 | // Just create a dummy `vmctx` global. 243 | let offset = ((index * 8) as i32 + 8).into(); 244 | let gv = func.create_global_var(ir::GlobalVarData::VMContext { offset }); 245 | GlobalValue::Memory { 246 | gv, 247 | ty: self.mod_info.globals[index].entity.ty, 248 | } 249 | } 250 | 251 | fn make_heap(&mut self, func: &mut ir::Function, _index: MemoryIndex) -> ir::Heap { 252 | // Create a static heap whose base address is stored at `vmctx+0`. 253 | let gv = func.create_global_var(ir::GlobalVarData::VMContext { offset: 0.into() }); 254 | 255 | func.create_heap(ir::HeapData { 256 | base: ir::HeapBase::GlobalVar(gv), 257 | min_size: 0.into(), 258 | guard_size: 0x8000_0000.into(), 259 | style: ir::HeapStyle::Static { bound: 0x1_0000_0000.into() }, 260 | }) 261 | } 262 | 263 | fn make_indirect_sig(&mut self, func: &mut ir::Function, index: SignatureIndex) -> ir::SigRef { 264 | // A real implementation would probably change the calling convention and add `vmctx` and 265 | // signature index arguments. 266 | func.import_signature(self.vmctx_sig(index)) 267 | } 268 | 269 | fn make_direct_func(&mut self, func: &mut ir::Function, index: FunctionIndex) -> ir::FuncRef { 270 | let sigidx = self.mod_info.functions[index].entity; 271 | // A real implementation would probably add a `vmctx` argument. 272 | // And maybe attempt some signature de-duplication. 273 | let signature = func.import_signature(self.vmctx_sig(sigidx)); 274 | let name = get_func_name(index); 275 | func.import_function(ir::ExtFuncData { 276 | name, 277 | signature, 278 | colocated: false, 279 | }) 280 | } 281 | 282 | fn translate_call_indirect( 283 | &mut self, 284 | mut pos: FuncCursor, 285 | _table_index: TableIndex, 286 | _sig_index: SignatureIndex, 287 | sig_ref: ir::SigRef, 288 | callee: ir::Value, 289 | call_args: &[ir::Value], 290 | ) -> ir::Inst { 291 | // Pass the current function's vmctx parameter on to the callee. 292 | let vmctx = pos.func 293 | .special_param(ir::ArgumentPurpose::VMContext) 294 | .expect("Missing vmctx parameter"); 295 | 296 | // The `callee` value is an index into a table of function pointers. 297 | // Apparently, that table is stored at absolute address 0 in this dummy environment. 298 | // TODO: Generate bounds checking code. 299 | let ptr = self.native_pointer(); 300 | let callee_offset = if ptr == I32 { 301 | pos.ins().imul_imm(callee, 4) 302 | } else { 303 | let ext = pos.ins().uextend(I64, callee); 304 | pos.ins().imul_imm(ext, 4) 305 | }; 306 | let mut mflags = ir::MemFlags::new(); 307 | mflags.set_notrap(); 308 | mflags.set_aligned(); 309 | let func_ptr = pos.ins().load(ptr, mflags, callee_offset, 0); 310 | 311 | // Build a value list for the indirect call instruction containing the callee, call_args, 312 | // and the vmctx parameter. 313 | let mut args = ir::ValueList::default(); 314 | args.push(func_ptr, &mut pos.func.dfg.value_lists); 315 | args.extend(call_args.iter().cloned(), &mut pos.func.dfg.value_lists); 316 | args.push(vmctx, &mut pos.func.dfg.value_lists); 317 | 318 | pos.ins() 319 | .CallIndirect(ir::Opcode::CallIndirect, VOID, sig_ref, args) 320 | .0 321 | } 322 | 323 | fn translate_call( 324 | &mut self, 325 | mut pos: FuncCursor, 326 | _callee_index: FunctionIndex, 327 | callee: ir::FuncRef, 328 | call_args: &[ir::Value], 329 | ) -> ir::Inst { 330 | // Pass the current function's vmctx parameter on to the callee. 331 | let vmctx = pos.func 332 | .special_param(ir::ArgumentPurpose::VMContext) 333 | .expect("Missing vmctx parameter"); 334 | 335 | // Build a value list for the call instruction containing the call_args and the vmctx 336 | // parameter. 337 | let mut args = ir::ValueList::default(); 338 | args.extend(call_args.iter().cloned(), &mut pos.func.dfg.value_lists); 339 | args.push(vmctx, &mut pos.func.dfg.value_lists); 340 | 341 | pos.ins().Call(ir::Opcode::Call, VOID, callee, args).0 342 | } 343 | 344 | fn translate_grow_memory( 345 | &mut self, 346 | mut pos: FuncCursor, 347 | _index: MemoryIndex, 348 | _heap: ir::Heap, 349 | _val: ir::Value, 350 | ) -> ir::Value { 351 | pos.ins().iconst(I32, -1) 352 | } 353 | 354 | fn translate_current_memory( 355 | &mut self, 356 | mut pos: FuncCursor, 357 | _index: MemoryIndex, 358 | _heap: ir::Heap, 359 | ) -> ir::Value { 360 | pos.ins().iconst(I32, -1) 361 | } 362 | } 363 | -------------------------------------------------------------------------------- /src/jit/mod.rs: -------------------------------------------------------------------------------- 1 | use config::Config; 2 | 3 | use cretonne_wasm::{translate_module, DummyEnvironment}; 4 | use std::fs::File; 5 | use std::io::Read; 6 | 7 | mod env; 8 | 9 | pub fn server(config: Config) { 10 | for app in config.applications.iter() { 11 | println!("loading {}:{} at '{} {}'", app.file_path, app.function, app.method, app.url_path); 12 | if let Ok(mut file) = File::open(&app.file_path) { 13 | let mut data = Vec::new(); 14 | file.read_to_end(&mut data); 15 | 16 | //let mut env = DummyEnvironment::default(); 17 | 18 | let mut env = env::Env::new(); 19 | 20 | translate_module(&data, &mut env).unwrap(); 21 | 22 | //let func_env = env.func_env(); 23 | //println!("bytecode:\n{:?}", env.func_bytecode_sizes); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate httparse; 2 | extern crate mio; 3 | extern crate parity_wasm; 4 | extern crate rouille; 5 | extern crate slab; 6 | extern crate toml; 7 | extern crate wasmi; 8 | extern crate cretonne; 9 | extern crate cretonne_wasm; 10 | extern crate cretonne_module; 11 | extern crate cretonne_simplejit; 12 | 13 | #[macro_use] 14 | extern crate serde_derive; 15 | 16 | use std::env::args; 17 | 18 | mod async; 19 | mod config; 20 | mod interpreter; 21 | mod sync; 22 | mod jit; 23 | 24 | fn main() { 25 | let args: Vec<_> = args().collect(); 26 | if args.len() != 2 { 27 | println!("Usage: {} ", args[0]); 28 | return; 29 | } 30 | 31 | if let Some(config) = config::load(&args[1]) { 32 | async::server(config); 33 | } else { 34 | println!("invalid configuration"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/sync/host.rs: -------------------------------------------------------------------------------- 1 | //! from https://github.com/paritytech/wasmi/blob/master/src/tests/host.rs 2 | 3 | use slab::Slab; 4 | use std::collections::HashMap; 5 | use std::io::{Read, Write}; 6 | use std::iter::repeat; 7 | use std::net::TcpStream; 8 | use std::str; 9 | use std::cmp; 10 | use std::rc::Rc; 11 | use std::cell::RefCell; 12 | use wasmi::memory_units::Pages; 13 | use wasmi::*; 14 | use interpreter::Host; 15 | 16 | #[derive(Debug, Clone, PartialEq)] 17 | struct HostErrorWithCode { 18 | error_code: u32, 19 | } 20 | 21 | impl ::std::fmt::Display for HostErrorWithCode { 22 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { 23 | write!(f, "{}", self.error_code) 24 | } 25 | } 26 | 27 | impl HostError for HostErrorWithCode {} 28 | 29 | #[derive(Clone)] 30 | pub struct PreparedResponse { 31 | pub status_code: Option, 32 | pub headers: Vec<(String, String)>, 33 | pub body: Option>, 34 | } 35 | 36 | impl PreparedResponse { 37 | pub fn new() -> PreparedResponse { 38 | PreparedResponse { 39 | status_code: None, 40 | headers: Vec::new(), 41 | body: None, 42 | } 43 | } 44 | } 45 | 46 | pub struct State { 47 | memory: Option, 48 | instance: Option, 49 | pub prepared_response: PreparedResponse, 50 | connections: Slab, 51 | pub db: HashMap, 52 | } 53 | 54 | impl State { 55 | pub fn new() -> State { 56 | State { 57 | memory: Some(MemoryInstance::alloc(Pages(3), Some(Pages(10))).unwrap()), 58 | instance: None, 59 | prepared_response: PreparedResponse::new(), 60 | connections: Slab::with_capacity(100), 61 | db: HashMap::new(), 62 | } 63 | } 64 | } 65 | 66 | pub struct SyncHost { 67 | pub inner: Rc>, 68 | } 69 | 70 | impl Host for SyncHost { 71 | type State = State; 72 | 73 | fn build(s: Rc>) -> Self { 74 | SyncHost { inner: s } 75 | } 76 | } 77 | 78 | /// log(ptr: *mut u8, size: u64) 79 | /// 80 | /// Returns value at the given address in memory. This function 81 | /// requires attached memory. 82 | const LOG_INDEX: usize = 0; 83 | 84 | const RESPONSE_SET_STATUS_LINE: usize = 1; 85 | const RESPONSE_SET_HEADER: usize = 2; 86 | const RESPONSE_SET_BODY: usize = 3; 87 | const TCP_CONNECT: usize = 4; 88 | const TCP_READ: usize = 5; 89 | const TCP_WRITE: usize = 6; 90 | const DB_GET: usize = 7; 91 | 92 | impl Externals for SyncHost { 93 | fn invoke_index(&mut self, index: usize, args: RuntimeArgs) -> Result, Trap> { 94 | match index { 95 | LOG_INDEX => { 96 | let ptr: u32 = args.nth(0); 97 | let sz: u64 = args.nth(1); 98 | 99 | let v = self 100 | .inner 101 | .borrow() 102 | .memory 103 | .as_ref() 104 | .expect("Function 'inc_mem' expects attached memory") 105 | .get(ptr, sz as usize) 106 | .unwrap(); 107 | 108 | println!("log({} bytes): {}", v.len(), str::from_utf8(&v).unwrap()); 109 | Ok(None) 110 | } 111 | RESPONSE_SET_STATUS_LINE => { 112 | let status: u32 = args.nth(0); 113 | let ptr: u32 = args.nth(1); 114 | let sz: u64 = args.nth(2); 115 | 116 | let _reason = self 117 | .inner 118 | .borrow() 119 | .memory 120 | .as_ref() 121 | .expect("Function 'inc_mem' expects attached memory") 122 | .get(ptr, sz as usize) 123 | .unwrap(); 124 | 125 | self.inner.borrow_mut().prepared_response.status_code = Some(status as u16); 126 | 127 | Ok(None) 128 | } 129 | RESPONSE_SET_HEADER => { 130 | let ptr1: u32 = args.nth(0); 131 | let sz1: u64 = args.nth(1); 132 | let ptr2: u32 = args.nth(2); 133 | let sz2: u64 = args.nth(3); 134 | let header_name = { 135 | self 136 | .inner 137 | .borrow() 138 | .memory 139 | .as_ref() 140 | .expect("Function 'inc_mem' expects attached memory") 141 | .get(ptr1, sz1 as usize) 142 | .unwrap() 143 | }; 144 | let header_value = { 145 | self 146 | .inner 147 | .borrow() 148 | .memory 149 | .as_ref() 150 | .expect("Function 'inc_mem' expects attached memory") 151 | .get(ptr2, sz2 as usize) 152 | .unwrap() 153 | }; 154 | 155 | self.inner.borrow_mut().prepared_response.headers.push(( 156 | String::from_utf8(header_name).unwrap(), 157 | String::from_utf8(header_value).unwrap(), 158 | )); 159 | Ok(None) 160 | } 161 | RESPONSE_SET_BODY => { 162 | let ptr: u32 = args.nth(0); 163 | let sz: u64 = args.nth(1); 164 | 165 | let body = self 166 | .inner 167 | .borrow() 168 | .memory 169 | .as_ref() 170 | .expect("Function 'inc_mem' expects attached memory") 171 | .get(ptr, sz as usize) 172 | .unwrap(); 173 | self.inner.borrow_mut().prepared_response.body = Some(body); 174 | Ok(None) 175 | } 176 | TCP_CONNECT => { 177 | let ptr: u32 = args.nth(0); 178 | let sz: u64 = args.nth(1); 179 | 180 | let v = self 181 | .inner 182 | .borrow() 183 | .memory 184 | .as_ref() 185 | .expect("Function 'inc_mem' expects attached memory") 186 | .get(ptr, sz as usize) 187 | .unwrap(); 188 | let address = String::from_utf8(v).unwrap(); 189 | if let Ok(socket) = TcpStream::connect(&address) { 190 | if let Ok(fd) = self.inner.borrow_mut().connections.insert(socket) { 191 | Ok(Some(RuntimeValue::I32(fd as i32))) 192 | } else { 193 | Ok(Some(RuntimeValue::I32(-2))) 194 | } 195 | } else { 196 | Ok(Some(RuntimeValue::I32(-1))) 197 | } 198 | } 199 | TCP_READ => { 200 | let fd: i32 = args.nth(0); 201 | let ptr: u32 = args.nth(1); 202 | let sz: u64 = args.nth(2); 203 | let mut v = Vec::with_capacity(sz as usize); 204 | v.extend(repeat(0).take(sz as usize)); 205 | let mut state = self.inner.borrow_mut(); 206 | if let Ok(sz) = state.connections[fd as usize].read(&mut v) { 207 | state.memory.as_ref().map(|m| m.set(ptr, &v[..sz])); 208 | 209 | Ok(Some(RuntimeValue::I64(sz as i64))) 210 | } else { 211 | Ok(Some(RuntimeValue::I64(-1))) 212 | } 213 | } 214 | TCP_WRITE => { 215 | let fd: i32 = args.nth(0); 216 | let ptr: u32 = args.nth(1); 217 | let sz: u64 = args.nth(2); 218 | 219 | let buf = self 220 | .inner 221 | .borrow() 222 | .memory 223 | .as_ref() 224 | .expect("Function 'inc_mem' expects attached memory") 225 | .get(ptr, sz as usize) 226 | .unwrap(); 227 | 228 | if let Ok(sz) = self.inner.borrow_mut().connections[fd as usize].write(&buf) { 229 | Ok(Some(RuntimeValue::I64(sz as i64))) 230 | } else { 231 | Ok(Some(RuntimeValue::I64(-1))) 232 | } 233 | } 234 | DB_GET => { 235 | let key_ptr: u32 = args.nth(0); 236 | let key_sz: u64 = args.nth(1); 237 | let value_ptr: u32 = args.nth(2); 238 | let value_sz: u64 = args.nth(3); 239 | 240 | let v = self 241 | .inner 242 | .borrow() 243 | .memory 244 | .as_ref() 245 | .expect("Function 'inc_mem' expects attached memory") 246 | .get(key_ptr, key_sz as usize) 247 | .unwrap(); 248 | let key = String::from_utf8(v).unwrap(); 249 | println!("requested value for key {}", key); 250 | 251 | match self.inner.borrow().db.get(&key) { 252 | None => Ok(Some(RuntimeValue::I64(-1))), 253 | Some(value) => { 254 | let to_write = cmp::min(value.len(), value_sz as usize); 255 | self 256 | .inner 257 | .borrow() 258 | .memory 259 | .as_ref() 260 | .map(|m| m.set(value_ptr, (&value[..to_write]).as_bytes())); 261 | Ok(Some(RuntimeValue::I64(value.len() as i64))) 262 | } 263 | } 264 | } 265 | _ => panic!("env doesn't provide function at index {}", index), 266 | } 267 | } 268 | } 269 | 270 | impl State { 271 | fn check_signature(&self, index: usize, signature: &Signature) -> bool { 272 | let (params, ret_ty): (&[ValueType], Option) = match index { 273 | LOG_INDEX => (&[ValueType::I32, ValueType::I64], None), 274 | RESPONSE_SET_STATUS_LINE => (&[ValueType::I32, ValueType::I32, ValueType::I64], None), 275 | RESPONSE_SET_HEADER => ( 276 | &[ 277 | ValueType::I32, 278 | ValueType::I64, 279 | ValueType::I32, 280 | ValueType::I64, 281 | ], 282 | None, 283 | ), 284 | RESPONSE_SET_BODY => (&[ValueType::I32, ValueType::I64], None), 285 | TCP_CONNECT => (&[ValueType::I32, ValueType::I64], Some(ValueType::I32)), 286 | TCP_READ => ( 287 | &[ValueType::I32, ValueType::I32, ValueType::I64], 288 | Some(ValueType::I64), 289 | ), 290 | TCP_WRITE => ( 291 | &[ValueType::I32, ValueType::I32, ValueType::I64], 292 | Some(ValueType::I64), 293 | ), 294 | DB_GET => ( 295 | &[ 296 | ValueType::I32, 297 | ValueType::I64, 298 | ValueType::I32, 299 | ValueType::I64, 300 | ], 301 | Some(ValueType::I64), 302 | ), 303 | _ => return false, 304 | }; 305 | 306 | signature.params() == params && signature.return_type() == ret_ty 307 | } 308 | } 309 | 310 | impl ModuleImportResolver for State { 311 | fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result { 312 | let index = match field_name { 313 | "log" => LOG_INDEX, 314 | "response_set_status_line" => RESPONSE_SET_STATUS_LINE, 315 | "response_set_header" => RESPONSE_SET_HEADER, 316 | "response_set_body" => RESPONSE_SET_BODY, 317 | "tcp_connect" => TCP_CONNECT, 318 | "tcp_read" => TCP_READ, 319 | "tcp_write" => TCP_WRITE, 320 | "db_get" => DB_GET, 321 | _ => { 322 | return Err(Error::Instantiation(format!( 323 | "Export {} not found", 324 | field_name 325 | ))) 326 | } 327 | }; 328 | 329 | if !self.check_signature(index, signature) { 330 | return Err(Error::Instantiation(format!( 331 | "Export `{}` doesnt match expected type {:?}", 332 | field_name, signature 333 | ))); 334 | } 335 | 336 | Ok(FuncInstance::alloc_host(signature.clone(), index)) 337 | } 338 | 339 | fn resolve_memory(&self, _field_name: &str, _memory_type: &MemoryDescriptor) -> Result { 340 | let Pages(initial1) = self.memory.as_ref().map(|m| m.initial()).unwrap(); 341 | let initial2 = _memory_type.initial() as usize; 342 | //println!("requested {} pages", initial2); 343 | if initial2 > initial1 { 344 | self.memory.as_ref().map(|_m| { 345 | //println!("grow res: {:?}", m.grow(Pages(initial2 - initial1)).unwrap()); 346 | }); 347 | } 348 | let Pages(_initial) = self.memory.as_ref().map(|m| m.current_size()).unwrap(); 349 | //println!("current number of pages: {}", initial); 350 | //println!("resolving memory at name: {}", field_name); 351 | let res = self.memory.as_ref().unwrap().clone(); 352 | 353 | Ok(res) 354 | } 355 | } 356 | -------------------------------------------------------------------------------- /src/sync/mod.rs: -------------------------------------------------------------------------------- 1 | use rouille; 2 | use wasmi::{Error, ExternVal, ImportsBuilder, ModuleInstance}; 3 | use std::rc::Rc; 4 | use std::cell::RefCell; 5 | 6 | use config::{ApplicationState, Config}; 7 | use interpreter::WasmInstance; 8 | 9 | mod host; 10 | 11 | pub fn server(config: Config) { 12 | let state = ApplicationState::new(&config); 13 | 14 | rouille::start_server(&config.listen_address, move |request| { 15 | if let Some((func_name, module, ref opt_env)) = state.route(request.method(), &request.url()) { 16 | let mut env = host::State::new(); 17 | if let Some(h) = opt_env { 18 | env.db.extend( 19 | h.iter() 20 | .map(|(ref k, ref v)| (k.to_string(), v.to_string())), 21 | ); 22 | } 23 | let main = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env)) 24 | .expect("Failed to instantiate module") 25 | .assert_no_start(); 26 | 27 | let mut response = env.prepared_response.clone(); 28 | if let Some(ExternVal::Func(func_ref)) = main.export_by_name(func_name) { 29 | let mut instance: WasmInstance = WasmInstance::new(Rc::new(RefCell::new(env)), &func_ref, &[]); 30 | let res = instance.resume().map_err(|t| Error::Trap(t)); 31 | println!("invocation result: {:?}", res); 32 | response = instance.state.borrow().prepared_response.clone(); 33 | } else { 34 | panic!("handle error here"); 35 | }; 36 | 37 | if let host::PreparedResponse { 38 | status_code: Some(status), 39 | headers, 40 | body: Some(body), 41 | } = response 42 | { 43 | rouille::Response { 44 | status_code: status, 45 | headers: Vec::new(), 46 | data: rouille::ResponseBody::from_data(body), 47 | upgrade: None, 48 | } 49 | } else { 50 | rouille::Response::text("wasm failed").with_status_code(500) 51 | } 52 | } else { 53 | rouille::Response::empty_404() 54 | } 55 | }); 56 | } 57 | 58 | /* 59 | pub fn start(file: &str) { 60 | let module = load_module(file, "handle"); 61 | let mut env = host::SyncHost::new(); 62 | let main = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env)) 63 | .expect("Failed to instantiate module") 64 | .assert_no_start(); 65 | 66 | println!( 67 | "Result: {:?}", 68 | main.invoke_export("handle", &[], &mut env) 69 | ); 70 | } 71 | */ 72 | --------------------------------------------------------------------------------