From b56cc883c1a9a41edb69545d40219591e0b3246e Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Thu, 1 Feb 2018 11:57:02 -0800 Subject: [PATCH] Adopt external tower-grpc and tower-h2 deps #225) The conduit repo includes several library projects that have since been moved into external repos, including `tower-grpc` and `tower-h2`. This change removes these vendored libraries in favor of using the new external crates. --- Cargo.lock | 733 +++++----- Cargo.toml | 5 - codegen/Cargo.toml | 7 - codegen/src/lib.rs | 1284 ----------------- codegen/tests/codegen.rs | 240 --- proxy/Cargo.toml | 16 +- proxy/src/bind.rs | 33 +- proxy/src/control/codec.rs | 63 - proxy/src/control/discovery.rs | 151 +- proxy/src/control/mod.rs | 82 +- proxy/src/control/observe.rs | 32 +- proxy/src/control/pb.rs | 8 +- proxy/src/control/telemetry.rs | 49 +- proxy/src/inbound.rs | 20 +- proxy/src/lib.rs | 6 +- proxy/src/outbound.rs | 39 +- proxy/src/telemetry/sensor/http.rs | 20 +- proxy/src/telemetry/tap/match_.rs | 5 +- proxy/src/timeout.rs | 63 +- proxy/src/transparency/client.rs | 12 +- proxy/src/transport/connect.rs | 1 - proxy/src/transport/mod.rs | 2 +- proxy/tests/support/client.rs | 2 +- tower-grpc-build/Cargo.toml | 8 - tower-grpc-build/src/client.rs | 270 ---- tower-grpc-build/src/lib.rs | 92 -- tower-grpc-build/src/server.rs | 723 ---------- tower-grpc-examples/Cargo.toml | 32 - tower-grpc-examples/build.rs | 17 - tower-grpc-examples/data/route_guide_db.json | 601 -------- .../proto/helloworld/helloworld.proto | 37 - .../proto/routeguide/route_guide.proto | 110 -- tower-grpc-examples/src/helloworld.rs | 79 - tower-grpc-examples/src/route_guide.rs | 155 -- tower-grpc-examples/src/routeguide/data.rs | 42 - tower-grpc-examples/src/routeguide/main.rs | 201 --- tower-grpc/Cargo.toml | 30 - tower-grpc/examples/greeter_client.rs | 209 --- tower-grpc/examples/greeter_server.rs | 190 --- tower-grpc/examples/helloworld_server.rs | 299 ---- tower-grpc/examples/routeguide_client.rs | 427 ------ tower-grpc/examples/routeguide_server.rs | 158 -- tower-grpc/src/client/codec.rs | 383 ----- tower-grpc/src/client/mod.rs | 260 ---- tower-grpc/src/error.rs | 27 - tower-grpc/src/lib.rs | 89 -- tower-grpc/src/protobuf/mod.rs | 433 ------ tower-grpc/src/request.rs | 67 - tower-grpc/src/response.rs | 39 - tower-grpc/src/server/client_streaming.rs | 59 - tower-grpc/src/server/codec.rs | 313 ---- tower-grpc/src/server/mod.rs | 57 - tower-grpc/src/server/server_streaming.rs | 144 -- tower-grpc/src/server/streaming.rs | 122 -- tower-grpc/src/server/unary.rs | 144 -- tower-grpc/src/status.rs | 204 --- tower-h2/Cargo.toml | 21 - tower-h2/examples/client.rs | 143 -- tower-h2/examples/server.rs | 121 -- tower-h2/src/body.rs | 48 - tower-h2/src/client/background.rs | 63 - tower-h2/src/client/mod.rs | 7 - tower-h2/src/client/new_service.rs | 140 -- tower-h2/src/client/service.rs | 204 --- tower-h2/src/flush.rs | 103 -- tower-h2/src/lib.rs | 23 - tower-h2/src/recv_body.rs | 118 -- tower-h2/src/server/mod.rs | 357 ----- 68 files changed, 629 insertions(+), 9613 deletions(-) delete mode 100644 codegen/Cargo.toml delete mode 100644 codegen/src/lib.rs delete mode 100644 codegen/tests/codegen.rs delete mode 100644 proxy/src/control/codec.rs delete mode 100644 tower-grpc-build/Cargo.toml delete mode 100644 tower-grpc-build/src/client.rs delete mode 100644 tower-grpc-build/src/lib.rs delete mode 100644 tower-grpc-build/src/server.rs delete mode 100644 tower-grpc-examples/Cargo.toml delete mode 100644 tower-grpc-examples/build.rs delete mode 100644 tower-grpc-examples/data/route_guide_db.json delete mode 100644 tower-grpc-examples/proto/helloworld/helloworld.proto delete mode 100644 tower-grpc-examples/proto/routeguide/route_guide.proto delete mode 100644 tower-grpc-examples/src/helloworld.rs delete mode 100644 tower-grpc-examples/src/route_guide.rs delete mode 100644 tower-grpc-examples/src/routeguide/data.rs delete mode 100644 tower-grpc-examples/src/routeguide/main.rs delete mode 100644 tower-grpc/Cargo.toml delete mode 100644 tower-grpc/examples/greeter_client.rs delete mode 100644 tower-grpc/examples/greeter_server.rs delete mode 100644 tower-grpc/examples/helloworld_server.rs delete mode 100644 tower-grpc/examples/routeguide_client.rs delete mode 100644 tower-grpc/examples/routeguide_server.rs delete mode 100644 tower-grpc/src/client/codec.rs delete mode 100644 tower-grpc/src/client/mod.rs delete mode 100644 tower-grpc/src/error.rs delete mode 100644 tower-grpc/src/lib.rs delete mode 100644 tower-grpc/src/protobuf/mod.rs delete mode 100644 tower-grpc/src/request.rs delete mode 100644 tower-grpc/src/response.rs delete mode 100644 tower-grpc/src/server/client_streaming.rs delete mode 100644 tower-grpc/src/server/codec.rs delete mode 100644 tower-grpc/src/server/mod.rs delete mode 100644 tower-grpc/src/server/server_streaming.rs delete mode 100644 tower-grpc/src/server/streaming.rs delete mode 100644 tower-grpc/src/server/unary.rs delete mode 100644 tower-grpc/src/status.rs delete mode 100644 tower-h2/Cargo.toml delete mode 100644 tower-h2/examples/client.rs delete mode 100644 tower-h2/examples/server.rs delete mode 100644 tower-h2/src/body.rs delete mode 100644 tower-h2/src/client/background.rs delete mode 100644 tower-h2/src/client/mod.rs delete mode 100644 tower-h2/src/client/new_service.rs delete mode 100644 tower-h2/src/client/service.rs delete mode 100644 tower-h2/src/flush.rs delete mode 100644 tower-h2/src/lib.rs delete mode 100644 tower-h2/src/recv_body.rs delete mode 100644 tower-h2/src/server/mod.rs diff --git a/Cargo.lock b/Cargo.lock index dc041e788..2ab4c9575 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,32 +3,35 @@ name = "abstract-ns" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "adler32" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "aho-corasick" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -36,8 +39,8 @@ name = "backtrace-sys" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -45,32 +48,32 @@ name = "base64" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "build_const" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -79,7 +82,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -87,13 +90,13 @@ name = "bzip2-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -106,15 +109,16 @@ name = "chrono" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "codegen" -version = "0.2.0" +version = "0.1.0" +source = "git+https://github.com/carllerche/codegen#6d0fea3634cc1e3f1576c1c321a20e6e56bfb132" dependencies = [ - "ordermap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -122,24 +126,24 @@ name = "conduit-proxy" version = "0.2.0" dependencies = [ "abstract-ns 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "domain 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "futures-mpsc-lossy 0.2.0", - "h2 0.1.0 (git+https://github.com/carllerche/h2)", + "h2 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.15 (registry+https://github.com/rust-lang/crates.io-index)", "ipnet 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "ns-dns-tokio 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "prost 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prost-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prost-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "quickcheck 0.4.2 (git+https://github.com/BurntSushi/quickcheck?rev=a1658ce)", "tokio-connect 0.1.0 (git+https://github.com/carllerche/tokio-connect)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -148,9 +152,9 @@ dependencies = [ "tower-balance 0.1.0 (git+https://github.com/tower-rs/tower)", "tower-buffer 0.1.0 (git+https://github.com/tower-rs/tower)", "tower-discover 0.1.0 (git+https://github.com/tower-rs/tower)", - "tower-grpc 0.2.0", - "tower-grpc-build 0.2.0", - "tower-h2 0.2.0", + "tower-grpc 0.1.0 (git+https://github.com/tower-rs/tower-grpc)", + "tower-grpc-build 0.1.0 (git+https://github.com/tower-rs/tower-grpc)", + "tower-h2 0.1.0 (git+https://github.com/tower-rs/tower-h2)", "tower-reconnect 0.1.0 (git+https://github.com/tower-rs/tower)", "tower-router 0.2.0", "tower-util 0.1.0 (git+https://github.com/tower-rs/tower)", @@ -158,39 +162,40 @@ dependencies = [ ] [[package]] -name = "curl" -version = "0.4.8" +name = "crc" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "curl" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "curl-sys" -version = "0.3.15" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dbghelp-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -198,17 +203,12 @@ name = "domain" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "dtoa" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "either" version = "1.4.0" @@ -220,15 +220,26 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "error-chain" -version = "0.11.0" +name = "failure" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -238,11 +249,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "flate2" -version = "0.2.20" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -250,14 +261,6 @@ name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "fuchsia-zircon" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -267,14 +270,6 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "fuchsia-zircon-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "fuchsia-zircon-sys" version = "0.3.3" @@ -282,23 +277,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "futures-borrow" -version = "0.1.0" -source = "git+https://github.com/carllerche/better-future#07baa13e91fefe7a51533dfde7b4e69e109ebe14" -dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -306,23 +293,23 @@ dependencies = [ name = "futures-mpsc-lossy" version = "0.2.0" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "h2" version = "0.1.0" -source = "git+https://github.com/carllerche/h2#5d54d8cd79bacfd09816d3156625a66d28772d1b" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.1.0 (git+https://github.com/carllerche/string)", + "string 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -339,7 +326,7 @@ name = "http" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -354,8 +341,8 @@ version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -364,7 +351,7 @@ dependencies = [ "mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -384,10 +371,10 @@ dependencies = [ [[package]] name = "iovec" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -398,25 +385,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "itertools" -version = "0.6.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "itertools" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itoa" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "kernel32-sys" version = "0.2.2" @@ -433,7 +407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "0.2.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -443,7 +417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.33" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -451,8 +425,8 @@ name = "libz-sys" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -480,10 +454,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "1.0.2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -495,12 +469,23 @@ dependencies = [ ] [[package]] -name = "miniz-sys" -version = "0.1.10" +name = "miniz_oxide" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz_oxide_c_api" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -510,10 +495,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -538,7 +523,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -554,7 +539,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -566,18 +551,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "abstract-ns 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "domain 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -585,7 +570,7 @@ name = "num-integer" version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -594,12 +579,12 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.1.40" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -607,21 +592,21 @@ name = "num_cpus" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl-probe" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.20" +version = "0.9.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -633,7 +618,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ordermap" -version = "0.3.0" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -643,11 +628,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "petgraph" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fixedbitset 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ordermap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -657,56 +642,65 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "podio" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "prost" -version = "0.2.3" +name = "proc-macro2" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "prost" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "prost-build" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "petgraph 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "petgraph 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "prost 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prost-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "zip 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "zip 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "prost-derive" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "prost-types" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "prost 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prost-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -721,7 +715,7 @@ source = "git+https://github.com/BurntSushi/quickcheck?rev=a1658ce#a1658ce9fc9ab dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -730,34 +724,52 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "rand" -version = "0.3.18" +name = "quote" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.31" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -765,7 +777,7 @@ name = "relay" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -778,46 +790,20 @@ name = "safemem" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "schannel" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "scoped-tls" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "serde" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde_derive" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive_internals" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "slab" version = "0.3.0" @@ -835,20 +821,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "socket2" -version = "0.2.4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "string" version = "0.1.0" -source = "git+https://github.com/carllerche/string#376413b9447b561500b0fe223a03b8999920b656" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" @@ -860,6 +844,16 @@ dependencies = [ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.12.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synom" version = "0.11.3" @@ -868,6 +862,15 @@ dependencies = [ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "synstructure" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "take" version = "0.1.0" @@ -878,27 +881,26 @@ name = "tempdir" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "thread_local" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "time" -version = "0.1.38" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -906,7 +908,7 @@ name = "tokio-connect" version = "0.1.0" source = "git+https://github.com/carllerche/tokio-connect#f413067d873dcb27540af2f45c135618c4e42a17" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -915,9 +917,9 @@ name = "tokio-core" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -930,8 +932,8 @@ name = "tokio-io" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -940,10 +942,10 @@ name = "tokio-proto" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -957,24 +959,26 @@ name = "tokio-service" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tower" version = "0.1.0" -source = "git+https://github.com/tower-rs/tower#2db5adee4324163636bf845ab523e907dcf0892c" +source = "git+https://github.com/tower-rs/tower#c06aa5452d130da948c0b9a3b587edc094b19045" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tower-balance" version = "0.1.0" -source = "git+https://github.com/tower-rs/tower#2db5adee4324163636bf845ab523e907dcf0892c" +source = "git+https://github.com/tower-rs/tower#c06aa5452d130da948c0b9a3b587edc094b19045" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tower 0.1.0 (git+https://github.com/tower-rs/tower)", "tower-discover 0.1.0 (git+https://github.com/tower-rs/tower)", ] @@ -982,79 +986,55 @@ dependencies = [ [[package]] name = "tower-buffer" version = "0.1.0" -source = "git+https://github.com/tower-rs/tower#2db5adee4324163636bf845ab523e907dcf0892c" +source = "git+https://github.com/tower-rs/tower#c06aa5452d130da948c0b9a3b587edc094b19045" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "tower 0.1.0 (git+https://github.com/tower-rs/tower)", ] [[package]] name = "tower-discover" version = "0.1.0" -source = "git+https://github.com/tower-rs/tower#2db5adee4324163636bf845ab523e907dcf0892c" +source = "git+https://github.com/tower-rs/tower#c06aa5452d130da948c0b9a3b587edc094b19045" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "tower 0.1.0 (git+https://github.com/tower-rs/tower)", ] [[package]] name = "tower-grpc" -version = "0.2.0" +version = "0.1.0" +source = "git+https://github.com/tower-rs/tower-grpc#3aad7412572a9279876af5292ecee13ac267eda2" dependencies = [ - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.0 (git+https://github.com/carllerche/h2)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-connect 0.1.0 (git+https://github.com/carllerche/tokio-connect)", - "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "prost 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tower 0.1.0 (git+https://github.com/tower-rs/tower)", - "tower-h2 0.2.0", - "tower-router 0.1.0 (git+https://github.com/tower-rs/tower)", + "tower-h2 0.1.0 (git+https://github.com/tower-rs/tower-h2)", ] [[package]] name = "tower-grpc-build" -version = "0.2.0" +version = "0.1.0" +source = "git+https://github.com/tower-rs/tower-grpc#3aad7412572a9279876af5292ecee13ac267eda2" dependencies = [ - "codegen 0.2.0", - "prost-build 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tower-grpc-examples" -version = "0.2.0" -dependencies = [ - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tower 0.1.0 (git+https://github.com/tower-rs/tower)", - "tower-grpc 0.2.0", - "tower-grpc-build 0.2.0", - "tower-h2 0.2.0", + "codegen 0.1.0 (git+https://github.com/carllerche/codegen)", + "prost-build 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tower-h2" -version = "0.2.0" +version = "0.1.0" +source = "git+https://github.com/tower-rs/tower-h2#745d02c8489f44b4b1e9549aba4dda0d1f417067" dependencies = [ - "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.0 (git+https://github.com/carllerche/h2)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.1.0 (git+https://github.com/carllerche/string)", "tokio-connect 0.1.0 (git+https://github.com/carllerche/tokio-connect)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1064,19 +1044,10 @@ dependencies = [ [[package]] name = "tower-reconnect" version = "0.1.0" -source = "git+https://github.com/tower-rs/tower#2db5adee4324163636bf845ab523e907dcf0892c" +source = "git+https://github.com/tower-rs/tower#c06aa5452d130da948c0b9a3b587edc094b19045" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tower 0.1.0 (git+https://github.com/tower-rs/tower)", -] - -[[package]] -name = "tower-router" -version = "0.1.0" -source = "git+https://github.com/tower-rs/tower#2db5adee4324163636bf845ab523e907dcf0892c" -dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-borrow 0.1.0 (git+https://github.com/carllerche/better-future)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "tower 0.1.0 (git+https://github.com/tower-rs/tower)", ] @@ -1084,7 +1055,7 @@ dependencies = [ name = "tower-router" version = "0.2.0" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "tower 0.1.0 (git+https://github.com/tower-rs/tower)", ] @@ -1092,9 +1063,9 @@ dependencies = [ [[package]] name = "tower-util" version = "0.1.0" -source = "git+https://github.com/tower-rs/tower#2db5adee4324163636bf845ab523e907dcf0892c" +source = "git+https://github.com/tower-rs/tower#c06aa5452d130da948c0b9a3b587edc094b19045" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "tower 0.1.0 (git+https://github.com/tower-rs/tower)", ] @@ -1129,6 +1100,11 @@ name = "unicode-xid" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unreachable" version = "1.0.0" @@ -1172,11 +1148,30 @@ name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -1188,121 +1183,121 @@ dependencies = [ [[package]] name = "zip" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] "checksum abstract-ns 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "babdbabd818c2b3f5a8b2c2015f5663d454fc8a69b67c0e65f391cfd362841a3" -"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" -"checksum backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8709cc7ec06f6f0ae6c2c7e12f6ed41540781f72b488d83734978295ceae182e" +"checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45" +"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229d032f1a99302697f10b27167ae6d03d49d032e6a8e2550e8d3fc13356d2b4" -"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" -"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" -"checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6" +"checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9" +"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" +"checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9" "checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24" "checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b" -"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719" +"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9" -"checksum curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7034c534a1d7d22f7971d6088aa9d281d219ef724026c3428092500f41ae9c2c" -"checksum curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4bee31aa3a079d5f3ff9579ea4dcfb1b1a17a40886f5f467436d383e78134b55" -"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" +"checksum codegen 0.1.0 (git+https://github.com/carllerche/codegen)" = "" +"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7" +"checksum curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b70fd6394677d3c0e239ff4be6f2b3176e171ffd1c23ffdc541e78dea2b8bb5e" +"checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961" "checksum domain 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c1850bf2c3c3349e1dba2aa214d86cf9edaa057a09ce46b1a02d5c07d5da5e65" -"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" +"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" "checksum fixedbitset 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "85cb8fec437468d86dc7c83ca7cfc933341d561873275f22dd5eedefa63a6478" -"checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" +"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "118b49cac82e04121117cbd3121ede3147e885627d82c4546b87c702debb90c1" -"checksum futures-borrow 0.1.0 (git+https://github.com/carllerche/better-future)" = "" +"checksum futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0bab5b5e94f5c31fc764ba5dd9ad16568aae5d4825538c01d6bca680c9bf94a7" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum h2 0.1.0 (git+https://github.com/carllerche/h2)" = "" +"checksum h2 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5617f23e03f04b44147b0dee52d1146e61b5044994659dedf71246ccd34eb48e" "checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" "checksum http 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf8217d8829cc05dedadc08b4bc0684e5e3fbba1126c5edc680af49053fa230c" "checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" "checksum hyper 0.11.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4d6105c5eeb03068b10ff34475a0d166964f98e7b9777cc34b342a225af9b87c" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" -"checksum iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6e8b9c2247fcf6c6a1151f1156932be5606c9fd6f55a2d7f9fc1cb29386b2f7" +"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum ipnet 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51268c3a27ad46afd1cca0bbf423a5be2e9fd3e6a7534736c195f0f834b763ef" -"checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21" -"checksum itertools 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c52051d3fd3b505796a0ee90f2e5ec43213808585e8adc4d0182492cf62751a" -"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" +"checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "236eb37a62591d4a41a89b7763d7de3e06ca02d5ab2815446a8bae5d2f8c2d57" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" -"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" +"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" "checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" -"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" -"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" +"checksum miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aaa2d3ad070f428fffbd7d3ca2ea20bb0d8cffe9024405c44e1840bc1418b398" +"checksum miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92d98fdbd6145645828069b37ea92ca3de225e000d80702da25c20d3584b38a5" "checksum mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "75f72a93f046f1517e3cfddc0a096eb756a2ba727d36edc8227dee769a50a9b0" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "65ba9d75bcea84e07812618fedf284a64776c2f2ea0cad6bca7f69739695a958" "checksum multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb04b9f127583ed176e163fb9ec6f3e793b87e21deedd5734a69386a18a0151" "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" "checksum ns-dns-tokio 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75311dd15a3051ab6adb4ae1de6824146d304a25030b8d12e0ae842e484157c5" -"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525" +"checksum num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4083e14b542ea3eb9b5f33ff48bd373a92d78687e74f4cc0a30caeb754f0ca" "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01" -"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" +"checksum num-traits 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "9936036cc70fe4a8b2d338ab665900323290efb03983c86cbe235ae800ad8017" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" -"checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf" -"checksum openssl-sys 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)" = "0ad395f1cee51b64a8d07cc8063498dc7554db62d5f3ca87a67f4eed2791d0c8" +"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +"checksum openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "14ba54ac7d5a4eabd1d5f2c1fdeb7e7c14debfa669d94b983d01b465e767ba9e" "checksum ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b81cf3b8cb96aa0e73bbedfcdc9708d09fec2854ba8d474be4e6f666d7379e8b" -"checksum ordermap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c7790b1bc9bf27776cd5cdeaae1263758c2c597d4ae02b58aa63c320f94d778" +"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum petgraph 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "28d0872a49ce3ee71b345f4fa675afe394d9e0d077f8eeeb3d04081724065d67" +"checksum petgraph 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7e5234c228fbfa874c86a77f685886127f82e0aef602ad1d48333fcac6ad61" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" -"checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0" -"checksum prost 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f66b40a469da708e5bb9463d92b434a7581aa7758305a22950ae4a63dc1cf93e" -"checksum prost-build 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b39ad9ea74b849e8a52dc259f794aa359ee967e080e44ceb60ec0e02f810611" -"checksum prost-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69fb9d2ab8ce9a3bd0e672de4292e110808c0cb8a6ce8d36c5301a7a9d6b89ee" -"checksum prost-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "03384dd1993571b90ca092c1dbf01b8dcf722dd31f9f8418190c83be26e60aed" +"checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd" +"checksum proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d1cb7aaaa4bf022ec2b14ff2f2ba1643a22f3cee88df014a85e14b392282c61d" +"checksum prost 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2d0af5d1459c836f160c1e57a95ed560f04ba6483206198c7f9456b20a05abe" +"checksum prost-build 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b53077811e2662acfb5ee60ff842791ecc16e8fcc8d0c1de60716f9fd5f9748" +"checksum prost-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc57900c837af0e8bf5917e3d1fa45109cde500b36dc65621eb2775acde0d54d" +"checksum prost-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc53b19b9de90ddbcdaa34120141cdcca68ad5f0de4859cc94f5417878958fc2" "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" "checksum quickcheck 0.4.2 (git+https://github.com/BurntSushi/quickcheck?rev=a1658ce)" = "" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd" -"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" -"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" -"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" +"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" +"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" +"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" +"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" +"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" "checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" +"checksum schannel 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "acece75e0f987c48863a6c792ec8b7d6c4177d4a027f8ccc72f849794f437016" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" -"checksum serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6eda663e865517ee783b0891a3f6eb3a253e0b0dabb46418969ee9635beadd9e" -"checksum serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "652bc323d694dc925829725ec6c890156d8e70ae5202919869cb00fe2eff3788" -"checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab" -"checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" -"checksum socket2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b4896961171cd3317c7e9603d88f379f8c6e45342212235d356496680c68fd" -"checksum string 0.1.0 (git+https://github.com/carllerche/string)" = "" +"checksum socket2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a76b792959eba82f021c9028c8ecb6396f085268d6d46af2ed96a829cc758d7c" +"checksum string 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31f98b200e7caca9efca50fc0aa69cd58a5ec81d5f6e75b2f3ecaad2e998972a" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum syn 0.12.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7d12ebcea3f1027a817b98e91cfe30805634ea1f63e36015f765960a7782494d" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" -"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" -"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" +"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" "checksum tokio-connect 0.1.0 (git+https://github.com/carllerche/tokio-connect)" = "" "checksum tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "52b4e32d8edbf29501aabb3570f027c6ceb00ccef6538f4bddba0200503e74e8" "checksum tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "514aae203178929dbf03318ad7c683126672d4d96eccb77b29603d33c9e25743" @@ -1312,14 +1307,17 @@ dependencies = [ "checksum tower-balance 0.1.0 (git+https://github.com/tower-rs/tower)" = "" "checksum tower-buffer 0.1.0 (git+https://github.com/tower-rs/tower)" = "" "checksum tower-discover 0.1.0 (git+https://github.com/tower-rs/tower)" = "" +"checksum tower-grpc 0.1.0 (git+https://github.com/tower-rs/tower-grpc)" = "" +"checksum tower-grpc-build 0.1.0 (git+https://github.com/tower-rs/tower-grpc)" = "" +"checksum tower-h2 0.1.0 (git+https://github.com/tower-rs/tower-h2)" = "" "checksum tower-reconnect 0.1.0 (git+https://github.com/tower-rs/tower)" = "" -"checksum tower-router 0.1.0 (git+https://github.com/tower-rs/tower)" = "" "checksum tower-util 0.1.0 (git+https://github.com/tower-rs/tower)" = "" "checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" @@ -1327,6 +1325,9 @@ dependencies = [ "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum zip 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "21c4067ff2f91926cb9aef8a8a55f8568b0f2631bb6b827d0fb9770ff5894e43" +"checksum zip 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "e7341988e4535c60882d5e5f0b7ad0a9a56b080ade8bdb5527cb512f7b2180e0" diff --git a/Cargo.toml b/Cargo.toml index 7a6ed1c57..f191b2563 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,6 @@ [workspace] members = [ - "codegen", "futures-mpsc-lossy", "proxy", "tower-router", - "tower-grpc", - "tower-grpc-build", - "tower-grpc-examples", - "tower-h2", ] diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml deleted file mode 100644 index a38e895a3..000000000 --- a/codegen/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "codegen" -version = "0.2.0" -authors = ["Carl Lerche "] - -[dependencies] -ordermap = "0.3.0" diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs deleted file mode 100644 index 533e0ab60..000000000 --- a/codegen/src/lib.rs +++ /dev/null @@ -1,1284 +0,0 @@ -extern crate ordermap; - -use ordermap::OrderMap; -use std::fmt::{self, Write}; - -/// Defines a scope. -/// -/// A scope contains modules, types, etc... -#[derive(Debug, Clone)] -pub struct Scope { - /// Scope documentation - docs: Option, - - /// Imports - imports: OrderMap>, - - /// Contents of the documentation, - items: Vec, -} - -#[derive(Debug, Clone)] -enum Item { - Module(Module), - Struct(Struct), - Enum(Enum), - Impl(Impl), -} - -/// Defines a module -#[derive(Debug, Clone)] -pub struct Module { - /// Module name - name: String, - - /// Visibility - vis: Option, - - /// Module documentation - docs: Option, - - /// Contents of the module - scope: Scope, -} - -/// Defines an enumeration -#[derive(Debug, Clone)] -pub struct Enum { - type_def: TypeDef, - variants: Vec, -} - -/// Defines a struct -#[derive(Debug, Clone)] -pub struct Struct { - type_def: TypeDef, - - /// Struct fields - fields: Fields, -} - -#[derive(Debug, Clone)] -pub struct Type { - name: String, - generics: Vec, -} - -/// A type definition -#[derive(Debug, Clone)] -struct TypeDef { - ty: Type, - vis: Option, - docs: Option, - derive: Vec, - bounds: Vec, -} - -/// An enum variant -#[derive(Debug, Clone)] -pub struct Variant { - name: String, - fields: Fields, -} - -#[derive(Debug, Clone)] -enum Fields { - Empty, - Tuple(Vec), - Named(Vec), -} - -/// Defines a struct field -#[derive(Debug, Clone)] -struct Field { - /// Field name - name: String, - - /// Field type - ty: Type, -} - -#[derive(Debug, Clone)] -pub struct Impl { - /// The struct being implemented - target: Type, - - /// Impl level generics - generics: Vec, - - /// If implementing a trait - impl_trait: Option, - - /// Associated types - assoc_tys: Vec, - - /// Bounds - bounds: Vec, - - fns: Vec, -} - -/// Import -#[derive(Debug, Clone)] -pub struct Import { - line: String, - vis: Option, -} - -/// A function definition -#[derive(Debug, Clone)] -pub struct Function { - /// Name of the function - name: String, - - /// Function documentation - docs: Option, - - /// Function visibility - vis: Option, - - /// Function generics - generics: Vec, - - /// If the function takes `&self` or `&mut self` - arg_self: Option, - - /// Function arguments - args: Vec, - - /// Return type - ret: Option, - - /// Where bounds - bounds: Vec, - - /// Body contents - body: Vec, -} - -/// A block of code -#[derive(Debug, Clone)] -pub struct Block { - before: Option, - after: Option, - body: Vec, -} - -#[derive(Debug, Clone)] -enum Body { - String(String), - Block(Block), -} - -#[derive(Debug, Clone)] -struct Docs { - docs: String, -} - -/// Formatting configuration -#[derive(Debug)] -pub struct Formatter<'a> { - /// Write destination - dst: &'a mut String, - - /// Number of spaces to start a new line with - spaces: usize, - - /// Number of spaces per indentiation - indent: usize, -} - -const DEFAULT_INDENT: usize = 4; - -// ===== impl Scope ===== - -impl Scope { - /// Returns a new scope - pub fn new() -> Self { - Scope { - docs: None, - imports: OrderMap::new(), - items: vec![], - } - } - - /// Push an `use` line - pub fn import(&mut self, path: &str, ty: &str) -> &mut Import { - self.imports.entry(path.to_string()) - .or_insert(OrderMap::new()) - .entry(ty.to_string()) - .or_insert_with(|| Import::new(path, ty)) - } - - /// Pushes a new module definition, returning a mutable reference to the - /// definition. - pub fn module(&mut self, name: &str) -> &mut Module { - self.push_module(Module::new(name)); - - match *self.items.last_mut().unwrap() { - Item::Module(ref mut v) => v, - _ => unreachable!(), - } - } - - /// Push a module definition - pub fn push_module(&mut self, module: Module) -> &mut Self { - self.items.push(Item::Module(module)); - self - } - - /// Push a new struct definition, returning a mutable reference to the - /// definition. - pub fn structure(&mut self, name: &str) -> &mut Struct { - self.push_structure(Struct::new(name)); - - match *self.items.last_mut().unwrap() { - Item::Struct(ref mut v) => v, - _ => unreachable!(), - } - } - - /// Push a structure definition - pub fn push_structure(&mut self, structure: Struct) -> &mut Self { - self.items.push(Item::Struct(structure)); - self - } - - /// Push a new struct definition, returning a mutable reference to the - /// definition. - pub fn enumeration(&mut self, name: &str) -> &mut Enum { - self.push_enumeration(Enum::new(name)); - - match *self.items.last_mut().unwrap() { - Item::Enum(ref mut v) => v, - _ => unreachable!(), - } - } - - /// Push a structure definition - pub fn push_enumeration(&mut self, enumeration: Enum) -> &mut Self { - self.items.push(Item::Enum(enumeration)); - self - } - - pub fn imp(&mut self, target: &str) -> &mut Impl { - self.push_imp(Impl::new(target)); - - match *self.items.last_mut().unwrap() { - Item::Impl(ref mut v) => v, - _ => unreachable!(), - } - } - - pub fn push_imp(&mut self, imp: Impl) -> &mut Self { - self.items.push(Item::Impl(imp)); - self - } - - /// Return a string representation of the scope. - pub fn to_string(&self) -> String { - let mut ret = String::new(); - - self.fmt(&mut Formatter::new(&mut ret)).unwrap(); - - // Remove the trailing newline - if ret.as_bytes().last() == Some(&b'\n') { - ret.pop(); - } - - ret - } - - pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - self.fmt_imports(fmt)?; - - if !self.imports.is_empty() { - write!(fmt, "\n")?; - } - - for (i, item) in self.items.iter().enumerate() { - if i != 0 { - write!(fmt, "\n")?; - } - - match *item { - Item::Module(ref v) => v.fmt(fmt)?, - Item::Struct(ref v) => v.fmt(fmt)?, - Item::Enum(ref v) => v.fmt(fmt)?, - Item::Impl(ref v) => v.fmt(fmt)?, - } - } - - Ok(()) - } - - fn fmt_imports(&self, fmt: &mut Formatter) -> fmt::Result { - // First, collect all visibilities - let mut visibilities = vec![]; - - for (_, imports) in &self.imports { - for (_, import) in imports { - if !visibilities.contains(&import.vis) { - visibilities.push(import.vis.clone()); - } - } - } - - let mut tys = vec![]; - - // Loop over all visibilities and format the associated imports - for vis in &visibilities { - for (path, imports) in &self.imports { - tys.clear(); - - for (ty, import) in imports { - if *vis == import.vis { - tys.push(ty); - } - } - - if !tys.is_empty() { - if let Some(ref vis) = *vis { - write!(fmt, "{} ", vis)?; - } - - write!(fmt, "use {}::", path)?; - - if tys.len() > 1 { - write!(fmt, "{{")?; - - for (i, ty) in tys.iter().enumerate() { - if i != 0 { write!(fmt, ", ")?; } - write!(fmt, "{}", ty)?; - } - - write!(fmt, "}};\n")?; - } else if tys.len() == 1 { - write!(fmt, "{};\n", tys[0])?; - } - } - } - } - - Ok(()) - } -} - -// ===== impl Module ===== - -impl Module { - /// Return a new, blank module - pub fn new(name: &str) -> Self { - Module { - name: name.to_string(), - vis: None, - docs: None, - scope: Scope::new(), - } - } - - pub fn vis(&mut self, vis: &str) -> &mut Self { - self.vis = Some(vis.to_string()); - self - } - - /// Push an `use` line - pub fn import(&mut self, path: &str, ty: &str) -> &mut Self { - self.scope.import(path, ty); - self - } - - /// Pushes a new module definition, returning a mutable reference to the - /// definition. - pub fn module(&mut self, name: &str) -> &mut Module { - self.scope.module(name) - } - - /// Push a module definition - pub fn push_module(&mut self, module: Module) -> &mut Self { - self.scope.push_module(module); - self - } - - /// Push a new struct definition, returning a mutable reference to the - /// definition. - pub fn structure(&mut self, name: &str) -> &mut Struct { - self.scope.structure(name) - } - - /// Push a structure definition - pub fn push_structure(&mut self, structure: Struct) -> &mut Self { - self.scope.push_structure(structure); - self - } - - /// Push a new struct definition, returning a mutable reference to the - /// definition. - pub fn enumeration(&mut self, name: &str) -> &mut Enum { - self.scope.enumeration(name) - } - - /// Push a structure definition - pub fn push_enumeration(&mut self, enumeration: Enum) -> &mut Self { - self.scope.push_enumeration(enumeration); - self - } - - pub fn imp(&mut self, target: &str) -> &mut Impl { - self.scope.imp(target) - } - - pub fn push_imp(&mut self, imp: Impl) -> &mut Self { - self.scope.push_imp(imp); - self - } - - pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - if let Some(ref vis) = self.vis { - write!(fmt, "{} ", vis)?; - } - - write!(fmt, "mod {}", self.name)?; - fmt.block(|fmt| { - self.scope.fmt(fmt) - }) - } -} - -// ===== impl Struct ===== - -impl Struct { - /// Return a structure definition with the provided name - pub fn new(name: &str) -> Self { - Struct { - type_def: TypeDef::new(name), - fields: Fields::Empty, - } - } - - /// Returns a reference to the type - pub fn ty(&self) -> &Type { - &self.type_def.ty - } - - pub fn vis(&mut self, vis: &str) -> &mut Self { - self.type_def.vis(vis); - self - } - - pub fn generic(&mut self, name: &str) -> &mut Self { - self.type_def.ty.generic(name); - self - } - - pub fn bound(&mut self, name: &str, ty: T) -> &mut Self - where T: Into, - { - self.type_def.bound(name, ty); - self - } - - pub fn doc(&mut self, docs: &str) -> &mut Self { - self.type_def.doc(docs); - self - } - - pub fn derive(&mut self, name: &str) -> &mut Self { - self.type_def.derive(name); - self - } - - pub fn field(&mut self, name: &str, ty: T) -> &mut Self - where T: Into, - { - self.fields.named(name, ty); - self - } - - pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - self.type_def.fmt_head("struct", fmt)?; - self.fields.fmt(fmt)?; - - Ok(()) - } -} - -// ===== impl Enum ===== - -impl Enum { - /// Return a structure definition with the provided name - pub fn new(name: &str) -> Self { - Enum { - type_def: TypeDef::new(name), - variants: vec![], - } - } - - /// Returns a reference to the type - pub fn ty(&self) -> &Type { - &self.type_def.ty - } - - pub fn vis(&mut self, vis: &str) -> &mut Self { - self.type_def.vis(vis); - self - } - - pub fn generic(&mut self, name: &str) -> &mut Self { - self.type_def.ty.generic(name); - self - } - - pub fn bound(&mut self, name: &str, ty: T) -> &mut Self - where T: Into, - { - self.type_def.bound(name, ty); - self - } - - pub fn doc(&mut self, docs: &str) -> &mut Self { - self.type_def.doc(docs); - self - } - - pub fn derive(&mut self, name: &str) -> &mut Self { - self.type_def.derive(name); - self - } - - pub fn variant(&mut self, name: &str) -> &mut Variant { - self.push_variant(Variant::new(name)); - self.variants.last_mut().unwrap() - } - - pub fn push_variant(&mut self, variant: Variant) -> &mut Self { - self.variants.push(variant); - self - } - - pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - self.type_def.fmt_head("enum", fmt)?; - - fmt.block(|fmt| { - for variant in &self.variants { - variant.fmt(fmt)?; - } - - Ok(()) - }) - } -} - -// ===== impl Variant ===== - -impl Variant { - pub fn new(name: &str) -> Self { - Variant { - name: name.to_string(), - fields: Fields::Empty, - } - } - - pub fn named(&mut self, name: &str, ty: T) -> &mut Self - where T: Into, - { - self.fields.named(name, ty); - self - } - - pub fn tuple(&mut self, ty: &str) -> &mut Self { - self.fields.tuple(ty); - self - } - - pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - write!(fmt, "{}", self.name)?; - self.fields.fmt(fmt)?; - write!(fmt, ",\n")?; - - Ok(()) - } -} - -// ===== impl Type ===== - -impl Type { - pub fn new(name: &str) -> Self { - Type { - name: name.to_string(), - generics: vec![], - } - } - - pub fn generic(&mut self, ty: T) -> &mut Self - where T: Into, - { - // Make sure that the name doesn't already include generics - assert!(!self.name.contains("<"), "type name already includes generics"); - - self.generics.push(ty.into()); - self - } - - /// Rewrite the `Type` with the provided path - pub fn path(&self, path: &str) -> Type { - // TODO: This isn't really correct - assert!(!self.name.contains("::")); - - let mut name = path.to_string(); - name.push_str("::"); - name.push_str(&self.name); - - Type { - name, - generics: self.generics.clone(), - } - } - - pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - write!(fmt, "{}", self.name)?; - Type::fmt_slice(&self.generics, fmt) - } - - fn fmt_slice(generics: &[Type], fmt: &mut Formatter) -> fmt::Result { - if !generics.is_empty() { - write!(fmt, "<")?; - - for (i, ty) in generics.iter().enumerate() { - if i != 0 { write!(fmt, ", ")? } - ty.fmt(fmt)?; - } - - write!(fmt, ">")?; - } - - Ok(()) - } -} - -impl<'a> From<&'a str> for Type { - fn from(src: &'a str) -> Self { - Type::new(src) - } -} - -impl From for Type { - fn from(src: String) -> Self { - Type { - name: src, - generics: vec![], - } - } -} - -impl<'a> From<&'a String> for Type { - fn from(src: &'a String) -> Self { - Type::new(src) - } -} - -impl<'a> From<&'a Type> for Type { - fn from(src: &'a Type) -> Self { - src.clone() - } -} - -// ===== impl TypeDef ===== - -impl TypeDef { - /// Return a structure definition with the provided name - pub fn new(name: &str) -> Self { - TypeDef { - ty: Type::new(name), - vis: None, - docs: None, - derive: vec![], - bounds: vec![], - } - } - - fn vis(&mut self, vis: &str) { - self.vis = Some(vis.to_string()); - } - - fn bound(&mut self, name: &str, ty: T) - where T: Into, - { - self.bounds.push(Field { - name: name.to_string(), - ty: ty.into(), - }); - } - - fn doc(&mut self, docs: &str) { - self.docs = Some(Docs::new(docs)); - } - - fn derive(&mut self, name: &str) { - self.derive.push(name.to_string()); - } - - fn fmt_head(&self, keyword: &str, fmt: &mut Formatter) -> fmt::Result { - if let Some(ref docs) = self.docs { - docs.fmt(fmt)?; - } - - self.fmt_derive(fmt)?; - - if let Some(ref vis) = self.vis { - write!(fmt, "{} ", vis)?; - } - - write!(fmt, "{} ", keyword)?; - self.ty.fmt(fmt)?; - - fmt_bounds(&self.bounds, fmt)?; - - Ok(()) - } - - fn fmt_derive(&self, fmt: &mut Formatter) -> fmt::Result { - if !self.derive.is_empty() { - write!(fmt, "#[derive(")?; - - for (i, name) in self.derive.iter().enumerate() { - if i != 0 { write!(fmt, ", ")? } - write!(fmt, "{}", name)?; - } - - write!(fmt, ")]\n")?; - } - - Ok(()) - } -} - -fn fmt_generics(generics: &[String], fmt: &mut Formatter) -> fmt::Result { - if !generics.is_empty() { - write!(fmt, "<")?; - - for (i, ty) in generics.iter().enumerate() { - if i != 0 { write!(fmt, ", ")? } - write!(fmt, "{}", ty)?; - } - - write!(fmt, ">")?; - } - - Ok(()) -} - -fn fmt_bounds(bounds: &[Field], fmt: &mut Formatter) -> fmt::Result { - if !bounds.is_empty() { - write!(fmt, "\n")?; - - // Write first bound - write!(fmt, "where {}: ", bounds[0].name)?; - bounds[0].ty.fmt(fmt)?; - write!(fmt, ",\n")?; - - for bound in &bounds[1..] { - write!(fmt, " {}: ", bound.name)?; - bound.ty.fmt(fmt)?; - write!(fmt, ",\n")?; - } - } - - Ok(()) -} - -// ===== impl Fields ===== - -impl Fields { - fn named(&mut self, name: &str, ty: T) -> &mut Self - where T: Into, - { - match *self { - Fields::Empty => { - *self = Fields::Named(vec![Field { - name: name.to_string(), - ty: ty.into(), - }]); - } - Fields::Named(ref mut fields) => { - fields.push(Field { - name: name.to_string(), - ty: ty.into(), - }); - } - _ => panic!("field list is named"), - } - - self - } - - fn tuple(&mut self, ty: T) -> &mut Self - where T: Into, - { - match *self { - Fields::Empty => { - *self = Fields::Tuple(vec![ty.into()]); - } - Fields::Tuple(ref mut fields) => { - fields.push(ty.into()); - } - _ => panic!("field list is tuple"), - } - - self - } - - fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - match *self { - Fields::Named(ref fields) => { - assert!(!fields.is_empty()); - - fmt.block(|fmt| { - for f in fields { - write!(fmt, "{}: ", f.name)?; - f.ty.fmt(fmt)?; - write!(fmt, ",\n")?; - } - - Ok(()) - })?; - } - Fields::Tuple(ref tys) => { - assert!(!tys.is_empty()); - - write!(fmt, "(")?; - - for (i, ty) in tys.iter().enumerate() { - if i != 0 { write!(fmt, ", ")?; } - ty.fmt(fmt)?; - } - - write!(fmt, ")")?; - } - Fields::Empty => {} - } - - Ok(()) - } -} - -// ===== impl Impl ===== - -impl Impl { - /// Return a new impl definition - pub fn new(target: T) -> Self - where T: Into, - { - Impl { - target: target.into(), - generics: vec![], - impl_trait: None, - assoc_tys: vec![], - bounds: vec![], - fns: vec![], - } - } - - pub fn generic(&mut self, name: &str) -> &mut Self { - self.generics.push(name.to_string()); - self - } - - pub fn target_generic(&mut self, ty: T) -> &mut Self - where T: Into, - { - self.target.generic(ty); - self - } - - pub fn impl_trait(&mut self, name: &str) -> &mut Self { - self.impl_trait = Some(name.to_string()); - self - } - - pub fn associate_type(&mut self, name: &str, ty: T) -> &mut Self - where T: Into, - { - self.assoc_tys.push(Field { - name: name.to_string(), - ty: ty.into(), - }); - - self - } - - pub fn bound(&mut self, name: &str, ty: T) -> &mut Self - where T: Into, - { - self.bounds.push(Field { - name: name.to_string(), - ty: ty.into(), - }); - self - } - - /// Define a new function - pub fn function(&mut self, name: &str) -> &mut Function { - self.push_function(Function::new(name)); - self.fns.last_mut().unwrap() - } - - /// Push a function definition - pub fn push_function(&mut self, func: Function) -> &mut Self { - self.fns.push(func); - self - } - - pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - write!(fmt, "impl")?; - fmt_generics(&self.generics[..], fmt)?; - - if let Some(ref t) = self.impl_trait { - write!(fmt, " {} for", t)?; - } - - write!(fmt, " ")?; - self.target.fmt(fmt)?; - - fmt_bounds(&self.bounds, fmt)?; - - fmt.block(|fmt| { - // format associated types - if !self.assoc_tys.is_empty() { - for ty in &self.assoc_tys { - write!(fmt, "type {} = ", ty.name)?; - ty.ty.fmt(fmt)?; - write!(fmt, ";\n")?; - } - } - - for (i, func) in self.fns.iter().enumerate() { - if i != 0 || !self.assoc_tys.is_empty() { write!(fmt, "\n")?; } - - func.fmt(fmt)?; - } - - Ok(()) - }) - } -} - -// ===== impl Import ===== - -impl Import { - pub fn new(path: &str, ty: &str) -> Self { - Import { - line: format!("{}::{}", path, ty), - vis: None, - } - } - - pub fn vis(&mut self, vis: &str) -> &mut Self { - self.vis = Some(vis.to_string()); - self - } -} - -// ===== impl Func ===== - -impl Function { - pub fn new(name: &str) -> Self { - Function { - name: name.to_string(), - docs: None, - vis: None, - generics: vec![], - arg_self: None, - args: vec![], - ret: None, - bounds: vec![], - body: vec![], - } - } - - pub fn docs(&mut self, docs: &str) -> &mut Self { - self.docs = Some(Docs::new(docs)); - self - } - - pub fn vis(&mut self, vis: &str) -> &mut Self { - self.vis = Some(vis.to_string()); - self - } - - pub fn generic(&mut self, name: &str) -> &mut Self { - self.generics.push(name.to_string()); - self - } - - pub fn arg_self(&mut self) -> &mut Self { - self.arg_self = Some("self".to_string()); - self - } - - pub fn arg_ref_self(&mut self) -> &mut Self { - self.arg_self = Some("&self".to_string()); - self - } - - pub fn arg_mut_self(&mut self) -> &mut Self { - self.arg_self = Some("&mut self".to_string()); - self - } - - pub fn arg(&mut self, name: &str, ty: T) -> &mut Self - where T: Into, - { - self.args.push(Field { - name: name.to_string(), - ty: ty.into(), - }); - - self - } - - pub fn ret(&mut self, ty: T) -> &mut Self - where T: Into, - { - self.ret = Some(ty.into()); - self - } - - pub fn bound(&mut self, name: &str, ty: T) -> &mut Self - where T: Into, - { - self.bounds.push(Field { - name: name.to_string(), - ty: ty.into(), - }); - self - } - - pub fn line(&mut self, line: T) -> &mut Self - where T: ToString, - { - self.body.push(Body::String(line.to_string())); - self - } - - pub fn block(&mut self, block: Block) -> &mut Self { - self.body.push(Body::Block(block)); - self - } - - pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - if let Some(ref docs) = self.docs { - docs.fmt(fmt)?; - } - - if let Some(ref vis) = self.vis { - write!(fmt, "{} ", vis)?; - } - - write!(fmt, "fn {}", self.name)?; - fmt_generics(&self.generics, fmt)?; - - write!(fmt, "(")?; - - if let Some(ref s) = self.arg_self { - write!(fmt, "{}", s)?; - } - - for (i, arg) in self.args.iter().enumerate() { - if i != 0 || self.arg_self.is_some() { - write!(fmt, ", ")?; - } - - write!(fmt, "{}: ", arg.name)?; - arg.ty.fmt(fmt)?; - } - - write!(fmt, ")")?; - - if let Some(ref ret) = self.ret { - write!(fmt, " -> ")?; - ret.fmt(fmt)?; - } - - fmt_bounds(&self.bounds, fmt)?; - - fmt.block(|fmt| { - for b in &self.body { - b.fmt(fmt)?; - } - - Ok(()) - }) - } -} - -// ===== impl Block ===== - -impl Block { - pub fn new(before: &str) -> Self { - Block { - before: Some(before.to_string()), - after: None, - body: vec![], - } - } - - pub fn line(&mut self, line: T) -> &mut Self - where T: ToString, - { - self.body.push(Body::String(line.to_string())); - self - } - - pub fn block(&mut self, block: Block) -> &mut Self { - self.body.push(Body::Block(block)); - self - } - - pub fn after(&mut self, after: &str) -> &mut Self { - self.after = Some(after.to_string()); - self - } - - pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - if let Some(ref before) = self.before { - write!(fmt, "{}", before)?; - } - - // Inlined `Formatter::fmt` - - if !fmt.is_start_of_line() { - write!(fmt, " ")?; - } - - write!(fmt, "{{\n")?; - - fmt.indent(|fmt| { - for b in &self.body { - b.fmt(fmt)?; - } - - Ok(()) - })?; - - write!(fmt, "}}")?; - - if let Some(ref after) = self.after { - write!(fmt, "{}", after)?; - } - - write!(fmt, "\n")?; - Ok(()) - } -} - -// ===== impl Body ===== - -impl Body { - pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - match *self { - Body::String(ref s) => { - write!(fmt, "{}\n", s) - } - Body::Block(ref b) => { - b.fmt(fmt) - } - } - } -} - -// ===== impl Docs ===== - -impl Docs { - fn new(docs: &str) -> Self { - Docs { docs: docs.to_string() } - } - - fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - for line in self.docs.lines() { - write!(fmt, "/// {}\n", line)?; - } - - Ok(()) - } -} - -// ===== impl Formatter ===== - -impl<'a> Formatter<'a> { - pub fn new(dst: &'a mut String) -> Self { - Formatter { - dst, - spaces: 0, - indent: DEFAULT_INDENT, - } - } - - fn block(&mut self, f: F) -> fmt::Result - where F: FnOnce(&mut Self) -> fmt::Result - { - if !self.is_start_of_line() { - write!(self, " ")?; - } - - write!(self, "{{\n")?; - self.indent(f)?; - write!(self, "}}\n")?; - Ok(()) - } - - /// Call the given function with the indentation level incremented by one. - fn indent(&mut self, f: F) -> R - where F: FnOnce(&mut Self) -> R - { - self.spaces += self.indent; - let ret = f(self); - self.spaces -= self.indent; - ret - } - - fn is_start_of_line(&self) -> bool { - self.dst.is_empty() || - self.dst.as_bytes().last() == Some(&b'\n') - } - - fn push_spaces(&mut self) { - for _ in 0..self.spaces { - self.dst.push_str(" "); - } - } -} - -impl<'a> fmt::Write for Formatter<'a> { - fn write_str(&mut self, s: &str) -> fmt::Result { - let mut first = true; - let mut should_indent = self.is_start_of_line(); - - for line in s.lines() { - if !first { - self.dst.push_str("\n"); - } - - first = false; - - let do_indent = should_indent && - !line.is_empty() && - line.as_bytes()[0] != b'\n'; - - if do_indent { - self.push_spaces(); - } - - // If this loops again, then we just wrote a new line - should_indent = true; - - self.dst.push_str(line); - } - - if s.as_bytes().last() == Some(&b'\n') { - self.dst.push_str("\n"); - } - - Ok(()) - } -} diff --git a/codegen/tests/codegen.rs b/codegen/tests/codegen.rs deleted file mode 100644 index 629c4cf47..000000000 --- a/codegen/tests/codegen.rs +++ /dev/null @@ -1,240 +0,0 @@ -extern crate codegen; - -use codegen::Scope; - -#[test] -fn empty_scope() { - let scope = Scope::new(); - - assert_eq!(scope.to_string(), ""); -} - -#[test] -fn single_struct() { - let mut scope = Scope::new(); - - scope.structure("Foo") - .field("one", "usize") - .field("two", "String"); - - let expect = r#" -struct Foo { - one: usize, - two: String, -}"#; - - assert_eq!(scope.to_string(), &expect[1..]); -} - -#[test] -fn two_structs() { - let mut scope = Scope::new(); - - scope.structure("Foo") - .field("one", "usize") - .field("two", "String"); - - scope.structure("Bar") - .field("hello", "World"); - - let expect = r#" -struct Foo { - one: usize, - two: String, -} - -struct Bar { - hello: World, -}"#; - - assert_eq!(scope.to_string(), &expect[1..]); -} - -#[test] -fn struct_with_derive() { - let mut scope = Scope::new(); - - scope.structure("Foo") - .derive("Debug").derive("Clone") - .field("one", "usize") - .field("two", "String"); - - let expect = r#" -#[derive(Debug, Clone)] -struct Foo { - one: usize, - two: String, -}"#; - - assert_eq!(scope.to_string(), &expect[1..]); -} - -#[test] -fn struct_with_generics_1() { - let mut scope = Scope::new(); - - scope.structure("Foo") - .generic("T") - .generic("U") - .field("one", "T") - .field("two", "U"); - - let expect = r#" -struct Foo { - one: T, - two: U, -}"#; - - assert_eq!(scope.to_string(), &expect[1..]); -} - -#[test] -fn struct_with_generics_2() { - let mut scope = Scope::new(); - - scope.structure("Foo") - .generic("T, U") - .field("one", "T") - .field("two", "U"); - - let expect = r#" -struct Foo { - one: T, - two: U, -}"#; - - assert_eq!(scope.to_string(), &expect[1..]); -} - -#[test] -fn struct_with_generics_3() { - let mut scope = Scope::new(); - - scope.structure("Foo") - .generic("T: Win, U") - .field("one", "T") - .field("two", "U"); - - let expect = r#" -struct Foo { - one: T, - two: U, -}"#; - - assert_eq!(scope.to_string(), &expect[1..]); -} - -#[test] -fn struct_where_clause_1() { - let mut scope = Scope::new(); - - scope.structure("Foo") - .generic("T") - .bound("T", "Foo") - .field("one", "T"); - - let expect = r#" -struct Foo -where T: Foo, -{ - one: T, -}"#; - - assert_eq!(scope.to_string(), &expect[1..]); -} - -#[test] -fn struct_where_clause_2() { - let mut scope = Scope::new(); - - scope.structure("Foo") - .generic("T, U") - .bound("T", "Foo") - .bound("U", "Baz") - .field("one", "T") - .field("two", "U"); - - let expect = r#" -struct Foo -where T: Foo, - U: Baz, -{ - one: T, - two: U, -}"#; - - assert_eq!(scope.to_string(), &expect[1..]); -} - -#[test] -fn struct_doc() { - let mut scope = Scope::new(); - - scope.structure("Foo") - .doc("Hello, this is a doc string\n\ - that continues on another line.") - .field("one", "T"); - - let expect = r#" -/// Hello, this is a doc string -/// that continues on another line. -struct Foo { - one: T, -}"#; - - assert_eq!(scope.to_string(), &expect[1..]); -} - -#[test] -fn struct_in_mod() { - let mut scope = Scope::new(); - - { - let module = scope.module("foo"); - module.structure("Foo") - .doc("Hello some docs") - .derive("Debug") - .generic("T, U") - .bound("T", "SomeBound") - .bound("U", "SomeOtherBound") - .field("one", "T") - .field("two", "U") - ; - } - - let expect = r#" -mod foo { - /// Hello some docs - #[derive(Debug)] - struct Foo - where T: SomeBound, - U: SomeOtherBound, - { - one: T, - two: U, - } -}"#; - - assert_eq!(scope.to_string(), &expect[1..]); -} - -#[test] -fn struct_mod_import() { - let mut scope = Scope::new(); - scope.module("foo") - .import("bar", "Bar") - .structure("Foo") - .field("bar", "Bar") - ; - - let expect = r#" -mod foo { - use bar::Bar; - - struct Foo { - bar: Bar, - } -}"#; - - assert_eq!(scope.to_string(), &expect[1..]); -} diff --git a/proxy/Cargo.toml b/proxy/Cargo.toml index e21cd5bff..f4dd8be84 100644 --- a/proxy/Cargo.toml +++ b/proxy/Cargo.toml @@ -10,6 +10,7 @@ chrono = "0.4" domain = "0.2.2" env_logger = "0.4" futures = "0.1" +h2 = "0.1" http = "0.1" httparse = "1.2" hyper = { version = "0.11.15", features = ["compat"] } @@ -21,33 +22,34 @@ url = "1.5" tokio-core = "0.1" tokio-io = "0.1" -prost = "0.2" -prost-derive = "0.2" -prost-types = "0.2" +prost = "0.3.0" +prost-derive = "0.3.0" +prost-types = "0.3.0" abstract-ns = "0.4" ns-dns-tokio = "0.4" #futures-watch = { git = "https://github.com/carllerche/better-future" } -h2 = { git = "https://github.com/carllerche/h2" } + tokio-connect = { git = "https://github.com/carllerche/tokio-connect" } tower = { git = "https://github.com/tower-rs/tower" } tower-balance = { git = "https://github.com/tower-rs/tower" } tower-buffer = { git = "https://github.com/tower-rs/tower" } tower-discover = { git = "https://github.com/tower-rs/tower" } +tower-grpc = { git = "https://github.com/tower-rs/tower-grpc" } +tower-h2 = { git = "https://github.com/tower-rs/tower-h2" } tower-reconnect = { git = "https://github.com/tower-rs/tower" } tower-util = { git = "https://github.com/tower-rs/tower" } futures-mpsc-lossy = { path = "../futures-mpsc-lossy" } tower-router = { path = "../tower-router" } -tower-grpc = { path = "../tower-grpc" } -tower-h2 = { path = "../tower-h2" } + [target.'cfg(target_os = "linux")'.dependencies] libc = "0.2" [build-dependencies] -tower-grpc-build = { path = "../tower-grpc-build" } +tower-grpc-build = { git = "https://github.com/tower-rs/tower-grpc" } [dev-dependencies] # Quickcheck 0.4.1, on crates.io, is missng useful Arbitrary implementations that exist on diff --git a/proxy/src/bind.rs b/proxy/src/bind.rs index e2a0ec74a..ab5dd5f39 100644 --- a/proxy/src/bind.rs +++ b/proxy/src/bind.rs @@ -1,4 +1,3 @@ -use std::io; use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::Arc; @@ -7,13 +6,14 @@ use std::time::Duration; use http; use tokio_core::reactor::Handle; +use tower; use tower_h2; -use tower_reconnect::{self, Reconnect}; +use tower_reconnect::Reconnect; use control; use ctx; -use telemetry; -use transparency; +use telemetry::{self, sensor}; +use transparency::{self, HttpBody}; use transport; use ::timeout::Timeout; @@ -48,15 +48,15 @@ pub enum Protocol { Http2 } -type Service = Reconnect< - telemetry::sensor::NewHttp< - transparency::Client< - telemetry::sensor::Connect>, - B, - >, - B, - transparency::HttpBody, - >, +pub type Service = Reconnect>; + +pub type NewHttp = sensor::NewHttp, B, HttpBody>; + +pub type HttpResponse = http::Response>; + +pub type Client = transparency::Client< + sensor::Connect>, + B, >; impl Bind<(), B> { @@ -189,11 +189,8 @@ where B: tower_h2::Body + 'static, { type Request = http::Request; - type Response = http::Response>; - type Error = tower_reconnect::Error< - tower_h2::client::Error, - tower_h2::client::ConnectError>, - >; + type Response = HttpResponse; + type Error = as tower::Service>::Error; type Service = Service; type BindError = (); diff --git a/proxy/src/control/codec.rs b/proxy/src/control/codec.rs deleted file mode 100644 index 4acfbefe0..000000000 --- a/proxy/src/control/codec.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::fmt; -use std::marker::PhantomData; - -use bytes::{Buf, BufMut}; -use prost::{DecodeError, Message}; -use tower_grpc::client::codec::{Codec, DecodeBuf, EncodeBuf}; - -/// A protobuf codec. -pub struct Protobuf(PhantomData<(T, U)>); - -impl Protobuf { - pub fn new() -> Self { - Protobuf(PhantomData) - } -} - -impl Clone for Protobuf { - fn clone(&self) -> Self { - Protobuf(PhantomData) - } -} - -impl fmt::Debug for Protobuf { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("Protobuf") - } -} - -impl Codec for Protobuf { - const CONTENT_TYPE: &'static str = "application/grpc+proto"; - - type Encode = T; - type Decode = U; - // never errors - type EncodeError = Void; - type DecodeError = DecodeError; - - fn encode(&mut self, msg: Self::Encode, buf: &mut EncodeBuf) -> Result<(), Self::EncodeError> { - let len = msg.encoded_len(); - if buf.remaining_mut() < len { - buf.reserve(len); - } - // prost says the only error from `Message::encode` is if there is not - // enough space in the buffer. - msg.encode(buf).expect("buf space was reserved"); - Ok(()) - } - - fn decode(&mut self, buf: &mut DecodeBuf) -> Result { - trace!("decode; bytes={}", buf.remaining()); - - match Message::decode(buf) { - Ok(msg) => Ok(msg), - Err(err) => { - debug!("decode error: {:?}", err); - Err(err) - } - } - } -} - -/// Can never be instantiated. -pub enum Void {} diff --git a/proxy/src/control/discovery.rs b/proxy/src/control/discovery.rs index e3adda5ae..185b9e9c2 100644 --- a/proxy/src/control/discovery.rs +++ b/proxy/src/control/discovery.rs @@ -1,26 +1,21 @@ use std::collections::{HashSet, VecDeque}; use std::collections::hash_map::{Entry, HashMap}; use std::net::SocketAddr; +use std::fmt; use futures::{Async, Future, Poll, Stream}; use futures::sync::mpsc; use tower::Service; +use tower_h2::{HttpService, BoxBody, RecvBody}; use tower_discover::{Change, Discover}; -use tower_grpc; +use tower_grpc as grpc; use fully_qualified_authority::FullyQualifiedAuthority; -use super::codec::Protobuf; use super::pb::common::{Destination, TcpAddress}; use super::pb::proxy::destination::Update as PbUpdate; -use super::pb::proxy::destination::client::Destination as DestinationSvc; -use super::pb::proxy::destination::client::destination_methods::Get as GetRpc; use super::pb::proxy::destination::update::Update as PbUpdate2; - -pub type ClientBody = ::tower_grpc::client::codec::EncodingBody< - Protobuf, - ::tower_grpc::client::codec::Unary, ->; +use super::pb::proxy::destination::client::{Destination as DestinationSvc}; /// A handle to start watching a destination for address changes. #[derive(Clone, Debug)] @@ -41,18 +36,14 @@ pub struct Background { rx: mpsc::UnboundedReceiver<(FullyQualifiedAuthority, mpsc::UnboundedSender)>, } -type DiscoveryWatch = DestinationSet< - tower_grpc::client::Streaming< - tower_grpc::client::ResponseFuture, F>, - tower_grpc::client::codec::DecodingBody>, - >, ->; - /// A future returned from `Background::work()`, doing the work of talking to /// the controller destination API. -#[derive(Debug)] -pub struct DiscoveryWork { - destinations: HashMap>, +// TODO: debug impl +pub struct DiscoveryWork> { + destinations: HashMap< + FullyQualifiedAuthority, + DestinationSet + >, /// A queue of authorities that need to be reconnected. reconnects: VecDeque, /// The Destination.Get RPC client service. @@ -62,14 +53,44 @@ pub struct DiscoveryWork { rx: mpsc::UnboundedReceiver<(FullyQualifiedAuthority, mpsc::UnboundedSender)>, } -#[derive(Debug)] -struct DestinationSet { +struct DestinationSet> { addrs: HashSet, needs_reconnect: bool, - rx: R, + rx: UpdateRx, txs: Vec>, } +/// Receiver for destination set updates. +/// +/// The destination RPC returns a `ResponseFuture` whose item is a +/// `Response`, so this type holds the state of that RPC call --- +/// either we're waiting for the future, or we have a stream --- and allows +/// us to implement `Stream` regardless of whether the RPC has returned yet +/// or not. +/// +/// Polling an `UpdateRx` polls the wrapped future while we are +/// `Waiting`, and the `Stream` if we are `Streaming`. If the future is `Ready`, +/// then we switch states to `Streaming`. +enum UpdateRx> { + Waiting(UpdateRsp), + Streaming(grpc::Streaming), +} + +type UpdateRsp = + grpc::client::server_streaming::ResponseFuture; + +/// Wraps the error types returned by `UpdateRx` polls. +/// +/// An `UpdateRx` error is either the error type of the `Future` in the +/// `UpdateRx::Waiting` state, or the `Stream` in the `UpdateRx::Streaming` +/// state. +// TODO: impl Error? +#[derive(Debug)] +enum RxError { + Future(grpc::Error), + Stream(grpc::Error), +} + #[derive(Debug)] enum Update { Insert(SocketAddr), @@ -168,7 +189,10 @@ where impl Background { /// Bind this handle to start talking to the controller API. - pub fn work(self) -> DiscoveryWork { + pub fn work(self) -> DiscoveryWork + where T: HttpService, + T::Error: fmt::Debug, + { DiscoveryWork { destinations: HashMap::new(), reconnects: VecDeque::new(), @@ -180,20 +204,12 @@ impl Background { // ==== impl DiscoveryWork ===== -impl DiscoveryWork +impl DiscoveryWork where - F: Future>, - F::Error: ::std::fmt::Debug, + T: HttpService, + T::Error: fmt::Debug, { - pub fn poll_rpc(&mut self, client: &mut S) - where - S: Service< - Request = ::http::Request, - Response = F::Item, - Error = F::Error, - Future = F, - >, - { + pub fn poll_rpc(&mut self, client: &mut T) { // This loop is make sure any streams that were found disconnected // in `poll_destinations` while the `rpc` service is ready should // be reconnected now, otherwise the task would just sleep... @@ -208,15 +224,7 @@ where } } - fn poll_new_watches(&mut self, mut client: &mut S) - where - S: Service< - Request = ::http::Request, - Response = F::Item, - Error = F::Error, - Future = F, - >, - { + fn poll_new_watches(&mut self, client: &mut T) { loop { // if rpc service isn't ready, not much we can do... match client.poll_ready() { @@ -239,8 +247,6 @@ where continue; } - let grpc = tower_grpc::Client::new(Protobuf::new(), &mut client); - let mut rpc = GetRpc::new(grpc); // check for any new watches match self.rx.poll() { Ok(Async::Ready(Some((auth, tx)))) => { @@ -260,7 +266,11 @@ where scheme: "k8s".into(), path: vac.key().without_trailing_dot().into(), }; - let stream = DestinationSvc::new(&mut rpc).get(req); + // TODO: Can grpc::Request::new be removed? + let mut svc = DestinationSvc::new(client.lift_ref()); + let response = svc.get(grpc::Request::new(req)); + let stream = UpdateRx::Waiting(response); + vac.insert(DestinationSet { addrs: HashSet::new(), needs_reconnect: false, @@ -281,18 +291,8 @@ where } /// Tries to reconnect next watch stream. Returns true if reconnection started. - fn poll_reconnect(&mut self, client: &mut S) -> bool - where - S: Service< - Request = ::http::Request, - Response = F::Item, - Error = F::Error, - Future = F, - >, - { + fn poll_reconnect(&mut self, client: &mut T) -> bool { debug_assert!(self.rpc_ready); - let grpc = tower_grpc::Client::new(Protobuf::new(), client); - let mut rpc = GetRpc::new(grpc); while let Some(auth) = self.reconnects.pop_front() { if let Some(set) = self.destinations.get_mut(&auth) { @@ -301,7 +301,9 @@ where scheme: "k8s".into(), path: auth.without_trailing_dot().into(), }; - set.rx = DestinationSvc::new(&mut rpc).get(req); + let mut svc = DestinationSvc::new(client.lift_ref()); + let response = svc.get(grpc::Request::new(req)); + set.rx = UpdateRx::Waiting(response); set.needs_reconnect = false; return true; } else { @@ -317,6 +319,7 @@ where continue; } let needs_reconnect = 'set: loop { + match set.rx.poll() { Ok(Async::Ready(Some(update))) => match update.update { Some(PbUpdate2::Add(a_set)) => for addr in a_set.addrs { @@ -356,6 +359,7 @@ where break 'set true; } } + }; if needs_reconnect { set.needs_reconnect = true; @@ -383,6 +387,33 @@ where } } +// ===== impl UpdateRx ===== + +impl Stream for UpdateRx +where T: HttpService, + T::Error: fmt::Debug, +{ + type Item = PbUpdate; + type Error = RxError; + + fn poll(&mut self) -> Poll, Self::Error> { + // this is not ideal. + let stream = match *self { + UpdateRx::Waiting(ref mut future) => match future.poll() { + Ok(Async::Ready(response)) => response.into_inner(), + Ok(Async::NotReady) => return Ok(Async::NotReady), + Err(e) => return Err(RxError::Future(e)), + }, + UpdateRx::Streaming(ref mut stream) => + return stream.poll().map_err(RxError::Stream), + }; + *self = UpdateRx::Streaming(stream); + self.poll() + } +} + +// ===== impl RxError ===== + fn pb_to_sock_addr(pb: TcpAddress) -> Option { use super::pb::common::ip_address::Ip; use std::net::{Ipv4Addr, Ipv6Addr}; @@ -434,4 +465,4 @@ fn pb_to_sock_addr(pb: TcpAddress) -> Option { }, None => None, } -} +} \ No newline at end of file diff --git a/proxy/src/control/mod.rs b/proxy/src/control/mod.rs index 3ae711e44..9544857de 100644 --- a/proxy/src/control/mod.rs +++ b/proxy/src/control/mod.rs @@ -1,4 +1,3 @@ -use std::marker::PhantomData; use std::time::{Duration, Instant}; use bytes::Bytes; @@ -6,7 +5,7 @@ use futures::{future, Async, Future, Poll, Stream}; use h2; use http; use tokio_core::reactor::{ - Handle, + Handle, // TODO: would rather just have Backoff in a separate file so this // renaming import is not necessary. Timeout as ReactorTimeout @@ -21,7 +20,6 @@ use fully_qualified_authority::FullyQualifiedAuthority; use transport::LookupAddressAndConnect; use timeout::Timeout; -mod codec; pub mod discovery; mod observe; pub mod pb; @@ -91,7 +89,7 @@ impl Background { executor, ); - let h2_client = tower_h2::client::Client::new( + let h2_client = tower_h2::client::Connect::new( connect, h2::client::Builder::default(), ::logging::context_executor(ctx, executor.clone()), @@ -100,6 +98,7 @@ impl Background { let reconnect = Reconnect::new(h2_client); let backoff = Backoff::new(reconnect, Duration::from_secs(5), executor); + // TODO: Use AddOrigin in tower-http AddOrigin::new(scheme, authority, backoff) }; @@ -108,11 +107,12 @@ impl Background { let fut = future::poll_fn(move || { trace!("poll rpc services"); - disco.poll_rpc(&mut EnumService(&mut client, PhantomData)); - telemetry.poll_rpc(&mut EnumService(&mut client, PhantomData)); + disco.poll_rpc(&mut client); + telemetry.poll_rpc(&mut client); Ok(Async::NotReady) }); + Box::new(fut) } } @@ -215,73 +215,3 @@ where } } -// ===== impl EnumService ===== - -struct EnumService(S, PhantomData); - -impl Service for EnumService -where - S: Service>, - B: Into, -{ - type Request = http::Request; - type Response = S::Response; - type Error = S::Error; - type Future = S::Future; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.0.poll_ready() - } - - fn call(&mut self, req: Self::Request) -> Self::Future { - let (head, body) = req.into_parts(); - self.0.call(http::Request::from_parts(head, body.into())) - } -} - - - -enum GrpcEncodingBody { - TelemetryReport(self::telemetry::ClientBody), - DestinationGet(self::discovery::ClientBody), -} - -impl tower_h2::Body for GrpcEncodingBody { - type Data = Bytes; - - #[inline] - fn is_end_stream(&self) -> bool { - match *self { - GrpcEncodingBody::TelemetryReport(ref b) => b.is_end_stream(), - GrpcEncodingBody::DestinationGet(ref b) => b.is_end_stream(), - } - } - - #[inline] - fn poll_data(&mut self) -> Poll, h2::Error> { - match *self { - GrpcEncodingBody::TelemetryReport(ref mut b) => b.poll_data(), - GrpcEncodingBody::DestinationGet(ref mut b) => b.poll_data(), - } - } - - #[inline] - fn poll_trailers(&mut self) -> Poll, h2::Error> { - match *self { - GrpcEncodingBody::TelemetryReport(ref mut b) => b.poll_trailers(), - GrpcEncodingBody::DestinationGet(ref mut b) => b.poll_trailers(), - } - } -} - -impl From for GrpcEncodingBody { - fn from(body: self::telemetry::ClientBody) -> Self { - GrpcEncodingBody::TelemetryReport(body) - } -} - -impl From for GrpcEncodingBody { - fn from(body: self::discovery::ClientBody) -> Self { - GrpcEncodingBody::DestinationGet(body) - } -} diff --git a/proxy/src/control/observe.rs b/proxy/src/control/observe.rs index 23a545291..f0e4c3e7d 100644 --- a/proxy/src/control/observe.rs +++ b/proxy/src/control/observe.rs @@ -3,11 +3,10 @@ use std::sync::{Arc, Mutex}; use futures::{future, Poll, Stream}; use futures_mpsc_lossy; use ordermap::OrderMap; -use tower_grpc::{self, Request, Response}; -use tower_grpc::codegen::server::grpc::ServerStreamingService; +use tower_grpc::{self as grpc, Response}; use control::pb::common::TapEvent; -use control::pb::proxy::tap::ObserveRequest; +use control::pb::proxy::tap::{server, ObserveRequest}; use convert::*; use ctx; use telemetry::Event; @@ -42,29 +41,23 @@ impl Observe { } } -impl ServerStreamingService for Observe { - type Request = ObserveRequest; - type Response = TapEvent; - type ResponseStream = TapEvents; - type Future = future::FutureResult, tower_grpc::Error>; +impl server::Tap for Observe { + type ObserveStream = TapEvents; + type ObserveFuture = future::FutureResult, grpc::Error>; - fn poll_ready(&mut self) -> Poll<(), tower_grpc::Error> { - Ok(().into()) - } - - fn call(&mut self, req: Request) -> Self::Future { + fn observe(&mut self, req: grpc::Request) -> Self::ObserveFuture { if self.next_id == ::std::usize::MAX { - return future::err(tower_grpc::Error::Grpc(tower_grpc::Status::INTERNAL)); + return future::err(grpc::Error::Grpc(grpc::Status::INTERNAL)); } - let (_, req) = req.into_http().into_parts(); + let req = req.into_inner(); let (tap, rx) = match req.match_ .and_then(|m| Tap::new(&m, self.tap_capacity).ok()) { Some(m) => m, None => { - return future::err(tower_grpc::Error::Grpc( - tower_grpc::Status::INVALID_ARGUMENT, + return future::err(grpc::Error::Grpc( + grpc::Status::INVALID_ARGUMENT, )); } }; @@ -77,7 +70,7 @@ impl ServerStreamingService for Observe { tap_id } Err(_) => { - return future::err(tower_grpc::Error::Grpc(tower_grpc::Status::INTERNAL)); + return future::err(grpc::Error::Grpc(grpc::Status::INTERNAL)); } }; @@ -88,13 +81,14 @@ impl ServerStreamingService for Observe { remaining: req.limit as usize, taps: self.taps.clone(), }; + future::ok(Response::new(events)) } } impl Stream for TapEvents { type Item = TapEvent; - type Error = tower_grpc::Error; + type Error = grpc::Error; fn poll(&mut self) -> Poll, Self::Error> { loop { diff --git a/proxy/src/control/pb.rs b/proxy/src/control/pb.rs index e13b703fd..bdffca8a0 100644 --- a/proxy/src/control/pb.rs +++ b/proxy/src/control/pb.rs @@ -176,7 +176,7 @@ impl<'a> TryFrom<&'a Event> for common::TapEvent { stream: ctx.id as u64, }), method: Some((&ctx.method).into()), - scheme: ctx.uri.scheme_part().map(|s| s.as_str().into()), + scheme: ctx.uri.scheme_part().map(common::Scheme::from), authority: ctx.uri .authority_part() .map(|a| a.as_str()) @@ -312,6 +312,12 @@ impl<'a> From<&'a http::Method> for common::HttpMethod { } } +impl<'a> From<&'a http::uri::Scheme> for common::Scheme { + fn from(scheme: &'a http::uri::Scheme) -> Self { + scheme.as_ref().into() + } +} + impl<'a> From<&'a str> for common::scheme::Type { fn from(s: &'a str) -> Self { use self::common::scheme::*; diff --git a/proxy/src/control/telemetry.rs b/proxy/src/control/telemetry.rs index b547e58c2..0d3a23d0a 100644 --- a/proxy/src/control/telemetry.rs +++ b/proxy/src/control/telemetry.rs @@ -1,42 +1,32 @@ +use std::fmt; use std::time::{Duration, Instant}; use futures::{Async, Future, Stream}; -use tower::Service; -use tower_grpc; use tokio_core::reactor::Handle; +use tower_h2::{HttpService, BoxBody}; +use tower_grpc as grpc; -use super::codec::Protobuf; use super::pb::proxy::telemetry::{ReportRequest, ReportResponse}; use super::pb::proxy::telemetry::client::Telemetry as TelemetrySvc; -use super::pb::proxy::telemetry::client::telemetry_methods::Report as ReportRpc; use ::timeout::{Timeout, TimeoutFuture}; -pub type ClientBody = tower_grpc::client::codec::EncodingBody< - Protobuf, - tower_grpc::client::codec::Unary, ->; - -type TelemetryStream = tower_grpc::client::BodyFuture< - tower_grpc::client::Unary< - tower_grpc::client::ResponseFuture, TimeoutFuture>, - Protobuf, - >, ->; +type TelemetryStream = grpc::client::unary::ResponseFuture< + ReportResponse, TimeoutFuture, B>; #[derive(Debug)] -pub struct Telemetry { +pub struct Telemetry { reports: T, - in_flight: Option<(Instant, TelemetryStream)>, + in_flight: Option<(Instant, TelemetryStream)>, report_timeout: Duration, handle: Handle, } -impl Telemetry +impl Telemetry where + S: HttpService, + S::Error: fmt::Debug, T: Stream, T::Error: ::std::fmt::Debug, - F: Future>, - F::Error: ::std::fmt::Debug, { pub fn new(reports: T, report_timeout: Duration, handle: &Handle) -> Self { Telemetry { @@ -47,18 +37,10 @@ where } } - pub fn poll_rpc(&mut self, client: &mut S) - where - S: Service< - Request = ::http::Request, - Response = F::Item, - Error = F::Error, - Future = F, - >, + pub fn poll_rpc(&mut self, client: &mut S) { - let client = Timeout::new(client, self.report_timeout, &self.handle); - let grpc = tower_grpc::Client::new(Protobuf::new(), client); - let mut rpc = ReportRpc::new(grpc); + let client = Timeout::new(client.lift_ref(), self.report_timeout, &self.handle); + let mut svc = TelemetrySvc::new(client); //let _ctxt = ::logging::context("Telemetry.Report".into()); @@ -78,8 +60,7 @@ where } } - - let controller_ready = self.in_flight.is_none() && match rpc.poll_ready() { + let controller_ready = self.in_flight.is_none() && match svc.poll_ready() { Ok(Async::Ready(_)) => true, Ok(Async::NotReady) => { trace!("controller unavailable"); @@ -119,7 +100,7 @@ where report.server_transports.len(), report.client_transports.len(), ); - let rep = TelemetrySvc::new(&mut rpc).report(report); + let rep = svc.report(grpc::Request::new(report)); self.in_flight = Some((Instant::now(), rep)); } } diff --git a/proxy/src/inbound.rs b/proxy/src/inbound.rs index 1aa577a83..587b64728 100644 --- a/proxy/src/inbound.rs +++ b/proxy/src/inbound.rs @@ -1,18 +1,14 @@ -use std::io; use std::net::{SocketAddr}; use std::sync::Arc; use http; +use tower; use tower_buffer::{self, Buffer}; use tower_h2; -use tower_reconnect::{self, Reconnect}; use tower_router::Recognize; use bind; use ctx; -use telemetry; -use transparency; -use transport; type Bind = bind::Bind, B>; @@ -21,11 +17,6 @@ pub struct Inbound { bind: Bind, } -type Client = transparency::Client< - telemetry::sensor::Connect>, - B, ->; - // ===== impl Inbound ===== impl Inbound { @@ -42,16 +33,13 @@ where B: tower_h2::Body + 'static, { type Request = http::Request; - type Response = http::Response>; + type Response = bind::HttpResponse; type Error = tower_buffer::Error< - tower_reconnect::Error< - tower_h2::client::Error, - tower_h2::client::ConnectError>, - >, + as tower::Service>::Error >; type Key = (SocketAddr, bind::Protocol); type RouteError = (); - type Service = Buffer, B, transparency::HttpBody>>>; + type Service = Buffer>; fn recognize(&self, req: &Self::Request) -> Option { let key = req.extensions() diff --git a/proxy/src/lib.rs b/proxy/src/lib.rs index da81cbc64..031bdaac8 100644 --- a/proxy/src/lib.rs +++ b/proxy/src/lib.rs @@ -76,7 +76,6 @@ mod tower_fn; // TODO: move to tower-fn use bind::Bind; use connection::BoundPort; -use control::pb::proxy::tap; use inbound::Inbound; use map_err::MapErr; use transparency::{HttpBody, Server}; @@ -245,12 +244,13 @@ where thread::Builder::new() .name("controller-client".into()) .spawn(move || { + use control::pb::proxy::tap::server::TapServer; + let mut core = Core::new().expect("initialize controller core"); let executor = core.handle(); let (taps, observe) = control::Observe::new(100); - - let new_service = tap::server::Tap::new_service().observe(observe); + let new_service = TapServer::new(observe); let server = serve_control( control_listener, diff --git a/proxy/src/outbound.rs b/proxy/src/outbound.rs index 1352ad09c..2fc08f896 100644 --- a/proxy/src/outbound.rs +++ b/proxy/src/outbound.rs @@ -1,32 +1,21 @@ -use std::io; use std::sync::Arc; use http; -use tower_balance::{self, Balance}; -use tower_buffer::{self, Buffer}; + +use tower; +use tower_balance::{self, choose, Balance}; +use tower_buffer::Buffer; use tower_h2; -use tower_reconnect; use tower_router::Recognize; -use bind::{Bind, BindProtocol, Protocol}; -use control; +use bind::{self, Bind, Protocol}; +use control::{self, discovery}; use ctx; use fully_qualified_authority::FullyQualifiedAuthority; -use telemetry; -use transparency; -use transport; -type Discovery = control::discovery::Watch, B>>; +type BindProtocol = bind::BindProtocol, B>; -type Error = tower_buffer::Error< - tower_balance::Error< - tower_reconnect::Error< - tower_h2::client::Error, - tower_h2::client::ConnectError>, - >, - (), - >, ->; +type Discovery = discovery::Watch>; pub struct Outbound { bind: Bind, B>, @@ -55,11 +44,14 @@ where B: tower_h2::Body + 'static, { type Request = http::Request; - type Response = http::Response>; - type Error = Error; + type Response = bind::HttpResponse; + type Error = ::Error; type Key = (FullyQualifiedAuthority, Protocol); type RouteError = (); - type Service = Buffer>>; + type Service = Buffer, + choose::RoundRobin, // TODO: better load balancer. + >>; fn recognize(&self, req: &Self::Request) -> Option { req.uri().authority_part().map(|authority| { @@ -97,7 +89,8 @@ where self.bind.clone().with_protocol(protocol), ); - let balance = Balance::new(resolve); + // TODO: move to p2c lb. + let balance = tower_balance::round_robin(resolve); // Wrap with buffering. This currently is an unbounded buffer, // which is not ideal. diff --git a/proxy/src/telemetry/sensor/http.rs b/proxy/src/telemetry/sensor/http.rs index 138d46bcd..5c3d3d269 100644 --- a/proxy/src/telemetry/sensor/http.rs +++ b/proxy/src/telemetry/sensor/http.rs @@ -77,7 +77,11 @@ impl NewHttp where A: Body + 'static, B: Body + 'static, - N: NewService, Response = http::Response, Error = client::Error> + N: NewService< + Request = http::Request, + Response = http::Response, + Error = client::Error, + > + 'static, { pub(super) fn new( @@ -100,7 +104,11 @@ impl NewService for NewHttp where A: Body + 'static, B: Body + 'static, - N: NewService, Response = http::Response, Error = client::Error> + N: NewService< + Request = http::Request, + Response = http::Response, + Error = client::Error, + > + 'static, { type Request = N::Request; @@ -152,7 +160,11 @@ impl Service for Http where A: Body + 'static, B: Body + 'static, - S: Service, Response = http::Response, Error = client::Error> + S: Service< + Request = http::Request, + Response = http::Response, + Error = client::Error, + > + 'static, { type Request = S::Request; @@ -197,7 +209,7 @@ where impl Future for Respond where - F: Future, Error = client::Error>, + F: Future, Error=client::Error>, B: Body + 'static, { type Item = http::Response>; diff --git a/proxy/src/telemetry/tap/match_.rs b/proxy/src/telemetry/tap/match_.rs index 0fb8e3b4b..b40286626 100644 --- a/proxy/src/telemetry/tap/match_.rs +++ b/proxy/src/telemetry/tap/match_.rs @@ -260,7 +260,10 @@ impl<'a> TryFrom<&'a observe_request::match_::tcp::Netmask> for NetMatch { impl HttpMatch { fn matches(&self, req: &Arc) -> bool { match *self { - HttpMatch::Scheme(ref m) => req.uri.scheme_part().map(|s| &**m == s).unwrap_or(false), + HttpMatch::Scheme(ref m) => req.uri + .scheme_part() + .map(|s| m == s.as_ref()) + .unwrap_or(false), HttpMatch::Method(ref m) => *m == req.method, diff --git a/proxy/src/timeout.rs b/proxy/src/timeout.rs index 254b2e07f..500d0193d 100644 --- a/proxy/src/timeout.rs +++ b/proxy/src/timeout.rs @@ -3,10 +3,12 @@ use futures::{Async, Future, Poll}; use std::error::Error; use std::fmt; +use std::io; use std::time::Duration; use tokio_connect::Connect; use tokio_core::reactor::{Timeout as ReactorTimeout, Handle}; +use tokio_io; use tower::Service; @@ -37,10 +39,9 @@ pub struct TimeoutFuture { //===== impl Timeout ===== impl Timeout { - /// Construct a new `Timeout` wrapping `inner`. pub fn new(inner: U, duration: Duration, handle: &Handle) -> Self { - Timeout { + Timeout { inner, duration, handle: handle.clone(), @@ -49,13 +50,13 @@ impl Timeout { } -impl Service for Timeout +impl Service for Timeout where S: Service, // E: Error, { type Request = S::Request; - type Response = T; + type Response = T; type Error = TimeoutError; type Future = TimeoutFuture; @@ -101,11 +102,51 @@ where } } +impl io::Read for Timeout +where + C: io::Read, +{ + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.inner.read(buf) + } +} + +impl io::Write for Timeout +where + C: io::Write, +{ + fn write(&mut self, buf: &[u8]) -> io::Result { + self.inner.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } +} + +impl tokio_io::AsyncRead for Timeout +where + C: tokio_io::AsyncRead, +{ + unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { + self.inner.prepare_uninitialized_buffer(buf) + } +} + +impl tokio_io::AsyncWrite for Timeout +where + C: tokio_io::AsyncWrite, +{ + fn shutdown(&mut self) -> Poll<(), io::Error> { + self.inner.shutdown() + } +} //===== impl TimeoutError ===== impl From for TimeoutError { - #[inline] fn from(error: E) -> Self { + #[inline] + fn from(error: E) -> Self { TimeoutError::Error(error) } } @@ -116,7 +157,7 @@ where { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - TimeoutError::Timeout(ref duration) => + TimeoutError::Timeout(ref duration) => // TODO: format the duration nicer. write!(f, "operation timed out after {:?}", duration), TimeoutError::Error(ref err) => @@ -125,10 +166,10 @@ where } } -impl Error for TimeoutError -where +impl Error for TimeoutError +where E: Error -{ +{ fn cause(&self) -> Option<&Error> { match *self { TimeoutError::Error(ref err) => Some(err), @@ -160,7 +201,7 @@ where Err(TimeoutError::Timeout(self.duration)) } else { Ok(Async::NotReady) - } + } } } @@ -176,4 +217,4 @@ where .field("duration", &self.duration) .finish() } -} \ No newline at end of file +} diff --git a/proxy/src/transparency/client.rs b/proxy/src/transparency/client.rs index 1bb73120b..f01d135e3 100644 --- a/proxy/src/transparency/client.rs +++ b/proxy/src/transparency/client.rs @@ -23,7 +23,7 @@ where B: tower_h2::Body, { Http1(hyper::Client, BodyStream>), - Http2(tower_h2::client::Client), + Http2(tower_h2::client::Connect), } /// A `Future` returned from `Client::new_service()`. @@ -48,6 +48,7 @@ where pub struct ClientService where B: tower_h2::Body, + C: Connect, { inner: ClientServiceInner, } @@ -55,9 +56,14 @@ where enum ClientServiceInner where B: tower_h2::Body, + C: Connect { Http1(hyper::Client, BodyStream>), - Http2(tower_h2::client::Service), + Http2(tower_h2::client::Connection< + ::Connected, + Handle, + B + >), } impl Client @@ -83,7 +89,7 @@ where // h2 currently doesn't handle PUSH_PROMISE that well, so we just // disable it for now. h2_builder.enable_push(false); - let h2 = tower_h2::client::Client::new(connect, h2_builder, executor); + let h2 = tower_h2::client::Connect::new(connect, h2_builder, executor); Client { inner: ClientInner::Http2(h2), diff --git a/proxy/src/transport/connect.rs b/proxy/src/transport/connect.rs index f51068cd6..c77712db5 100644 --- a/proxy/src/transport/connect.rs +++ b/proxy/src/transport/connect.rs @@ -24,7 +24,6 @@ pub struct LookupAddressAndConnect { } pub type TimeoutConnect = timeout::Timeout; -pub type TimeoutError = timeout::TimeoutError; // ===== impl Connect ===== diff --git a/proxy/src/transport/mod.rs b/proxy/src/transport/mod.rs index 93137d21b..076a3bfce 100644 --- a/proxy/src/transport/mod.rs +++ b/proxy/src/transport/mod.rs @@ -1,5 +1,5 @@ mod connect; mod so_original_dst; -pub use self::connect::{Connect, LookupAddressAndConnect, TimeoutConnect, TimeoutError}; +pub use self::connect::{Connect, LookupAddressAndConnect, TimeoutConnect}; pub use self::so_original_dst::{GetOriginalDst, SoOriginalDst}; diff --git a/proxy/tests/support/client.rs b/proxy/tests/support/client.rs index 4dde60b25..6d7698aed 100644 --- a/proxy/tests/support/client.rs +++ b/proxy/tests/support/client.rs @@ -124,7 +124,7 @@ fn run(addr: SocketAddr, version: Run) -> Sender { .map_err(|e| println!("client error: {:?}", e))) }, Run::Http2 => { - let h2 = tower_h2::Client::::new( + let h2 = tower_h2::client::Connect::::new( conn, Default::default(), reactor.clone(), diff --git a/tower-grpc-build/Cargo.toml b/tower-grpc-build/Cargo.toml deleted file mode 100644 index 209f7c095..000000000 --- a/tower-grpc-build/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "tower-grpc-build" -version = "0.2.0" -authors = ["Carl Lerche "] - -[dependencies] -codegen = { version = "0.2", path = "../codegen" } -prost-build = "0.2" diff --git a/tower-grpc-build/src/client.rs b/tower-grpc-build/src/client.rs deleted file mode 100644 index 01527a429..000000000 --- a/tower-grpc-build/src/client.rs +++ /dev/null @@ -1,270 +0,0 @@ -use prost_build; - -#[allow(unused)] -use std::ascii::AsciiExt; -use std::fmt::{self, Write}; - -/// Generates service code -pub struct ServiceGenerator; - -struct State { - mod_levels: usize, -} - -// ===== impl ServiceGenerator ===== - -impl ServiceGenerator { - pub fn generate(&self, service: &prost_build::Service, buf: &mut String) -> fmt::Result { - let mut state = State { - mod_levels: 0, - }; - state.generate(service, buf) - } -} - -// ===== impl State ===== - -impl State { - pub fn generate(&mut self, service: &prost_build::Service, buf: &mut String) -> fmt::Result { - // Generate code in a client module - write!(buf, "pub mod client {{\n")?; - self.mod_levels = 1; - - self.generate_svc(&service, buf)?; - - write!(buf, "\n pub mod {}_methods {{", service.name.to_ascii_lowercase())?; - self.mod_levels = 2; - - self.generate_rpcs(&service.methods, buf)?; - buf.push_str(" }\n"); // end `mod name_methods {` - - buf.push_str("}"); // end `mod client {` - - Ok(()) - } - - /// Generates a generic struct to represent the gRPC service. - fn generate_svc(&self, service: &prost_build::Service, buf: &mut String) -> fmt::Result { - // Generic names used to identify concrete service implementations - // contained by the service client struct. - let mut rpc_generics = vec![]; - let mut all_generics = vec![]; - let mut struct_fields = vec![]; - let mut new_args = vec![]; - let mut new_fields = vec![]; - let mut where_bounds = vec![]; - - for method in &service.methods { - let rpc_name = format!("{}Rpc", method.proto_name); - - let arg = self.input_name(method); - let returns = self.svc_returns(method); - - rpc_generics.push(rpc_name.clone()); - all_generics.push(rpc_name.clone()); - - struct_fields.push(format!("{}: {},", method.name, rpc_name)); - - where_bounds.push(format!("{}: ::tower::Service<\ - Request=::tower_grpc::Request<{}>,\ - Response=::tower_grpc::Response<{}>,\ - >,", rpc_name, arg, returns)); - - if method.server_streaming { - all_generics.push(returns.clone()); - where_bounds.push(format!("{}: ::futures::Stream>,", returns, self.output_name(method))); - } - - new_args.push(format!("{}: {}", method.name, rpc_name)); - new_fields.push(format!("{},", method.name)); - - } - - write!(buf, r##" - #[derive(Debug)] - pub struct {name}<{rpc_generics}> {{ - {struct_fields} - }} - - impl<{all_generics}> {name}<{rpc_generics}> - where - {where_bounds} - {{ - pub fn new({new_args}) -> Self {{ - {name} {{ - {new_fields} - }} - }} -"##, - name=service.name, - all_generics=all_generics.join(", "), - rpc_generics=rpc_generics.join(", "), - where_bounds=where_bounds.join("\n"), - struct_fields=struct_fields.join("\n "), - new_args=new_args.join(", "), - new_fields=new_fields.join("\n "), - )?; - - self.generate_svc_methods(&service, buf)?; - - buf.push_str(" }\n"); // close `impl {name} {` - - Ok(()) - } - - /// Generates the inherent methods on the generic service struct. - fn generate_svc_methods(&self, service: &prost_build::Service, buf: &mut String) -> fmt::Result { - for method in &service.methods { - let path = format!("/{}.{}/{}", service.package, service.proto_name, method.proto_name); - let svc_returns = self.svc_returns(method); - let rpc_name = format!("{}Rpc", method.proto_name); - - let (returns, map_fut) = if method.server_streaming { - let returns = format!( - "::tower_grpc::client::Streaming<{rpc_name}::Future, {returns}>", - rpc_name=rpc_name, - returns=svc_returns, - ); - (returns, "::tower_grpc::client::Streaming::map_future(fut)") - } else { - let returns = format!( - "::tower_grpc::client::BodyFuture<{rpc_name}::Future>", - rpc_name=rpc_name, - ); - (returns, "::tower_grpc::client::BodyFuture::new(fut)") - }; - - write!(buf, r##" - pub fn {method}(&mut self, req: {arg}) -> {returns} {{ - let req = ::tower_grpc::Request::new("{path}", req); - let fut = self.{method}.call(req); - {fut} - }} -"##, - method=method.name, - arg=self.input_name(method), - returns=returns, - path=path, - fut=map_fut, - )?; - } - - Ok(()) - } - - /// Generates the individual RPCs as `tower::Service`. - fn generate_rpcs(&self, methods: &[prost_build::Method], buf: &mut String) -> fmt::Result { - for method in methods { - let input = self.input_name(method); - let output = self.output_name(method); - let call_stream = if method.client_streaming { - unimplemented!("generate client streaming"); - } else { - "::tower_grpc::client::codec::Unary" - }; - - let where_bounds = format!(r##" - C: ::tower_grpc::client::Codec, - S: ::tower::Service< - Request=::tower_grpc::Request< - {call_stream}<{input}> - >, - Response=::tower_grpc::Response< - ::tower_grpc::client::codec::DecodingBody - >, - Error=::tower_grpc::Error - >,"##, - call_stream=call_stream, - input=input, - output=output, - ); - - let returns = self.rpc_returns(method); - let fut = if method.server_streaming { - "S::Future" - } else { - "::tower_grpc::client::Unary" - }; - let call = if method.server_streaming { - "fut" - } else { - "::tower_grpc::client::Unary::map_future(fut)" - }; - write!(buf, r##" - #[derive(Debug)] - pub struct {name} {{ - service: S, - }} - - impl {name} - where{where_bounds} - {{ - pub fn new(service: S) -> Self {{ - {name} {{ - service, - }} - }} - }} - - impl ::tower::Service for {name} - where{where_bounds} - {{ - type Request = ::tower_grpc::Request<{input}>; - type Response = ::tower_grpc::Response<{returns}>; - type Error = S::Error; - type Future = {fut}; - - fn poll_ready(&mut self) -> ::futures::Poll<(), Self::Error> {{ - ::tower::Service::poll_ready(&mut self.service) - }} - - fn call(&mut self, req: Self::Request) -> Self::Future {{ - let fut = ::tower::Service::call(&mut self.service, {req}); - {call} - }} - }} -"##, - name=method.proto_name, - where_bounds=where_bounds, - input=input, - returns=returns, - fut=fut, - req=if method.client_streaming { "req" } else { "req.into_unary()" }, - call=call, - )?; - } - - Ok(()) - } - - fn supers(&self) -> String { - (0..self.mod_levels) - .map(|_| "super::") - .collect::>() - .concat() - } - - fn input_name(&self, method: &prost_build::Method) -> String { - format!("{}{}", self.supers(), method.input_type) - } - - fn output_name(&self, method: &prost_build::Method) -> String { - format!("{}{}", self.supers(), method.output_type) - } - - fn svc_returns(&self, method: &prost_build::Method) -> String { - if method.server_streaming { - format!("{}Returns", method.proto_name) - } else { - self.output_name(method) - } - } - - fn rpc_returns(&self, method: &prost_build::Method) -> String { - if method.server_streaming { - "::tower_grpc::client::codec::DecodingBody".into() - } else { - self.output_name(method) - } - } -} diff --git a/tower-grpc-build/src/lib.rs b/tower-grpc-build/src/lib.rs deleted file mode 100644 index d28a96cc5..000000000 --- a/tower-grpc-build/src/lib.rs +++ /dev/null @@ -1,92 +0,0 @@ -extern crate codegen; -extern crate prost_build; - -mod client; -mod server; - -use std::io; -use std::cell::RefCell; -use std::fmt::Write; -use std::path::Path; -use std::rc::Rc; - -/// Code generation configuration -pub struct Config { - prost: prost_build::Config, - inner: Rc>, -} - -struct Inner { - build_client: bool, - build_server: bool, -} - -struct ServiceGenerator { - client: client::ServiceGenerator, - server: server::ServiceGenerator, - inner: Rc>, -} - -impl Config { - /// Returns a new `Config` with default values. - pub fn new() -> Self { - let mut prost = prost_build::Config::new(); - - let inner = Rc::new(RefCell::new(Inner { - // Enable client code gen by default - build_client: true, - - // Disable server code gen by default - build_server: false, - })); - - // Set the service generator - prost.service_generator(Box::new(ServiceGenerator { - client: client::ServiceGenerator, - server: server::ServiceGenerator, - inner: inner.clone(), - })); - - Config { - prost, - inner, - } - } - - /// Enable gRPC client code generation - pub fn enable_client(&mut self, enable: bool) -> &mut Self { - self.inner.borrow_mut().build_client = enable; - self - } - - /// Enable gRPC server code generation - pub fn enable_server(&mut self, enable: bool) -> &mut Self { - self.inner.borrow_mut().build_server = enable; - self - } - - /// Generate code - pub fn build

(&self, protos: &[P], includes: &[P]) -> io::Result<()> - where P: AsRef, - { - self.prost.compile_protos(protos, includes) - } -} - -impl prost_build::ServiceGenerator for ServiceGenerator { - fn generate(&self, service: prost_build::Service, buf: &mut String) { - let inner = self.inner.borrow(); - - if inner.build_client { - // Add an extra new line to separate messages - write!(buf, "\n").unwrap(); - - self.client.generate(&service, buf).unwrap(); - } - - if inner.build_server { - write!(buf, "\n\n").unwrap(); - self.server.generate(&service, buf).unwrap(); - } - } -} diff --git a/tower-grpc-build/src/server.rs b/tower-grpc-build/src/server.rs deleted file mode 100644 index 3be46017c..000000000 --- a/tower-grpc-build/src/server.rs +++ /dev/null @@ -1,723 +0,0 @@ -use codegen; -use prost_build; - -#[allow(unused)] -use std::ascii::AsciiExt; -use std::fmt; - -fn super_import(ty: &str) -> (String, &str) { - let mut v: Vec<&str> = ty.split("::").collect(); - v.insert(0, "super"); - let last = v.pop().unwrap_or(ty); - (v.join("::"), last) -} - -fn unqualified(ty: &str) -> &str { - ty.rsplit("::").next().unwrap_or(ty) -} - -/// Generates service code -pub struct ServiceGenerator; - -impl ServiceGenerator { - fn define(&self, service: &prost_build::Service) -> codegen::Scope { - // Name of the support module. This is the module that will contain all - // the extra types for the service to avoid potential name conflicts - // with other services. - let support_name = service.name.to_ascii_lowercase(); - - // Create support module for the service - let mut support = codegen::Module::new(&support_name); - support.vis("pub") - .import("::tower_grpc::codegen::server", "*") - .import("super", &service.name) - ; - - // Create a structure for the service - let mut service_struct = codegen::Struct::new(&service.name); - service_struct - .vis("pub") - .derive("Debug") - ; - - // A fully not implemented service - let mut service_not_implemented_ty = codegen::Type::new(&service.name); - - // Create a service implementation for the service struct - let mut service_impl = codegen::Impl::new(&service.name); - service_impl.impl_trait("tower::Service") - .associate_type("Request", "http::Request") - .associate_type("Error", "h2::Error") - // `Response` and `Future` associated type comes later! - ; - - let mut service_call_block = codegen::Block::new("match request.uri().path()"); - - // Create a clone impl for the service struct - let mut clone_impl = codegen::Impl::new(&service.name); - clone_impl.impl_trait("Clone") - ; - - let mut clone_block = codegen::Block::new(&service.name); - - // A `NewService` type. This is a wrapper around the service struct, but - // also adds builder functions to help define the service. - let mut new_service = codegen::Struct::new("NewService"); - new_service - .vis("pub") - .derive("Debug") - ; - - let mut new_service_builder_impl = codegen::Impl::new("NewService"); - - let mut new_service_trait_impl = codegen::Impl::new("NewService"); - new_service_trait_impl - .impl_trait("tower::NewService") - .associate_type("Request", "http::Request") - .associate_type("Error", "h2::Error") - .associate_type("InitError", "h2::Error") - .associate_type("Future", "futures::FutureResult") - // `Response` and `Service` associated type comes later! - ; - - // A fully not implemented `NewService` - let mut new_service_not_implemented_ty = codegen::Type::new("NewService"); - - let mut new_block = codegen::Block::new(&format!("inner: {}", service.name)); - - // Create a response future as an enumeration of the service methods - // response futures. - let mut response_fut = codegen::Struct::new("ResponseFuture"); - response_fut - .vis("pub") - ; - - let mut response_impl = codegen::Impl::new("ResponseFuture"); - response_impl.impl_trait("futures::Future") - .associate_type("Error", "h2::Error") - // `Item` associated type comes later - ; - - let mut response_debug_impl = codegen::Impl::new("ResponseFuture"); - response_debug_impl.impl_trait("fmt::Debug") - .function("fmt") - .arg_ref_self() - .arg("fmt", "&mut fmt::Formatter") - .ret("fmt::Result") - .line("write!(fmt, \"ResponseFuture\")") - ; - - let mut response_block = codegen::Block::new(&format!("match self.kind")); - - // Create a response body type as an enumeration of the service methods - // response bodies. - let mut response_body = codegen::Struct::new("ResponseBody"); - response_body - .vis("pub") - ; - - let mut response_body_body_imp = codegen::Impl::new("ResponseBody"); - response_body_body_imp - .impl_trait("tower_h2::Body") - .associate_type("Data", "bytes::Bytes") - ; - - let mut response_body_debug_impl = codegen::Impl::new("ResponseBody"); - response_body_debug_impl.impl_trait("fmt::Debug") - .function("fmt") - .arg_ref_self() - .arg("fmt", "&mut fmt::Formatter") - .ret("fmt::Result") - .line("write!(fmt, \"ResponseBody\")") - ; - ; - - let mut is_end_stream_block = codegen::Block::new("match self.kind"); - let mut poll_data_block = codegen::Block::new("match self.kind"); - let mut poll_trailers_block = codegen::Block::new("match self.kind"); - - // Create the `Kind` enum. This is by the various types above in order - // to contain the inner types for each of the possible service methods. - let mut kind_enum = codegen::Enum::new("Kind"); - kind_enum - .vis("pub(super)") - .derive("Debug") - ; - - for method in &service.methods { - // ===== service struct ===== - - // Push a generic representing the method service - service_struct.generic(&method.proto_name); - - let service_bound = service_bound_for(method); - - // Bound a bound requiring that the service is of the appropriate - // type. - service_struct.bound(&method.proto_name, &service_bound); - - // Push a field to hold the service - service_struct.field(&method.name, field_type_for(&method)); - - let ty = unimplemented_type_for(method); - service_not_implemented_ty.generic(&ty); - new_service_not_implemented_ty.generic(&ty); - - // ===== Service impl ===== - - service_impl.generic(&method.proto_name); - service_impl.target_generic(&method.proto_name); - service_impl.bound(&method.proto_name, &service_bound); - - // The service method path. - let match_line = format!("\"/{}.{}/{}\" =>", - service.package, - service.proto_name, - method.proto_name); - - // Match the service path - let mut route_block = codegen::Block::new(&match_line); - route_block - .line(&format!("let response = self.{}.call(request);", method.name)) - .line(&format!("{}::ResponseFuture {{ kind: Ok({}(response)) }}", support_name, method.proto_name)) - ; - - service_call_block.block(route_block); - - // ===== Clone impl ===== - - clone_impl.generic(&method.proto_name); - clone_impl.target_generic(&method.proto_name); - clone_impl.bound(&method.proto_name, &service_bound); - - clone_block.line(format!("{name}: self.{name}.clone(),", name = method.name)); - - // ===== NewService ===== - - new_service.generic(&method.proto_name); - new_service.bound(&method.proto_name, &service_bound); - - new_service_builder_impl - .generic(&method.proto_name) - .target_generic(&method.proto_name) - .bound(&method.proto_name, &service_bound) - ; - - new_service_trait_impl - .generic(&method.proto_name) - .target_generic(&method.proto_name) - .bound(&method.proto_name, &service_bound) - ; - - new_block.line(&format!("{}: {},", method.name, new_unimplemented_for(&method))); - - // ===== ResponseFuture ===== - - // Push a generic on the response future type - response_fut - .generic(&method.proto_name) - .bound(&method.proto_name, &service_bound); - - response_impl - .generic(&method.proto_name) - .bound(&method.proto_name, &service_bound) - .target_generic(&method.proto_name); - - response_debug_impl - .generic(&method.proto_name) - .target_generic(&method.proto_name) - .bound(&method.proto_name, &service_bound); - - let match_line = format!("Ok({}(ref mut fut)) =>", method.proto_name); - - let mut try_ready_block = codegen::Block::new("let response = match fut.poll()?"); - try_ready_block - .line("futures::Async::Ready(v) => v,") - .line("futures::Async::NotReady => return Ok(futures::Async::NotReady)") - .after(";") - ; - - let mut match_block = codegen::Block::new(&match_line); - match_block - .block(try_ready_block) - .line("let (head, body) = response.into_parts();") - .line(&format!("let body = ResponseBody {{ kind: Ok({}(body)) }};", method.proto_name)) - .line("let response = http::Response::from_parts(head, body);") - .line("Ok(response.into())") - ; - - response_block.block(match_block); - - // ===== ResponseBody ===== - - response_body - .generic(&method.proto_name) - .bound(&method.proto_name, &service_bound) - ; - - response_body_body_imp - .generic(&method.proto_name) - .target_generic(&method.proto_name) - .bound(&method.proto_name, &service_bound) - ; - - response_body_debug_impl - .generic(&method.proto_name) - .target_generic(&method.proto_name) - .bound(&method.proto_name, &service_bound) - ; - - is_end_stream_block - .line(&format!("Ok({}(ref v)) => v.is_end_stream(),", method.proto_name)); - - poll_data_block - .line(&format!("Ok({}(ref mut v)) => v.poll_data(),", method.proto_name)); - - poll_trailers_block - .line(&format!("Ok({}(ref mut v)) => v.poll_trailers(),", method.proto_name)); - - // ===== Kind ===== - - // Push a response kind variant - kind_enum.generic(&method.proto_name); - kind_enum.variant(&method.proto_name) - .tuple(&method.proto_name) - ; - - // ===== support module ===== - - let (input_path, input_type) = super_import(&method.input_type); - let (output_path, output_type) = super_import(&method.output_type); - - // Import the request and response types - support.import(&input_path, input_type); - support.import(&output_path, output_type); - - } - - // ===== service impl ===== - - // An impl block that contains the `new_service` function. This block is - // fixed to `NotImplemented` services for all methods. - let mut service_struct_new = codegen::Impl::new(service_not_implemented_ty); - service_struct_new.function("new_service") - .vis("pub") - .ret(&new_service_not_implemented_ty.path(&support_name)) - .line(&format!("{}::NewService::new()", &support_name)) - ; - - // ===== Service impl ===== - - // Add the Future service associated type - let mut http_response_ty = codegen::Type::new("http::Response"); - http_response_ty.generic(response_body.ty().path(&support_name)); - - service_impl - .associate_type("Response", &http_response_ty) - .associate_type("Future", response_fut.ty().path(&support_name)); - - service_impl.function("poll_ready") - .arg_mut_self() - .ret("futures::Poll<(), Self::Error>") - .line("Ok(().into())") - ; - - let mut catch_all_block = codegen::Block::new("_ =>"); - catch_all_block - .line(&format!("{}::ResponseFuture {{ kind: Err(grpc::Status::UNIMPLEMENTED) }}", support_name)); - - service_call_block.block(catch_all_block); - - service_impl.function("call") - .arg_mut_self() - .arg("request", "Self::Request") - .ret("Self::Future") - .line(&format!("use self::{}::Kind::*;", &support_name)) - .line("") - .block(service_call_block) - ; - - // ===== Clone impl ===== - - clone_impl.function("clone") - .arg_ref_self() - .ret("Self") - .block(clone_block) - ; - - // ===== NewService ===== - - new_service - .field("inner", service_struct.ty()) - ; - - - // Generate all the builder functions - for (i, m1) in service.methods.iter().enumerate() { - let service_bound = service_bound_for(m1); - - let mut ret = codegen::Type::new("NewService"); - - let mut build = codegen::Block::new(&format!("inner: {}", &service.name)); - - // Push all generics onto the return type - for (j, m2) in service.methods.iter().enumerate() { - if i == j { - ret.generic("T"); - build.line(&format!("{}: service,", m2.name)); - } else { - ret.generic(&m2.proto_name); - build.line(&format!("{name}: self.inner.{name},", name = m2.name)); - } - } - - new_service_builder_impl.function(&m1.name) - .vis("pub") - .generic("T") - .bound("T", service_bound) - .arg_self() - .arg("service", "T") - .ret(ret) - .line(new_service_line_for(&m1)) - .line("") - .block({ - let mut b = codegen::Block::new("NewService"); - b.block(build); - b - }) - ; - } - - let mut http_response_ty = codegen::Type::new("http::Response"); - http_response_ty.generic(response_body.ty()); - - new_service_trait_impl - .associate_type("Response", &http_response_ty) - .associate_type("Service", service_struct.ty()) - .function("new_service") - .arg_ref_self() - .ret("Self::Future") - .line("futures::ok(self.inner.clone())") - ; - - let mut new_service_not_implemented_impl = codegen::Impl::new(new_service_not_implemented_ty); - new_service_not_implemented_impl - .function("new") - .vis("pub(super)") - .ret("Self") - .block(codegen::Block::new("NewService") - .block(new_block).clone()) - ; - - // ===== ResponseFuture ===== - - let mut ty = codegen::Type::new("Result"); - ty.generic(response_fut_kind(service)); - ty.generic("grpc::Status"); - - response_fut - .field("pub(super) kind", ty) - ; - - let mut http_response_ty = codegen::Type::new("http::Response"); - http_response_ty.generic(response_body.ty()); - - response_impl - .associate_type("Item", &http_response_ty) - ; - - let mut match_block = codegen::Block::new("Err(ref status) =>"); - match_block - .line("let body = ResponseBody { kind: Err(status.clone()) };") - .line("Ok(grpc::Response::new(body).into_http().into())") - ; - - response_block.block(match_block); - - response_impl.function("poll") - .arg_mut_self() - .ret("futures::Poll") - .line("use self::Kind::*;") - .line("") - .block(response_block) - ; - - // ===== ResponseBody ===== - - let mut ty = codegen::Type::new("Result"); - ty.generic(response_body_kind(service)); - ty.generic("grpc::Status"); - - response_body.field("kind", ty); - - is_end_stream_block - .line("Err(_) => true,"); - - response_body_body_imp.function("is_end_stream") - .arg_ref_self() - .ret("bool") - .line("use self::Kind::*;") - .line("") - .block(is_end_stream_block) - ; - - poll_data_block - .line("Err(_) => Ok(None.into()),"); - - response_body_body_imp.function("poll_data") - .arg_mut_self() - .ret("futures::Poll, h2::Error>") - .line("use self::Kind::*;") - .line("") - .block(poll_data_block) - ; - - let mut match_block = codegen::Block::new("Err(ref status) =>"); - match_block - .line("let mut map = http::HeaderMap::new();") - .line("map.insert(\"grpc-status\", status.to_header_value());") - .line("Ok(Some(map).into())") - ; - - poll_trailers_block.block(match_block); - - response_body_body_imp.function("poll_trailers") - .arg_mut_self() - .ret("futures::Poll, h2::Error>") - .line("use self::Kind::*;") - .line("") - .block(poll_trailers_block) - ; - - // ===== support module ===== - - support - .vis("pub") - .import("std", "fmt") - .push_structure(new_service) - .push_structure(response_fut) - .push_structure(response_body) - .push_enumeration(kind_enum) - .push_imp(new_service_not_implemented_impl) - .push_imp(new_service_builder_impl) - .push_imp(new_service_trait_impl) - .push_imp(response_impl) - .push_imp(response_debug_impl) - .push_imp(response_body_body_imp) - .push_imp(response_body_debug_impl) - ; - - // Create scope that contains the generated server code. - let mut scope = codegen::Scope::new(); - { - let server = scope.module("server") - .vis("pub") - .import("::tower_grpc::codegen::server", "*"); - - for method in &service.methods { - let (input_path, input_type) = super_import(&method.input_type); - let (output_path, output_type) = super_import(&method.output_type); - - // Import the request and response types - server.import(&input_path, input_type); - server.import(&output_path, output_type); - } - - server.push_structure(service_struct) - .push_imp(service_struct_new) - .push_imp(service_impl) - .push_imp(clone_impl) - .push_module(support) - ; - } - - scope - - } - - pub fn generate(&self, service: &prost_build::Service, buf: &mut String) -> fmt::Result { - let scope = self.define(service); - let mut fmt = codegen::Formatter::new(buf); - - scope.fmt(&mut fmt) - } -} - -fn field_type_for(method: &prost_build::Method) -> codegen::Type { - let ty = match (method.client_streaming, method.server_streaming) { - (false, false) => { - format!("grpc::Grpc>>", - method.proto_name, method.input_type) - } - (false, true) => { - format!("grpc::Grpc>>", - method.proto_name, method.input_type) - } - (true, false) => { - format!("grpc::Grpc>", - method.proto_name) - } - (true, true) => { - format!("grpc::Grpc<{}>", - method.proto_name) - } - }; - - codegen::Type::from(ty) -} - -fn service_bound_for(method: &prost_build::Method) -> codegen::Type { - - let input_type = unqualified(&method.input_type); - let output_type = unqualified(&method.output_type); - - let ty = match (method.client_streaming, method.server_streaming) { - (false, false) => { - format!("grpc::UnaryService", - input_type, output_type) - } - (false, true) => { - format!("grpc::ServerStreamingService", - input_type, output_type) - } - (true, false) => { - format!("grpc::ClientStreamingService, Response = {output}>", - input = input_type, output = output_type) - } - (true, true) => { - format!("grpc::GrpcService, Response = {output}>", - input = input_type, output = output_type) - } - }; - - codegen::Type::from(ty) -} - -fn new_service_line_for(method: &prost_build::Method) -> &'static str { - match (method.client_streaming, method.server_streaming) { - (false, false) => { - "let service = grpc::Grpc::new(grpc::Unary::new(service));" - } - (false, true) => { - "let service = grpc::Grpc::new(grpc::ServerStreaming::new(service));" - } - (true, false) => { - "let service = grpc::Grpc::new(grpc::ClientStreaming::new(service));" - } - (true, true) => { - "let service = grpc::Grpc::new(service);" - } - } -} - -fn unimplemented_type_for(method: &prost_build::Method) -> codegen::Type { - let ty = match (method.client_streaming, method.server_streaming) { - (false, false) => { - format!("grpc::NotImplemented<{}, {}>", - unqualified(&method.input_type), unqualified(&method.output_type)) - } - (false, true) => { - format!("grpc::NotImplemented<{}, grpc::unary::Once<{}>>", - unqualified(&method.input_type), unqualified(&method.output_type)) - } - (true, false) => { - format!("grpc::NotImplemented, {}>", - unqualified(&method.input_type), unqualified(&method.output_type)) - } - (true, true) => { - format!("grpc::NotImplemented, grpc::unary::Once<{}>>", - unqualified(&method.input_type), unqualified(&method.output_type)) - } - }; - - codegen::Type::from(ty) -} - -fn new_unimplemented_for(method: &prost_build::Method) -> &'static str { - match (method.client_streaming, method.server_streaming) { - (false, false) => { - "grpc::Grpc::new(grpc::Unary::new(grpc::NotImplemented::new()))" - } - (false, true) => { - "grpc::Grpc::new(grpc::ServerStreaming::new(grpc::NotImplemented::new()))" - } - (true, false) => { - "grpc::Grpc::new(grpc::ClientStreaming::new(grpc::NotImplemented::new()))" - } - (true, true) => { - "grpc::Grpc::new(grpc::NotImplemented::new())" - } - } -} - -// ===== Here be the crazy types ===== - -fn response_fut_kind(service: &prost_build::Service) -> String { - use std::fmt::Write; - - // Handle theempty case... - if service.methods.is_empty() { - return "Kind".to_string(); - } - - let mut ret = "Kind<\n".to_string(); - - for method in &service.methods { - match (method.client_streaming, method.server_streaming) { - (false, false) => { - write!(&mut ret, " >> as tower::Service>::Future,\n", - method.proto_name, method.input_type).unwrap(); - } - (false, true) => { - write!(&mut ret, " >> as tower::Service>::Future,\n", - method.proto_name, method.input_type).unwrap(); - } - (true, false) => { - write!(&mut ret, " > as tower::Service>::Future,\n", - method.proto_name).unwrap(); - } - (true, true) => { - write!(&mut ret, " as tower::Service>::Future,\n", - method.proto_name).unwrap(); - } - } - } - - ret.push_str(">"); - ret -} - -fn response_body_kind(service: &prost_build::Service) -> String { - use std::fmt::Write; - - // Handle theempty case... - if service.methods.is_empty() { - return "Kind".to_string(); - } - - let mut ret = "Kind<\n".to_string(); - - for method in &service.methods { - match (method.client_streaming, method.server_streaming) { - (false, false) => { - write!(&mut ret, " grpc::Encode<> as grpc::GrpcService>::ResponseStream>,\n", - method.proto_name, method.input_type).unwrap(); - } - (false, true) => { - write!(&mut ret, " grpc::Encode<> as grpc::GrpcService>::ResponseStream>,\n", - method.proto_name, method.input_type).unwrap(); - } - (true, false) => { - write!(&mut ret, " grpc::Encode< as grpc::GrpcService>::ResponseStream>,\n", - method.proto_name).unwrap(); - } - (true, true) => { - write!(&mut ret, " grpc::Encode<<{} as grpc::GrpcService>::ResponseStream>,\n", - method.proto_name).unwrap(); - } - } - } - - ret.push_str(">"); - ret -} diff --git a/tower-grpc-examples/Cargo.toml b/tower-grpc-examples/Cargo.toml deleted file mode 100644 index bc01591f0..000000000 --- a/tower-grpc-examples/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "tower-grpc-examples" -version = "0.2.0" -authors = ["Carl Lerche "] - -[[bin]] -name = "helloworld" -path = "src/helloworld.rs" - -[[bin]] -name = "route_guide" -path = "src/routeguide/main.rs" - -[dependencies] -futures = "0.1" -bytes = "0.4" -env_logger = "0.4" -log = "0.3" -prost = "0.2" -prost-derive = "0.2" -tokio-core = "0.1" -tower = { git = "https://github.com/tower-rs/tower" } -tower-h2 = { path = "../tower-h2" } -tower-grpc = { path = "../tower-grpc" } - -# For the routeguide example -serde = "1.0" -serde_json = "1.0" -serde_derive = "1.0" - -[build-dependencies] -tower-grpc-build = { path = "../tower-grpc-build" } diff --git a/tower-grpc-examples/build.rs b/tower-grpc-examples/build.rs deleted file mode 100644 index 0da8d4d15..000000000 --- a/tower-grpc-examples/build.rs +++ /dev/null @@ -1,17 +0,0 @@ -extern crate tower_grpc_build; - -fn main() { - // Build helloworld - tower_grpc_build::Config::new() - .enable_server(true) - .enable_client(false) - .build(&["proto/helloworld/helloworld.proto"], &["proto/helloworld"]) - .unwrap(); - - // Build routeguide - tower_grpc_build::Config::new() - .enable_server(true) - .enable_client(false) - .build(&["proto/routeguide/route_guide.proto"], &["proto/routeguide"]) - .unwrap(); -} diff --git a/tower-grpc-examples/data/route_guide_db.json b/tower-grpc-examples/data/route_guide_db.json deleted file mode 100644 index 9d6a980ab..000000000 --- a/tower-grpc-examples/data/route_guide_db.json +++ /dev/null @@ -1,601 +0,0 @@ -[{ - "location": { - "latitude": 407838351, - "longitude": -746143763 - }, - "name": "Patriots Path, Mendham, NJ 07945, USA" -}, { - "location": { - "latitude": 408122808, - "longitude": -743999179 - }, - "name": "101 New Jersey 10, Whippany, NJ 07981, USA" -}, { - "location": { - "latitude": 413628156, - "longitude": -749015468 - }, - "name": "U.S. 6, Shohola, PA 18458, USA" -}, { - "location": { - "latitude": 419999544, - "longitude": -740371136 - }, - "name": "5 Conners Road, Kingston, NY 12401, USA" -}, { - "location": { - "latitude": 414008389, - "longitude": -743951297 - }, - "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" -}, { - "location": { - "latitude": 419611318, - "longitude": -746524769 - }, - "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" -}, { - "location": { - "latitude": 406109563, - "longitude": -742186778 - }, - "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" -}, { - "location": { - "latitude": 416802456, - "longitude": -742370183 - }, - "name": "352 South Mountain Road, Wallkill, NY 12589, USA" -}, { - "location": { - "latitude": 412950425, - "longitude": -741077389 - }, - "name": "Bailey Turn Road, Harriman, NY 10926, USA" -}, { - "location": { - "latitude": 412144655, - "longitude": -743949739 - }, - "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" -}, { - "location": { - "latitude": 415736605, - "longitude": -742847522 - }, - "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" -}, { - "location": { - "latitude": 413843930, - "longitude": -740501726 - }, - "name": "162 Merrill Road, Highland Mills, NY 10930, USA" -}, { - "location": { - "latitude": 410873075, - "longitude": -744459023 - }, - "name": "Clinton Road, West Milford, NJ 07480, USA" -}, { - "location": { - "latitude": 412346009, - "longitude": -744026814 - }, - "name": "16 Old Brook Lane, Warwick, NY 10990, USA" -}, { - "location": { - "latitude": 402948455, - "longitude": -747903913 - }, - "name": "3 Drake Lane, Pennington, NJ 08534, USA" -}, { - "location": { - "latitude": 406337092, - "longitude": -740122226 - }, - "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" -}, { - "location": { - "latitude": 406421967, - "longitude": -747727624 - }, - "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" -}, { - "location": { - "latitude": 416318082, - "longitude": -749677716 - }, - "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" -}, { - "location": { - "latitude": 415301720, - "longitude": -748416257 - }, - "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" -}, { - "location": { - "latitude": 402647019, - "longitude": -747071791 - }, - "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" -}, { - "location": { - "latitude": 412567807, - "longitude": -741058078 - }, - "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" -}, { - "location": { - "latitude": 416855156, - "longitude": -744420597 - }, - "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" -}, { - "location": { - "latitude": 404663628, - "longitude": -744820157 - }, - "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" -}, { - "location": { - "latitude": 407113723, - "longitude": -749746483 - }, - "name": "" -}, { - "location": { - "latitude": 402133926, - "longitude": -743613249 - }, - "name": "" -}, { - "location": { - "latitude": 400273442, - "longitude": -741220915 - }, - "name": "" -}, { - "location": { - "latitude": 411236786, - "longitude": -744070769 - }, - "name": "" -}, { - "location": { - "latitude": 411633782, - "longitude": -746784970 - }, - "name": "211-225 Plains Road, Augusta, NJ 07822, USA" -}, { - "location": { - "latitude": 415830701, - "longitude": -742952812 - }, - "name": "" -}, { - "location": { - "latitude": 413447164, - "longitude": -748712898 - }, - "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" -}, { - "location": { - "latitude": 405047245, - "longitude": -749800722 - }, - "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" -}, { - "location": { - "latitude": 418858923, - "longitude": -746156790 - }, - "name": "" -}, { - "location": { - "latitude": 417951888, - "longitude": -748484944 - }, - "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" -}, { - "location": { - "latitude": 407033786, - "longitude": -743977337 - }, - "name": "26 East 3rd Street, New Providence, NJ 07974, USA" -}, { - "location": { - "latitude": 417548014, - "longitude": -740075041 - }, - "name": "" -}, { - "location": { - "latitude": 410395868, - "longitude": -744972325 - }, - "name": "" -}, { - "location": { - "latitude": 404615353, - "longitude": -745129803 - }, - "name": "" -}, { - "location": { - "latitude": 406589790, - "longitude": -743560121 - }, - "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" -}, { - "location": { - "latitude": 414653148, - "longitude": -740477477 - }, - "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" -}, { - "location": { - "latitude": 405957808, - "longitude": -743255336 - }, - "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" -}, { - "location": { - "latitude": 411733589, - "longitude": -741648093 - }, - "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" -}, { - "location": { - "latitude": 412676291, - "longitude": -742606606 - }, - "name": "1270 Lakes Road, Monroe, NY 10950, USA" -}, { - "location": { - "latitude": 409224445, - "longitude": -748286738 - }, - "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" -}, { - "location": { - "latitude": 406523420, - "longitude": -742135517 - }, - "name": "652 Garden Street, Elizabeth, NJ 07202, USA" -}, { - "location": { - "latitude": 401827388, - "longitude": -740294537 - }, - "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" -}, { - "location": { - "latitude": 410564152, - "longitude": -743685054 - }, - "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" -}, { - "location": { - "latitude": 408472324, - "longitude": -740726046 - }, - "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" -}, { - "location": { - "latitude": 412452168, - "longitude": -740214052 - }, - "name": "5 White Oak Lane, Stony Point, NY 10980, USA" -}, { - "location": { - "latitude": 409146138, - "longitude": -746188906 - }, - "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" -}, { - "location": { - "latitude": 404701380, - "longitude": -744781745 - }, - "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" -}, { - "location": { - "latitude": 409642566, - "longitude": -746017679 - }, - "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" -}, { - "location": { - "latitude": 408031728, - "longitude": -748645385 - }, - "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" -}, { - "location": { - "latitude": 413700272, - "longitude": -742135189 - }, - "name": "367 Prospect Road, Chester, NY 10918, USA" -}, { - "location": { - "latitude": 404310607, - "longitude": -740282632 - }, - "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" -}, { - "location": { - "latitude": 409319800, - "longitude": -746201391 - }, - "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" -}, { - "location": { - "latitude": 406685311, - "longitude": -742108603 - }, - "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" -}, { - "location": { - "latitude": 419018117, - "longitude": -749142781 - }, - "name": "43 Dreher Road, Roscoe, NY 12776, USA" -}, { - "location": { - "latitude": 412856162, - "longitude": -745148837 - }, - "name": "Swan Street, Pine Island, NY 10969, USA" -}, { - "location": { - "latitude": 416560744, - "longitude": -746721964 - }, - "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" -}, { - "location": { - "latitude": 405314270, - "longitude": -749836354 - }, - "name": "" -}, { - "location": { - "latitude": 414219548, - "longitude": -743327440 - }, - "name": "" -}, { - "location": { - "latitude": 415534177, - "longitude": -742900616 - }, - "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" -}, { - "location": { - "latitude": 406898530, - "longitude": -749127080 - }, - "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" -}, { - "location": { - "latitude": 407586880, - "longitude": -741670168 - }, - "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" -}, { - "location": { - "latitude": 400106455, - "longitude": -742870190 - }, - "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" -}, { - "location": { - "latitude": 400066188, - "longitude": -746793294 - }, - "name": "" -}, { - "location": { - "latitude": 418803880, - "longitude": -744102673 - }, - "name": "40 Mountain Road, Napanoch, NY 12458, USA" -}, { - "location": { - "latitude": 414204288, - "longitude": -747895140 - }, - "name": "" -}, { - "location": { - "latitude": 414777405, - "longitude": -740615601 - }, - "name": "" -}, { - "location": { - "latitude": 415464475, - "longitude": -747175374 - }, - "name": "48 North Road, Forestburgh, NY 12777, USA" -}, { - "location": { - "latitude": 404062378, - "longitude": -746376177 - }, - "name": "" -}, { - "location": { - "latitude": 405688272, - "longitude": -749285130 - }, - "name": "" -}, { - "location": { - "latitude": 400342070, - "longitude": -748788996 - }, - "name": "" -}, { - "location": { - "latitude": 401809022, - "longitude": -744157964 - }, - "name": "" -}, { - "location": { - "latitude": 404226644, - "longitude": -740517141 - }, - "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" -}, { - "location": { - "latitude": 410322033, - "longitude": -747871659 - }, - "name": "" -}, { - "location": { - "latitude": 407100674, - "longitude": -747742727 - }, - "name": "" -}, { - "location": { - "latitude": 418811433, - "longitude": -741718005 - }, - "name": "213 Bush Road, Stone Ridge, NY 12484, USA" -}, { - "location": { - "latitude": 415034302, - "longitude": -743850945 - }, - "name": "" -}, { - "location": { - "latitude": 411349992, - "longitude": -743694161 - }, - "name": "" -}, { - "location": { - "latitude": 404839914, - "longitude": -744759616 - }, - "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" -}, { - "location": { - "latitude": 414638017, - "longitude": -745957854 - }, - "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" -}, { - "location": { - "latitude": 412127800, - "longitude": -740173578 - }, - "name": "" -}, { - "location": { - "latitude": 401263460, - "longitude": -747964303 - }, - "name": "" -}, { - "location": { - "latitude": 412843391, - "longitude": -749086026 - }, - "name": "" -}, { - "location": { - "latitude": 418512773, - "longitude": -743067823 - }, - "name": "" -}, { - "location": { - "latitude": 404318328, - "longitude": -740835638 - }, - "name": "42-102 Main Street, Belford, NJ 07718, USA" -}, { - "location": { - "latitude": 419020746, - "longitude": -741172328 - }, - "name": "" -}, { - "location": { - "latitude": 404080723, - "longitude": -746119569 - }, - "name": "" -}, { - "location": { - "latitude": 401012643, - "longitude": -744035134 - }, - "name": "" -}, { - "location": { - "latitude": 404306372, - "longitude": -741079661 - }, - "name": "" -}, { - "location": { - "latitude": 403966326, - "longitude": -748519297 - }, - "name": "" -}, { - "location": { - "latitude": 405002031, - "longitude": -748407866 - }, - "name": "" -}, { - "location": { - "latitude": 409532885, - "longitude": -742200683 - }, - "name": "" -}, { - "location": { - "latitude": 416851321, - "longitude": -742674555 - }, - "name": "" -}, { - "location": { - "latitude": 406411633, - "longitude": -741722051 - }, - "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" -}, { - "location": { - "latitude": 413069058, - "longitude": -744597778 - }, - "name": "261 Van Sickle Road, Goshen, NY 10924, USA" -}, { - "location": { - "latitude": 418465462, - "longitude": -746859398 - }, - "name": "" -}, { - "location": { - "latitude": 411733222, - "longitude": -744228360 - }, - "name": "" -}, { - "location": { - "latitude": 410248224, - "longitude": -747127767 - }, - "name": "3 Hasta Way, Newton, NJ 07860, USA" -}] diff --git a/tower-grpc-examples/proto/helloworld/helloworld.proto b/tower-grpc-examples/proto/helloworld/helloworld.proto deleted file mode 100644 index d79a6a0d1..000000000 --- a/tower-grpc-examples/proto/helloworld/helloworld.proto +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015 gRPC authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -option java_multiple_files = true; -option java_package = "io.grpc.examples.helloworld"; -option java_outer_classname = "HelloWorldProto"; - -package helloworld; - -// The greeting service definition. -service Greeter { - // Sends a greeting - rpc SayHello (HelloRequest) returns (HelloReply) {} -} - -// The request message containing the user's name. -message HelloRequest { - string name = 1; -} - -// The response message containing the greetings -message HelloReply { - string message = 1; -} diff --git a/tower-grpc-examples/proto/routeguide/route_guide.proto b/tower-grpc-examples/proto/routeguide/route_guide.proto deleted file mode 100644 index fe21e437a..000000000 --- a/tower-grpc-examples/proto/routeguide/route_guide.proto +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2015 gRPC authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -option java_multiple_files = true; -option java_package = "io.grpc.examples.routeguide"; -option java_outer_classname = "RouteGuideProto"; - -package routeguide; - -// Interface exported by the server. -service RouteGuide { - // A simple RPC. - // - // Obtains the feature at a given position. - // - // A feature with an empty name is returned if there's no feature at the given - // position. - rpc GetFeature(Point) returns (Feature) {} - - // A server-to-client streaming RPC. - // - // Obtains the Features available within the given Rectangle. Results are - // streamed rather than returned at once (e.g. in a response message with a - // repeated field), as the rectangle may cover a large area and contain a - // huge number of features. - rpc ListFeatures(Rectangle) returns (stream Feature) {} - - // A client-to-server streaming RPC. - // - // Accepts a stream of Points on a route being traversed, returning a - // RouteSummary when traversal is completed. - rpc RecordRoute(stream Point) returns (RouteSummary) {} - - // A Bidirectional streaming RPC. - // - // Accepts a stream of RouteNotes sent while a route is being traversed, - // while receiving other RouteNotes (e.g. from other users). - rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} -} - -// Points are represented as latitude-longitude pairs in the E7 representation -// (degrees multiplied by 10**7 and rounded to the nearest integer). -// Latitudes should be in the range +/- 90 degrees and longitude should be in -// the range +/- 180 degrees (inclusive). -message Point { - int32 latitude = 1; - int32 longitude = 2; -} - -// A latitude-longitude rectangle, represented as two diagonally opposite -// points "lo" and "hi". -message Rectangle { - // One corner of the rectangle. - Point lo = 1; - - // The other corner of the rectangle. - Point hi = 2; -} - -// A feature names something at a given point. -// -// If a feature could not be named, the name is empty. -message Feature { - // The name of the feature. - string name = 1; - - // The point where the feature is detected. - Point location = 2; -} - -// A RouteNote is a message sent while at a given point. -message RouteNote { - // The location from which the message is sent. - Point location = 1; - - // The message to be sent. - string message = 2; -} - -// A RouteSummary is received in response to a RecordRoute rpc. -// -// It contains the number of individual points received, the number of -// detected features, and the total distance covered as the cumulative sum of -// the distance between each point. -message RouteSummary { - // The number of points received. - int32 point_count = 1; - - // The number of known features passed while traversing the route. - int32 feature_count = 2; - - // The distance covered in metres. - int32 distance = 3; - - // The duration of the traversal in seconds. - int32 elapsed_time = 4; -} diff --git a/tower-grpc-examples/src/helloworld.rs b/tower-grpc-examples/src/helloworld.rs deleted file mode 100644 index 7fb465a96..000000000 --- a/tower-grpc-examples/src/helloworld.rs +++ /dev/null @@ -1,79 +0,0 @@ -extern crate bytes; -extern crate env_logger; -extern crate futures; -#[macro_use] -extern crate log; -extern crate prost; -#[macro_use] -extern crate prost_derive; -extern crate tokio_core; -extern crate tower; -extern crate tower_h2; -extern crate tower_grpc; - -mod hello_world { - include!(concat!(env!("OUT_DIR"), "/helloworld.rs")); -} - -use hello_world::{server, HelloRequest, HelloReply}; - -use futures::{future, Future, Stream, Poll}; -use tokio_core::net::TcpListener; -use tokio_core::reactor::Core; -use tower::Service; -use tower_h2::Server; -use tower_grpc::{Request, Response}; - -#[derive(Clone, Debug)] -struct Greet; - -impl Service for Greet { - type Request = Request; - type Response = Response; - type Error = tower_grpc::Error; - type Future = future::FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(().into()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - println!("SayHello = {:?}", request); - - let response = Response::new(HelloReply { - message: "Zomg, it works!".to_string(), - }); - - future::ok(response) - } -} - -pub fn main() { - let _ = ::env_logger::init(); - - let mut core = Core::new().unwrap(); - let reactor = core.handle(); - - let new_service = server::Greeter::new_service() - .say_hello(Greet) - ; - - let h2 = Server::new(new_service, Default::default(), reactor.clone()); - - let addr = "[::1]:50051".parse().unwrap(); - let bind = TcpListener::bind(&addr, &reactor).expect("bind"); - - let serve = bind.incoming() - .fold((h2, reactor), |(h2, reactor), (sock, _)| { - if let Err(e) = sock.set_nodelay(true) { - return Err(e); - } - - let serve = h2.serve(sock); - reactor.spawn(serve.map_err(|e| error!("h2 error: {:?}", e))); - - Ok((h2, reactor)) - }); - - core.run(serve).unwrap(); -} diff --git a/tower-grpc-examples/src/route_guide.rs b/tower-grpc-examples/src/route_guide.rs deleted file mode 100644 index 3e122a609..000000000 --- a/tower-grpc-examples/src/route_guide.rs +++ /dev/null @@ -1,155 +0,0 @@ -extern crate bytes; -extern crate env_logger; -extern crate futures; -#[macro_use] -extern crate log; -extern crate prost; -#[macro_use] -extern crate prost_derive; -extern crate tokio_core; -extern crate tower; -extern crate tower_h2; -extern crate tower_grpc; - -extern crate serde; -extern crate serde_json; -#[macro_use] -extern crate serde_derive; - -mod routeguide { - include!(concat!(env!("OUT_DIR"), "/routeguide.rs")); -} -use routeguide::{server, Point, Rectangle, Feature, RouteSummary, RouteNote}; - -use futures::{future, Future, Stream, Poll}; -use futures::sync::mpsc; -use tokio_core::net::TcpListener; -use tokio_core::reactor::Core; -use tower::Service; -use tower_h2::Server; -use tower_grpc::{Request, Response}; - -#[derive(Debug, Deserialize)] -pub struct Route { -} - -#[derive(Debug, Deserialize)] -pub struct Location { - latitude: i32, - longitude: i32, -} - -/// Handles GetFeature requests -#[derive(Clone, Debug)] -struct GetFeature; - -/// Handles ListFeatures requests -#[derive(Clone, Debug)] -struct ListFeatures; - -/// Handles RecordRoute requests -#[derive(Clone, Debug)] -struct RecordRoute; - -/// Handles RouteChat requests -#[derive(Clone, Debug)] -struct RouteChat; - -impl Service for GetFeature { - type Request = Request; - type Response = Response; - type Error = tower_grpc::Error; - type Future = future::FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(().into()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - println!("GetFeature = {:?}", request); - - let response = Response::new(Feature { - name: "This is my feature".to_string(), - location: Some(request.get_ref().clone()), - }); - - future::ok(response) - } -} - -impl Service for ListFeatures { - type Request = Request; - type Response = Response>>; - type Error = tower_grpc::Error; - type Future = future::FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(().into()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - unimplemented!(); - } -} - -impl Service for RecordRoute { - type Request = Request>; - type Response = Response; - type Error = tower_grpc::Error; - type Future = future::FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(().into()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - unimplemented!(); - } -} - -impl Service for RouteChat { - type Request = Request>; - type Response = Response>>; - type Error = tower_grpc::Error; - type Future = future::FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(().into()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - unimplemented!(); - } -} - -pub fn main() { - let _ = ::env_logger::init(); - - let mut core = Core::new().unwrap(); - let reactor = core.handle(); - - let new_service = server::RouteGuide::new_service() - .get_feature(GetFeature) - .list_features(ListFeatures) - ; - - let h2 = Server::new(new_service, Default::default(), reactor.clone()); - - let addr = "[::1]:50051".parse().unwrap(); - let bind = TcpListener::bind(&addr, &reactor).expect("bind"); - - let serve = bind.incoming() - .fold((h2, reactor), |(h2, reactor), (sock, _)| { - if let Err(e) = sock.set_nodelay(true) { - return Err(e); - } - - let serve = h2.serve(sock); - reactor.spawn(serve.map_err(|e| error!("h2 error: {:?}", e))); - - Ok((h2, reactor)) - }); - - core.run(serve).unwrap(); -} - diff --git a/tower-grpc-examples/src/routeguide/data.rs b/tower-grpc-examples/src/routeguide/data.rs deleted file mode 100644 index f4e86b966..000000000 --- a/tower-grpc-examples/src/routeguide/data.rs +++ /dev/null @@ -1,42 +0,0 @@ -#![allow(unused_imports)] - -use serde_json; - -use std::{env, io}; -use std::io::prelude::*; -use std::fs::File; -use std::path::Path; - -#[derive(Debug, Deserialize)] -struct Feature { - location: Location, - name: String, -} - -#[derive(Debug, Deserialize)] -struct Location { - latitude: i32, - longitude: i32, -} - -pub fn load() -> Vec<::routeguide::Feature> { - let args: Vec<_> = env::args().collect(); - - assert_eq!(args.len(), 2, "unexpected arguments"); - - let mut file = File::open(&args[1]).ok().expect("failed to open data file"); - let mut data = String::new(); - file.read_to_string(&mut data).ok().expect("failed to read data file"); - - let decoded: Vec = serde_json::from_str(&data).unwrap(); - - decoded.into_iter().map(|feature| { - ::routeguide::Feature { - name: feature.name, - location: Some(::routeguide::Point { - longitude: feature.location.longitude, - latitude: feature.location.latitude, - }), - } - }).collect() -} diff --git a/tower-grpc-examples/src/routeguide/main.rs b/tower-grpc-examples/src/routeguide/main.rs deleted file mode 100644 index 185eacb61..000000000 --- a/tower-grpc-examples/src/routeguide/main.rs +++ /dev/null @@ -1,201 +0,0 @@ -#![allow(dead_code)] -#![allow(unused_variables)] - -extern crate bytes; -extern crate env_logger; -extern crate futures; -#[macro_use] -extern crate log; -extern crate prost; -#[macro_use] -extern crate prost_derive; -extern crate tokio_core; -extern crate tower; -extern crate tower_h2; -extern crate tower_grpc; - -extern crate serde; -extern crate serde_json; -#[macro_use] -extern crate serde_derive; - -mod data; -mod routeguide { - include!(concat!(env!("OUT_DIR"), "/routeguide.rs")); -} -use routeguide::{server, Point, Rectangle, Feature, RouteSummary, RouteNote}; - -use futures::{future, Future, Stream, Sink, Poll}; -use futures::sync::mpsc; -use tokio_core::net::TcpListener; -use tokio_core::reactor::Core; -use tower::Service; -use tower_h2::Server; -use tower_grpc::{Request, Response}; - -use std::sync::Arc; - -pub type Features = Arc>; - -/// Handles GetFeature requests -#[derive(Clone, Debug)] -struct GetFeature(Features); - -/// Handles ListFeatures requests -#[derive(Clone, Debug)] -struct ListFeatures(Features); - -/// Handles RecordRoute requests -#[derive(Clone, Debug)] -struct RecordRoute; - -/// Handles RouteChat requests -#[derive(Clone, Debug)] -struct RouteChat; - -impl Service for GetFeature { - type Request = Request; - type Response = Response; - type Error = tower_grpc::Error; - type Future = future::FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(().into()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - println!("GetFeature = {:?}", request); - - for feature in &self.0[..] { - if feature.location.as_ref() == Some(request.get_ref()) { - return future::ok(Response::new(feature.clone())); - } - } - - // Otherwise, return some other feature? - let response = Response::new(Feature { - name: "".to_string(), - location: None, - }); - - future::ok(response) - } -} - -impl Service for ListFeatures { - type Request = Request; - type Response = Response>>; - type Error = tower_grpc::Error; - type Future = future::FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(().into()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - use std::thread; - - println!("ListFeatures = {:?}", request); - - let (tx, rx) = mpsc::channel(4); - - let features = self.0.clone(); - - thread::spawn(move || { - let mut tx = tx.wait(); - - for feature in &features[..] { - if in_range(feature.location.as_ref().unwrap(), request.get_ref()) { - tx.send(feature.clone()).unwrap(); - } - } - }); - - let rx = rx.map_err(|_| unimplemented!()); - future::ok(Response::new(Box::new(rx))) - } -} - -impl Service for RecordRoute { - type Request = Request>; - type Response = Response; - type Error = tower_grpc::Error; - type Future = future::FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(().into()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - - unimplemented!(); - } -} - -impl Service for RouteChat { - type Request = Request>; - type Response = Response>>; - type Error = tower_grpc::Error; - type Future = future::FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(().into()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - unimplemented!(); - } -} - -fn in_range(point: &Point, rect: &Rectangle) -> bool { - use std::cmp; - - let lo = rect.lo.as_ref().unwrap(); - let hi = rect.hi.as_ref().unwrap(); - - let left = cmp::min(lo.longitude, hi.longitude); - let right = cmp::max(lo.longitude, hi.longitude); - let top = cmp::max(lo.latitude, hi.latitude); - let bottom = cmp::min(lo.latitude, hi.latitude); - - point.longitude >= left && - point.longitude <= right && - point.latitude >= bottom && - point.latitude <= top -} - -pub fn main() { - let _ = ::env_logger::init(); - - // Load data file - let data = Arc::new(data::load()); - - let mut core = Core::new().unwrap(); - let reactor = core.handle(); - - let new_service = server::RouteGuide::new_service() - .get_feature(GetFeature(data.clone())) - .list_features(ListFeatures(data.clone())) - ; - - let h2 = Server::new(new_service, Default::default(), reactor.clone()); - - let addr = "127.0.0.1:10000".parse().unwrap(); - let bind = TcpListener::bind(&addr, &reactor).expect("bind"); - - println!("listining on {:?}", addr); - - let serve = bind.incoming() - .fold((h2, reactor), |(h2, reactor), (sock, _)| { - if let Err(e) = sock.set_nodelay(true) { - return Err(e); - } - - let serve = h2.serve(sock); - reactor.spawn(serve.map_err(|e| error!("h2 error: {:?}", e))); - - Ok((h2, reactor)) - }); - - core.run(serve).unwrap(); -} diff --git a/tower-grpc/Cargo.toml b/tower-grpc/Cargo.toml deleted file mode 100644 index 218b6806b..000000000 --- a/tower-grpc/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "tower-grpc" -version = "0.2.0" -authors = ["Sean McArthur "] - -[features] -default = ["protobuf"] -protobuf = ["prost"] - -[dependencies] -bytes = "0.4" -futures = "0.1" -http = "0.1" -h2 = { git = "https://github.com/carllerche/h2" } -log = "0.3" -tower = { git = "https://github.com/tower-rs/tower" } -tower-h2 = { path = "../tower-h2" } -tower-router = { git = "https://github.com/tower-rs/tower" } - -# For protobuf -prost = { version = "0.2", optional = true } - -[dev-dependencies] -env_logger = "0.4" -tokio-connect = { git = "https://github.com/carllerche/tokio-connect" } -tokio-core = "0.1" - -# For examples -prost = "0.2" -prost-derive = "0.2" diff --git a/tower-grpc/examples/greeter_client.rs b/tower-grpc/examples/greeter_client.rs deleted file mode 100644 index 36688cdc0..000000000 --- a/tower-grpc/examples/greeter_client.rs +++ /dev/null @@ -1,209 +0,0 @@ -extern crate bytes; -extern crate env_logger; -extern crate futures; -extern crate http; -extern crate h2; -extern crate tokio_connect; -extern crate tokio_core; -extern crate tower; -extern crate tower_grpc; -extern crate tower_h2; - -use std::net::SocketAddr; - -use bytes::{Buf, BufMut}; -use futures::Future; -use tokio_connect::Connect; -use tokio_core::net::TcpStream; -use tokio_core::reactor::{Core, Handle}; -use tower::{Service, NewService}; - -use self::helloworld::{Greeter, HelloRequest, HelloReply, SayHello}; - -// eventually generated? -mod helloworld { - use futures::{Future, Poll}; - use tower::Service; - use tower_grpc; - use tower_grpc::client::Codec; - - pub struct HelloRequest { - pub name: String, - } - - pub struct HelloReply { - pub message: String, - } - - pub struct Greeter { - say_hello: SayHelloRpc, - } - - impl Greeter - where - SayHelloRpc: Service< - Request=tower_grpc::Request, - Response=tower_grpc::Response, - >, - { - pub fn new(say_hello: SayHelloRpc) -> Self { - Greeter { - say_hello, - } - } - - pub fn say_hello(&mut self, req: HelloRequest) -> ::futures::future::Map) -> HelloReply> { - let req = tower_grpc::Request::new("/helloworld.Greeter/SayHello", req); - self.say_hello.call(req) - .map(|res| { - res.into_http().into_parts().1 - } as _) - } - } - - pub struct SayHello { - service: S, - } - - impl SayHello - where - C: Codec, - S: Service< - Request=tower_grpc::Request< - tower_grpc::client::codec::Unary - >, - Response=tower_grpc::Response< - tower_grpc::client::codec::DecodingBody - >, - >, - { - pub fn new(service: S) -> Self { - SayHello { - service, - } - } - } - - impl Service for SayHello - where - C: Codec, - S: Service< - Request=tower_grpc::Request< - tower_grpc::client::codec::Unary - >, - Response=tower_grpc::Response< - tower_grpc::client::codec::DecodingBody - >, - Error=tower_grpc::Error - >, - { - type Request = tower_grpc::Request; - type Response = tower_grpc::Response; - type Error = S::Error; - type Future = tower_grpc::client::Unary; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.service.poll_ready() - } - - fn call(&mut self, req: Self::Request) -> Self::Future { - let fut = self.service.call(req.into_unary()); - tower_grpc::client::Unary::map_future(fut) - } - } -} - -#[derive(Clone, Copy)] -pub struct StupidCodec; - -impl tower_grpc::client::codec::Codec for StupidCodec { - const CONTENT_TYPE: &'static str = "application/proto+stupid"; - type Encode = HelloRequest; - type Decode = HelloReply; - type EncodeError = (); - type DecodeError = (); - - - fn encode(&mut self, msg: Self::Encode, buf: &mut tower_grpc::client::codec::EncodeBuf) -> Result<(), Self::EncodeError> { - buf.reserve(msg.name.len()); - buf.put(msg.name.as_bytes()); - Ok(()) - } - - fn decode(&mut self, buf: &mut tower_grpc::client::codec::DecodeBuf) -> Result { - let s = ::std::str::from_utf8(buf.bytes()).unwrap().to_string(); - buf.advance(s.len()); - Ok(HelloReply { - message: s, - }) - } -} - -struct Conn(SocketAddr, Handle); - -impl Connect for Conn { - type Connected = TcpStream; - type Error = ::std::io::Error; - type Future = Box>; - - fn connect(&self) -> Self::Future { - let c = TcpStream::connect(&self.0, &self.1) - .and_then(|tcp| tcp.set_nodelay(true).map(move |_| tcp)); - Box::new(c) - } -} - -struct AddOrigin(S); - -impl Service for AddOrigin -where - S: Service>, -{ - type Request = S::Request; - type Response = S::Response; - type Error = S::Error; - type Future = S::Future; - - fn poll_ready(&mut self) -> ::futures::Poll<(), Self::Error> { - self.0.poll_ready() - } - - fn call(&mut self, mut req: Self::Request) -> Self::Future { - use std::str::FromStr; - //TODO: use Uri.into_parts() to be more efficient - let full_uri = format!("http://127.0.0.1:8888{}", req.uri().path()); - let new_uri = http::Uri::from_str(&full_uri).expect("example uri should work"); - *req.uri_mut() = new_uri; - self.0.call(req) - } -} - - -fn main() { - drop(env_logger::init()); - - let mut core = Core::new().unwrap(); - let reactor = core.handle(); - - let addr = "[::1]:8888".parse().unwrap(); - - - let conn = Conn(addr, reactor.clone()); - let h2 = tower_h2::Client::new(conn, Default::default(), reactor); - - let done = h2.new_service() - .map_err(|e| unimplemented!("h2 new_service error: {:?}", e)) - .and_then(move |service| { - let service = AddOrigin(service); - let grpc = tower_grpc::Client::new(StupidCodec, service); - let say_hello = SayHello::new(grpc); - let mut greeter = Greeter::new(say_hello); - greeter.say_hello(HelloRequest { - name: String::from("world"), - }) - }) - .map(|reply| println!("Greeter.SayHello: {}", reply.message)) - .map_err(|e| println!("error: {:?}", e)); - - let _ = core.run(done); -} diff --git a/tower-grpc/examples/greeter_server.rs b/tower-grpc/examples/greeter_server.rs deleted file mode 100644 index d9c5e30e1..000000000 --- a/tower-grpc/examples/greeter_server.rs +++ /dev/null @@ -1,190 +0,0 @@ -extern crate bytes; -extern crate env_logger; -extern crate futures; -extern crate h2; -extern crate http; -#[macro_use] -extern crate log; -extern crate tokio_core; -extern crate tower; -extern crate tower_h2; - -use bytes::{Buf, BufMut, Bytes, BytesMut, IntoBuf, BigEndian}; -use futures::{future, Async, Future, Poll, Stream}; -use http::{Request, HeaderMap}; -use http::header::HeaderValue; -use tokio_core::net::TcpListener; -use tokio_core::reactor::Core; -use tower::{NewService, Service}; -use tower_h2::{Body, Data, Server, RecvBody}; - -type Response = http::Response; - -struct HelloBody { - message: Bytes, - status: &'static str, -} - -impl HelloBody { - fn new(body: Bytes) -> Self { - HelloBody { - message: body, - status: "0", - } - } - - fn unimplemented() -> Self { - HelloBody { - message: Bytes::new(), - status: "12", - } - } - - fn internal() -> Self { - HelloBody { - message: Bytes::new(), - status: "13", - } - } -} - - -impl Body for HelloBody { - type Data = Bytes; - - fn poll_data(&mut self) -> Poll, h2::Error> { - let data = self.message.split_off(0); - let data = if data.is_empty() { - None - } else { - Some(data) - }; - Ok(Async::Ready(data)) - } - - fn poll_trailers(&mut self) -> Poll, h2::Error> { - let mut map = HeaderMap::new(); - map.insert("grpc-status", HeaderValue::from_static(self.status)); - Ok(Async::Ready(Some(map))) - } -} - -struct RecvBodyStream(tower_h2::RecvBody); - -impl Stream for RecvBodyStream { - type Item = Data; - type Error = h2::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - self.0.poll_data() - } -} - -const SAY_HELLO: &'static str = "/helloworld.Greeter/SayHello"; - -#[derive(Debug)] -struct Svc; -impl Service for Svc { - type Request = Request; - type Response = Response; - type Error = h2::Error; - type Future = Box>; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(Async::Ready(())) - } - - fn call(&mut self, req: Self::Request) -> Self::Future { - let mut rsp = http::Response::builder(); - rsp.version(http::Version::HTTP_2); - - if req.uri().path() != SAY_HELLO { - println!("unknown route"); - let body = HelloBody::unimplemented(); - let rsp = rsp.body(body).unwrap(); - return Box::new(future::ok(rsp)); - } - - let hello = RecvBodyStream(req.into_parts().1); - - // TODO: This is not great flow control management - Box::new(hello.map(Bytes::from).concat2().and_then(move |bytes| { - let mut buf = bytes.into_buf(); - let compressed_byte = buf.get_u8(); - if compressed_byte == 1 { - println!("compression not supported"); - let body = HelloBody::unimplemented(); - let rsp = rsp.body(body).unwrap(); - return Ok(rsp); - } else if compressed_byte != 0 { - println!("grpc header looked busted"); - let body = HelloBody::internal(); - let rsp = rsp.body(body).unwrap(); - return Ok(rsp); - } - - let len = buf.get_u32::() as usize; - - if buf.remaining() != len { - println!("delimited message claims len={}, but body={}", len, buf.remaining()); - let body = HelloBody::internal(); - let rsp = rsp.body(body).unwrap(); - return Ok(rsp); - } - - let s = ::std::str::from_utf8(buf.bytes()).unwrap(); - println!("HelloRequest = {}:{:?}", len, s); - let reply = format!("Hello, {}", s); - let mut bytes = BytesMut::with_capacity(reply.len() + 5); - bytes.put_u8(0); - bytes.put_u32::(reply.len() as u32); - bytes.put_slice(reply.as_bytes()); - - let body = HelloBody::new(bytes.freeze()); - let rsp = rsp.body(body).unwrap(); - Ok(rsp) - })) - } -} - -#[derive(Debug)] -struct NewSvc; -impl NewService for NewSvc { - type Request = Request; - type Response = Response; - type Error = h2::Error; - type InitError = ::std::io::Error; - type Service = Svc; - type Future = future::FutureResult; - - fn new_service(&self) -> Self::Future { - future::ok(Svc) - } -} - -fn main() { - drop(env_logger::init()); - - let mut core = Core::new().unwrap(); - let reactor = core.handle(); - - let h2 = Server::new(NewSvc, Default::default(), reactor.clone()); - - let addr = "127.0.0.1:9888".parse().unwrap(); - let bind = TcpListener::bind(&addr, &reactor).expect("bind"); - - let serve = bind.incoming() - .fold((h2, reactor), |(h2, reactor), (sock, _)| { - if let Err(e) = sock.set_nodelay(true) { - return Err(e); - } - - let serve = h2.serve(sock); - reactor.spawn(serve.map_err(|e| error!("h2 error: {:?}", e))); - - Ok((h2, reactor)) - }); - - println!("Greeter listening on {}", addr); - core.run(serve).unwrap(); -} diff --git a/tower-grpc/examples/helloworld_server.rs b/tower-grpc/examples/helloworld_server.rs deleted file mode 100644 index f03b6a1b4..000000000 --- a/tower-grpc/examples/helloworld_server.rs +++ /dev/null @@ -1,299 +0,0 @@ -#![allow(unused_variables)] - -extern crate env_logger; -#[macro_use] -extern crate futures; -#[macro_use] -extern crate log; -#[macro_use] -extern crate prost_derive; -extern crate tokio_core; -extern crate tower; -extern crate tower_h2; -extern crate tower_grpc; - -use futures::{future, Future, Stream, Poll}; -use tokio_core::net::TcpListener; -use tokio_core::reactor::Core; -use tower::Service; -use tower_grpc::{Request, Response}; -use tower_h2::Server; - -#[derive(Clone, Debug)] -struct Greet; - -impl Service for Greet { - type Request = Request; - type Response = Response; - type Error = tower_grpc::Error; - type Future = future::FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(().into()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - let response = Response::new(HelloReply { - message: "Zomg, it works!".to_string(), - }); - - future::ok(response) - } -} - -pub fn main() { - let _ = ::env_logger::init(); - - let mut core = Core::new().unwrap(); - let reactor = core.handle(); - - let new_service = server::Greeter::new_service() - .say_hello(Greet) - ; - - let h2 = Server::new(new_service, Default::default(), reactor.clone()); - - let addr = "[::1]:50051".parse().unwrap(); - let bind = TcpListener::bind(&addr, &reactor).expect("bind"); - - let serve = bind.incoming() - .fold((h2, reactor), |(h2, reactor), (sock, _)| { - if let Err(e) = sock.set_nodelay(true) { - return Err(e); - } - - let serve = h2.serve(sock); - reactor.spawn(serve.map_err(|e| error!("h2 error: {:?}", e))); - - Ok((h2, reactor)) - }); - - core.run(serve).unwrap(); -} - -/// The request message containing the user's name. -#[derive(Clone, Debug, PartialEq, Message)] -pub struct HelloRequest { - #[prost(string, tag="1")] - pub name: String, -} - -/// The response message containing the greetings -#[derive(Clone, Debug, PartialEq, Message)] -pub struct HelloReply { - #[prost(string, tag="1")] - pub message: String, -} - -pub mod server { - use super::{HelloRequest, HelloReply}; - use ::tower_grpc::codegen::server::*; - - #[derive(Debug)] - pub struct Greeter - where SayHello: grpc::UnaryService, - { - say_hello: grpc::Grpc>>, - } - - impl Greeter> - { - pub fn new_service() -> greeter::NewService> { - greeter::NewService::new() - } - } - - impl Clone for Greeter - where SayHello: grpc::UnaryService, - { - fn clone(&self) -> Self { - Greeter { - say_hello: self.say_hello.clone(), - } - } - } - - // ===== impl Greeter service ===== - - impl tower::Service for Greeter - where SayHello: grpc::UnaryService, - { - type Request = http::Request<::tower_h2::RecvBody>; - type Response = http::Response>; - type Error = h2::Error; - type Future = greeter::ResponseFuture; - - fn poll_ready(&mut self) -> futures::Poll<(), Self::Error> { - // Always ready - Ok(().into()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - use self::greeter::Kind::*; - - println!("PATH={:?}", request.uri().path()); - - match request.uri().path() { - "/helloworld.Greeter/SayHello" => { - let response = self.say_hello.call(request); - greeter::ResponseFuture { kind: Ok(SayHello(response)) } - } - _ => { - greeter::ResponseFuture { kind: Err(grpc::Status::UNIMPLEMENTED) } - } - } - } - } - - pub mod greeter { - use ::tower_grpc::codegen::server::*; - use super::{Greeter, HelloRequest, HelloReply}; - use std::fmt; - - #[derive(Debug)] - pub struct NewService - where SayHello: grpc::UnaryService, - { - inner: Greeter, - } - - pub struct ResponseFuture - where SayHello: grpc::UnaryService, - { - pub(super) kind: Result>> as tower::Service>::Future>, grpc::Status>, - } - - pub struct ResponseBody - where SayHello: grpc::UnaryService, - { - kind: Result> as grpc::GrpcService>::ResponseStream>>, grpc::Status>, - } - - /// Enumeration of all the service methods - #[derive(Debug)] - pub(super) enum Kind { - SayHello(SayHello), - } - - impl NewService> - { - pub fn new() -> Self { - NewService { - inner: Greeter { - say_hello: grpc::Grpc::new(grpc::Unary::new(grpc::NotImplemented::new())), - }, - } - } - } - - impl NewService - where SayHello: grpc::UnaryService, - { - /// Set the `say_hello` method - pub fn say_hello(self, say_hello: T) -> NewService - where T: grpc::UnaryService, - { - let say_hello = grpc::Grpc::new(grpc::Unary::new(say_hello)); - - NewService { - inner: Greeter { - say_hello, - } - } - } - } - - impl tower::NewService for NewService - where SayHello: grpc::UnaryService, - { - type Request = http::Request<::tower_h2::RecvBody>; - type Response = http::Response>; - type Error = h2::Error; - type Service = Greeter; - type InitError = h2::Error; - type Future = futures::FutureResult; - - fn new_service(&self) -> Self::Future { - futures::ok(self.inner.clone()) - } - } - - impl futures::Future for ResponseFuture - where SayHello: grpc::UnaryService, - { - type Item = http::Response>; - type Error = h2::Error; - - fn poll(&mut self) -> futures::Poll { - use self::Kind::*; - - match self.kind { - Ok(SayHello(ref mut fut)) => { - let response = try_ready!(fut.poll()); - let (head, body) = response.into_parts(); - let body = ResponseBody { kind: Ok(SayHello(body)) }; - let response = http::Response::from_parts(head, body); - Ok(response.into()) - } - Err(ref status) => { - let body = ResponseBody { kind: Err(status.clone()) }; - Ok(grpc::Response::new(body).into_http().into()) - } - } - } - } - - impl fmt::Debug for ResponseFuture - where SayHello: grpc::UnaryService, - { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "ResponseFuture") - } - } - - impl ::tower_h2::Body for ResponseBody - where SayHello: grpc::UnaryService, - { - type Data = bytes::Bytes; - - fn is_end_stream(&self) -> bool { - use self::Kind::*; - - match self.kind { - Ok(SayHello(ref v)) => v.is_end_stream(), - Err(_) => true, - } - } - - fn poll_data(&mut self) -> futures::Poll, h2::Error> { - use self::Kind::*; - - match self.kind { - Ok(SayHello(ref mut v)) => v.poll_data(), - Err(_) => Ok(None.into()), - } - } - - fn poll_trailers(&mut self) -> futures::Poll, h2::Error> { - use self::Kind::*; - - match self.kind { - Ok(SayHello(ref mut v)) => v.poll_trailers(), - Err(ref status) => { - let mut map = http::HeaderMap::new(); - map.insert("grpc-status", status.to_header_value()); - Ok(Some(map).into()) - } - } - } - } - - impl fmt::Debug for ResponseBody - where SayHello: grpc::UnaryService, - { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "ResponseBody") - } - } - } -} diff --git a/tower-grpc/examples/routeguide_client.rs b/tower-grpc/examples/routeguide_client.rs deleted file mode 100644 index 242d8934e..000000000 --- a/tower-grpc/examples/routeguide_client.rs +++ /dev/null @@ -1,427 +0,0 @@ -#![allow(dead_code)] -#![allow(unused_imports)] -#![allow(unused_variables)] - -extern crate bytes; -extern crate env_logger; -extern crate futures; -extern crate http; -extern crate h2; -extern crate tokio_connect; -extern crate tokio_core; -extern crate tower; -extern crate tower_grpc; -extern crate tower_h2; - -use std::net::SocketAddr; - -use bytes::BytesMut; -use futures::{Future, Stream}; -use tokio_connect::Connect; -use tokio_core::net::TcpStream; -use tokio_core::reactor::{Core, Handle}; -use tower::{Service, NewService}; - -use self::routeguide::{GetFeature, ListFeatures, RouteGuide, Point, Feature, Rectangle, RouteNote}; - -// eventually generated? -mod routeguide { - use futures::{Future, Poll}; - use tower::Service; - use tower_grpc; - use tower_grpc::client::Codec; - - #[derive(Debug)] - pub struct Point { - pub latitude: i32, - pub longitude: i32, - } - - #[derive(Debug)] - pub struct Rectangle { - pub lo: Point, - pub hi: Point, - } - - #[derive(Debug)] - pub struct Feature { - pub name: String, - pub location: Point, - } - - #[derive(Debug)] - pub struct RouteSummary { - pub point_count: i32, - pub feature_count: i32, - pub distance: i32, - pub elapsed_time: i32, - } - - #[derive(Debug)] - pub struct RouteNote { - pub location: Point, - pub message: String, - } - - // the full "service" - - pub struct RouteGuide { - get_feature: GetFeatureRpc, - list_features: ListFeaturesRpc, - record_route: RecordRouteRpc, - route_chat: RouteChatRpc, - } - - impl - RouteGuide - where - GetFeatureRpc: Service< - Request=tower_grpc::Request, - Response=tower_grpc::Response, - >, - ListFeaturesRpc: Service< - Request=tower_grpc::Request, - Response=tower_grpc::Response, - >, - ListFeaturesStream: ::futures::Stream, - { - pub fn new(get_feature: GetFeatureRpc, list_features: ListFeaturesRpc, record_route: RecordRouteRpc, route_chat: RouteChatRpc) -> Self { - RouteGuide { - get_feature, - list_features, - record_route, - route_chat, - } - } - - pub fn get_feature(&mut self, req: Point) -> ::futures::future::Map) -> Feature> - { - let req = tower_grpc::Request::new("/routeguide.RouteGuide/GetFeature", req); - self.get_feature.call(req) - .map(|res| { - res.into_http().into_parts().1 - } as _) - } - - //TODO: should this return a Stream wrapping the future? - pub fn list_features(&mut self, req: Rectangle) -> ::futures::future::Map) -> ListFeaturesStream> - { - let req = tower_grpc::Request::new("/routeguide.RouteGuide/GetFeature", req); - self.list_features.call(req) - .map(|res| { - res.into_http().into_parts().1 - } as _) - } - } - - // rpc methods - - pub struct GetFeature { - service: S, - } - - - impl GetFeature - where - C: Codec, - S: Service< - Request=tower_grpc::Request< - tower_grpc::client::codec::Unary - >, - Response=tower_grpc::Response< - tower_grpc::client::codec::DecodingBody - >, - Error=tower_grpc::Error - >, - { - pub fn new(service: S) -> Self { - GetFeature { - service, - } - } - } - - impl Service for GetFeature - where - C: Codec, - S: Service< - Request=tower_grpc::Request< - tower_grpc::client::codec::Unary - >, - Response=tower_grpc::Response< - tower_grpc::client::codec::DecodingBody - >, - Error=tower_grpc::Error - >, - { - type Request = tower_grpc::Request; - type Response = tower_grpc::Response; - type Error = S::Error; - type Future = tower_grpc::client::Unary; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.service.poll_ready() - } - - fn call(&mut self, req: Self::Request) -> Self::Future { - let fut = self.service.call(req.into_unary()); - tower_grpc::client::Unary::map_future(fut) - } - } - - pub struct ListFeatures { - service: S, - } - - impl ListFeatures - where - C: Codec, - S: Service< - Request=tower_grpc::Request< - tower_grpc::client::codec::Unary - >, - Response=tower_grpc::Response< - tower_grpc::client::codec::DecodingBody - >, - Error=tower_grpc::Error - >, - { - pub fn new(service: S) -> Self { - ListFeatures { - service, - } - } - } - - impl Service for ListFeatures - where - C: Codec, - S: Service< - Request=tower_grpc::Request< - tower_grpc::client::codec::Unary - >, - Response=tower_grpc::Response< - tower_grpc::client::codec::DecodingBody - >, - Error=tower_grpc::Error - >, - { - type Request = tower_grpc::Request; - type Response = tower_grpc::Response>; - type Error = S::Error; - type Future = S::Future; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.service.poll_ready() - } - - fn call(&mut self, req: Self::Request) -> Self::Future { - self.service.call(req.into_unary()) - } - } - - pub struct RecordRoute { - service: S, - } - - pub struct RouteChat { - service: S, - } -} - -pub struct StupidCodec(::std::marker::PhantomData<(T, U)>); - -impl StupidCodec { - fn new() -> Self { - StupidCodec(::std::marker::PhantomData) - } -} - -impl Clone for StupidCodec { - fn clone(&self) -> Self { - StupidCodec(::std::marker::PhantomData) - } -} - -impl tower_grpc::client::Codec for StupidCodec { - const CONTENT_TYPE: &'static str = "application/proto+stupid"; - - type Encode = Point; - type Decode = Feature; - type EncodeError = (); - type DecodeError = (); - - fn encode(&mut self, msg: Self::Encode, buf: &mut tower_grpc::client::codec::EncodeBuf) -> Result<(), Self::EncodeError> { - Ok(()) - } - - fn decode(&mut self, buf: &mut tower_grpc::client::codec::DecodeBuf) -> Result { - Ok(Feature { - name: String::from("faked"), - location: Point { - longitude: 5, - latitude: 5, - } - }) - } -} - -impl tower_grpc::client::Codec for StupidCodec { - const CONTENT_TYPE: &'static str = "application/proto+stupid"; - - type Encode = Rectangle; - type Decode = Feature; - type EncodeError = (); - type DecodeError = (); - - fn encode(&mut self, msg: Self::Encode, buf: &mut tower_grpc::client::codec::EncodeBuf) -> Result<(), Self::EncodeError> { - Ok(()) - } - - fn decode(&mut self, buf: &mut tower_grpc::client::codec::DecodeBuf) -> Result { - Ok(Feature { - name: String::from("faked"), - location: Point { - longitude: 5, - latitude: 5, - } - }) - } -} - -struct Conn(SocketAddr, Handle); - -impl Connect for Conn { - type Connected = TcpStream; - type Error = ::std::io::Error; - type Future = Box>; - - fn connect(&self) -> Self::Future { - let c = TcpStream::connect(&self.0, &self.1) - .and_then(|tcp| tcp.set_nodelay(true).map(move |_| tcp)); - Box::new(c) - } -} - -struct AddOrigin(S); - -impl Service for AddOrigin -where - S: Service>, -{ - type Request = S::Request; - type Response = S::Response; - type Error = S::Error; - type Future = S::Future; - - fn poll_ready(&mut self) -> ::futures::Poll<(), Self::Error> { - self.0.poll_ready() - } - - fn call(&mut self, mut req: Self::Request) -> Self::Future { - use std::str::FromStr; - //TODO: use Uri.into_parts() to be more efficient - let full_uri = format!("http://127.0.0.1:8888{}", req.uri().path()); - let new_uri = http::Uri::from_str(&full_uri).expect("example uri should work"); - *req.uri_mut() = new_uri; - self.0.call(req) - } -} - -fn main() { - drop(env_logger::init()); - - let mut core = Core::new().unwrap(); - let reactor = core.handle(); - - let addr = "[::1]:8888".parse().unwrap(); - - - let conn = Conn(addr, reactor.clone()); - let h2 = tower_h2::Client::new(conn, Default::default(), reactor); - - let done = h2.new_service() - .map_err(|_e| unimplemented!("h2 new_service error")) - .and_then(move |orig_service| { - - let service = AddOrigin(orig_service.clone_handle()); - let grpc = tower_grpc::Client::new(StupidCodec::::new(), service); - let get_feature = GetFeature::new(grpc); - - - let service = AddOrigin(orig_service); - let grpc = tower_grpc::Client::new(StupidCodec::::new(), service); - let list_features = ListFeatures::new(grpc); - - let mut client = RouteGuide::new(get_feature, list_features, (), ()); - - let valid_feature = client.get_feature(Point { - latitude: 409146138, - longitude: -746188906, - }).map(|feature| { - println!("GetFeature: {:?}", feature); - }).map_err(|e| ("GetFeature", e)); - - let missing_feature = client.get_feature(Point { - latitude: 0, - longitude: 0, - }).map(|feature| { - println!("GetFeature: {:?}", feature); - }).map_err(|e| ("GetFeature", e)); - - let features_between = client.list_features(Rectangle { - lo: Point { - latitude: 400000000, - longitude: -750000000, - }, - hi: Point { - latitude: 420000000, - longitude: -730000000, - } - }).and_then(|features| { - features.for_each(|feature| { - println!("ListFeatures: {:?}", feature); - Ok(()) - }).map_err(|e| match e { - tower_grpc::Error::Inner(h2) => tower_grpc::Error::Inner(h2.into()), - tower_grpc::Error::Grpc(status) => tower_grpc::Error::Grpc(status), - }) - }).map_err(|e| ("ListFeatures", e)); - - /* - let record_route = client.record_route(futures::stream::iter_ok::<_, ()>(vec![ - Point { - longitude: 1, - latitude: 1, - }, - Point { - longitude: 2, - latitude: 2, - }, - ])).map(|summary| { - println!("RecordRoute: {:?}", summary); - }).map_err(|e| ("RecordRoute", e)); - - let route_chat = client.route_chat(futures::stream::iter_ok::<_, ()>(vec![ - RouteNote { - location: Point { - longitude: 55, - latitude: 55, - }, - message: "First note".to_string(), - }, - ])).for_each(|_| { - Ok(()) - }).map_err(|e| ("RouteChat", e)); - */ - - valid_feature - .join(missing_feature) - //.join(features_between) - //.join(record_route) - //.join(route_chat) - }) - .map_err(|e| println!("error: {:?}", e)); - - let _ = core.run(done); -} diff --git a/tower-grpc/examples/routeguide_server.rs b/tower-grpc/examples/routeguide_server.rs deleted file mode 100644 index 3aee9b8d4..000000000 --- a/tower-grpc/examples/routeguide_server.rs +++ /dev/null @@ -1,158 +0,0 @@ -extern crate bytes; -extern crate env_logger; -extern crate futures; -extern crate h2; -extern crate http; -#[macro_use] -extern crate log; -extern crate tokio_core; -extern crate tower; -extern crate tower_h2; - -use bytes::Bytes; -use futures::*; -use http::{Request, HeaderMap}; -use http::header::HeaderValue; -use tokio_core::net::TcpListener; -use tokio_core::reactor::Core; -use tower::{NewService, Service}; -use tower_h2::{Body, Data, Server, RecvBody}; - -type Response = http::Response; - -struct GrpcBody { - message: Bytes, - status: &'static str, -} - -impl GrpcBody { - fn new(body: Bytes) -> Self { - GrpcBody { - message: body, - status: "0", - } - } - - fn unimplemented() -> Self { - GrpcBody { - message: Bytes::new(), - status: "12", - } - } -} - - -impl Body for GrpcBody { - type Data = Bytes; - - fn poll_data(&mut self) -> Poll, h2::Error> { - let data = self.message.split_off(0); - let data = if data.is_empty() { - None - } else { - Some(data) - }; - - Ok(Async::Ready(data)) - } - - fn poll_trailers(&mut self) -> Poll, h2::Error> { - let mut map = HeaderMap::new(); - map.insert("grpc-status", HeaderValue::from_static(self.status)); - Ok(Async::Ready(Some(map))) - } -} - -struct RecvBodyStream(tower_h2::RecvBody); - -impl Stream for RecvBodyStream { - type Item = Data; - type Error = h2::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - self.0.poll_data() - } -} - -const GET_FEATURE: &'static str = "/routeguide.RouteGuide/GetFeature"; - -#[derive(Debug)] -struct Svc; -impl Service for Svc { - type Request = Request; - type Response = Response; - type Error = h2::Error; - type Future = Box>; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(Async::Ready(())) - } - - fn call(&mut self, req: Request) -> Self::Future { - let mut rsp = http::Response::builder(); - rsp.version(http::Version::HTTP_2); - - let (head, body) = req.into_parts(); - match head.uri.path() { - GET_FEATURE => { - let body = RecvBodyStream(body); - - // TODO: This is not great flow control management - Box::new(body.map(Bytes::from).concat2().and_then(move |bytes| { - let s = ::std::str::from_utf8(&bytes).unwrap(); - println!("GetFeature = {:?}", s); - let body = GrpcBody::new("blah".into()); - let rsp = rsp.body(body).unwrap(); - Ok(rsp) - })) - }, - _ => { - println!("unknown route"); - let body = GrpcBody::unimplemented(); - let rsp = rsp.body(body).unwrap(); - Box::new(future::ok(rsp)) - } - } - } -} - -#[derive(Debug)] -struct NewSvc; -impl NewService for NewSvc { - type Request = Request; - type Response = Response; - type Error = h2::Error; - type InitError = ::std::io::Error; - type Service = Svc; - type Future = future::FutureResult; - - fn new_service(&self) -> Self::Future { - future::ok(Svc) - } -} - -fn main() { - drop(env_logger::init()); - - let mut core = Core::new().unwrap(); - let reactor = core.handle(); - - let h2 = Server::new(NewSvc, Default::default(), reactor.clone()); - - let addr = "[::1]:8888".parse().unwrap(); - let bind = TcpListener::bind(&addr, &reactor).expect("bind"); - - let serve = bind.incoming() - .fold((h2, reactor), |(h2, reactor), (sock, _)| { - if let Err(e) = sock.set_nodelay(true) { - return Err(e); - } - - let serve = h2.serve(sock); - reactor.spawn(serve.map_err(|e| error!("h2 error: {:?}", e))); - - Ok((h2, reactor)) - }); - - core.run(serve).unwrap(); -} diff --git a/tower-grpc/src/client/codec.rs b/tower-grpc/src/client/codec.rs deleted file mode 100644 index b40f6a97e..000000000 --- a/tower-grpc/src/client/codec.rs +++ /dev/null @@ -1,383 +0,0 @@ -use std::collections::VecDeque; - -use bytes::{Buf, BufMut, Bytes, BytesMut, BigEndian}; -use futures::{Async, Stream, Poll}; -use h2; -use http::header::HeaderMap; -use tower_h2::{self, Body, Data, RecvBody}; - -use ::Status; -use super::check_grpc_status; - -/// A type used to encode and decode for a single RPC method. -pub trait Codec: Clone { - /// The content-type header for messages using this encoding. - /// - /// Should be `application/grpc+yourencoding`. - const CONTENT_TYPE: &'static str; - - /// The message to encode into bytes. - type Encode; - /// The message to decode from bytes. - type Decode; - /// An error that could occur during encoding. - type EncodeError; - /// An error that could occur during decoding. - type DecodeError; - - /// Encode a message into the provided buffer. - fn encode(&mut self, item: Self::Encode, buf: &mut EncodeBuf) -> Result<(), Self::EncodeError>; - - /// Decode a message from the buffer. - /// - /// The buffer will contain exactly the bytes of a full message. There - /// is no need to get the length from the bytes, gRPC framing is handled - /// for you. - fn decode(&mut self, buf: &mut DecodeBuf) -> Result; -} - -/// A buffer to encode a message into. -#[derive(Debug)] -pub struct EncodeBuf<'a> { - pub(crate) bytes: &'a mut BytesMut, -} - -/// A buffer to decode messages from. -#[derive(Debug)] -pub struct DecodeBuf<'a> { - pub(crate) bufs: &'a mut BytesList, - pub(crate) len: usize, -} - -/// A mapping of a stream of encodable items to a stream of bytes. -#[must_use = "futures do nothing unless polled"] -#[derive(Debug)] -pub struct EncodingBody { - buf: BytesMut, - encoder: E, - stream: S, -} - -#[must_use = "futures do nothing unless polled"] -#[derive(Debug)] -pub struct DecodingBody { - bufs: BytesList, - decoder: D, - state: DecodingState, - stream: RecvBody, -} - -#[derive(Debug)] -enum DecodingState { - ReadHeader, - ReadBody { - compression: bool, - len: usize, - }, - Trailers, - Done, -} - -#[derive(Debug)] -pub(crate) struct BytesList { - pub(crate) bufs: VecDeque, -} - -impl<'a> EncodeBuf<'a> { - #[inline] - pub fn reserve(&mut self, capacity: usize) { - self.bytes.reserve(capacity); - } -} - -impl<'a> BufMut for EncodeBuf<'a> { - #[inline] - fn remaining_mut(&self) -> usize { - self.bytes.remaining_mut() - } - - #[inline] - unsafe fn advance_mut(&mut self, cnt: usize) { - self.bytes.advance_mut(cnt) - } - - #[inline] - unsafe fn bytes_mut(&mut self) -> &mut [u8] { - self.bytes.bytes_mut() - } -} - -impl<'a> Buf for DecodeBuf<'a> { - #[inline] - fn remaining(&self) -> usize { - self.len - } - - #[inline] - fn bytes(&self) -> &[u8] { - &self.bufs.bytes()[..self.len] - } - - #[inline] - fn advance(&mut self, cnt: usize) { - assert!(cnt <= self.len); - self.bufs.advance(cnt); - self.len -= cnt; - } -} - -impl<'a> Drop for DecodeBuf<'a> { - fn drop(&mut self) { - if self.len > 0 { - warn!("DecodeBuf was not advanced to end"); - self.bufs.advance(self.len); - } - } -} - -impl Buf for BytesList { - #[inline] - fn remaining(&self) -> usize { - self.bufs.iter().map(|buf| buf.remaining()).sum() - } - - #[inline] - fn bytes(&self) -> &[u8] { - if self.bufs.is_empty() { - &[] - } else { - &self.bufs[0].bytes() - } - } - - #[inline] - fn advance(&mut self, mut cnt: usize) { - while cnt > 0 { - { - let front = &mut self.bufs[0]; - if front.remaining() > cnt { - front.advance(cnt); - return; - } else { - cnt -= front.remaining(); - } - } - self.bufs.pop_front(); - } - } -} - -impl EncodingBody { - pub(crate) fn new(encoder: E, stream: S) -> Self { - EncodingBody { - buf: BytesMut::new(), - encoder, - stream, - } - } -} - -impl tower_h2::Body for EncodingBody -where - S: Stream, - E: Codec, -{ - type Data = Bytes; - - fn is_end_stream(&self) -> bool { - false - } - - fn poll_data(&mut self) -> Poll, h2::Error> { - let item = try_ready!(self.stream.poll().map_err(|_| h2_err())); - if let Some(item) = item { - self.buf.reserve(5); - unsafe { self.buf.advance_mut(5); } - self.encoder.encode(item, &mut EncodeBuf { - bytes: &mut self.buf, - }).map_err(|_| h2_err())?; - - // now that we know length, we can write the header - let len = self.buf.len() - 5; - assert!(len <= ::std::u32::MAX as usize); - { - let mut cursor = ::std::io::Cursor::new(&mut self.buf[..5]); - cursor.put_u8(0); // byte must be 0, reserve doesn't auto-zero - cursor.put_u32::(len as u32); - } - - Ok(Async::Ready(Some(self.buf.split_to(len + 5).freeze()))) - } else { - Ok(Async::Ready(None)) - } - } -} - -fn grpc_status(trailers: &HeaderMap) -> Result<(), Status> { - match check_grpc_status(&trailers) { - Some(status) => if status.code() == ::Code::OK { - Ok(()) - } else { - Err(status) - } - None => { - trace!("trailers missing grpc-status"); - Err(Status::UNKNOWN) - } - } -} - - -impl DecodingBody -where - D: Codec, -{ - pub(crate) fn new(decoder: D, stream: RecvBody) -> Self { - DecodingBody { - bufs: BytesList { - bufs: VecDeque::new(), - }, - decoder, - state: DecodingState::ReadHeader, - stream, - } - } - - fn decode(&mut self) -> Result, Status> { - if let DecodingState::ReadHeader = self.state { - if self.bufs.remaining() < 5 { - return Ok(None); - } - - let is_compressed = match self.bufs.get_u8() { - 0 => false, - 1 => { - trace!("message compressed, compression not supported yet"); - return Err(Status::UNIMPLEMENTED); - }, - _ => { - trace!("unexpected compression flag"); - return Err(Status::UNKNOWN); - } - }; - let len = self.bufs.get_u32::() as usize; - - self.state = DecodingState::ReadBody { - compression: is_compressed, - len, - } - } - - if let DecodingState::ReadBody { len, .. } = self.state { - if self.bufs.remaining() < len { - return Ok(None); - } - - match self.decoder.decode(&mut DecodeBuf { - bufs: &mut self.bufs, - len, - }) { - Ok(msg) => { - self.state = DecodingState::ReadHeader; - return Ok(Some(msg)); - }, - Err(_) => { - debug!("decoder error"); - return Err(Status::UNKNOWN); - } - } - } - - Ok(None) - } - - fn poll_inner(&mut self) -> Poll, ::Error> { - loop { - match self.state { - DecodingState::Trailers | DecodingState::Done => break, - _ => (), - } - - match self.decode() { - Ok(Some(val)) => return Ok(Async::Ready(Some(val))), - Ok(None) => (), - Err(status) => return Err(::Error::Grpc(status)), - } - - let chunk = try_ready!(self.stream.poll_data()); - - if let Some(data) = chunk { - self.bufs.bufs.push_back(data); - } else { - if self.bufs.has_remaining() { - trace!("unexpected EOF decoding stream"); - return Err(::Error::Grpc(Status::UNKNOWN)) - } else { - self.state = DecodingState::Trailers; - break; - } - } - } - - if let DecodingState::Trailers = self.state { - return if let Some(trailers) = try_ready!(self.stream.poll_trailers()) { - grpc_status(&trailers).map_err(::Error::Grpc)?; - self.state = DecodingState::Done; - Ok(Async::Ready(None)) - } else { - trace!("receive body ended without trailers"); - Err(::Error::Grpc(Status::UNKNOWN)) - } - } - Ok(Async::Ready(None)) - } -} - -impl Stream for DecodingBody -where - D: Codec, -{ - type Item = D::Decode; - type Error = ::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - self.poll_inner() - .map_err(|err| { - self.state = DecodingState::Done; - err - }) - } -} - -fn h2_err() -> h2::Error { - unimplemented!("EncodingBody map_err") -} - -/// Wraps a message to provide a `Stream` of just one item. -#[must_use = "futures do nothing unless polled"] -#[derive(Debug)] -pub struct Unary { - item: Option, -} - -impl Unary { - pub fn new(item: T) -> Self { - Unary { - item: Some(item), - } - } -} - -impl Stream for Unary { - type Item = T; - type Error = self::inner::Void; - - fn poll(&mut self) -> Poll, Self::Error> { - Ok(Async::Ready(self.item.take())) - } -} - -mod inner { - pub struct Void(Void_); - enum Void_ {} -} diff --git a/tower-grpc/src/client/mod.rs b/tower-grpc/src/client/mod.rs deleted file mode 100644 index a8ce44288..000000000 --- a/tower-grpc/src/client/mod.rs +++ /dev/null @@ -1,260 +0,0 @@ -pub mod codec; - -use futures::{Async, Future, Poll, Stream}; -use http; -use http::header::{HeaderMap, HeaderValue}; -use tower::Service; -use tower_h2::RecvBody; - -pub use self::codec::Codec; - -use self::codec::{DecodingBody, EncodingBody}; -use ::Status; - -/// A gRPC client wrapping a `Service` over `h2`. -#[derive(Debug)] -pub struct Client { - codec: C, - service: S, -} - -#[must_use = "futures do nothing unless polled"] -#[derive(Debug)] -pub struct ResponseFuture { - decoder: Option, - future: F, -} - -/// Future mapping Response into B. -#[must_use = "futures do nothing unless polled"] -#[derive(Debug)] -pub struct BodyFuture { - future: F, -} - -#[must_use = "futures do nothing unless polled"] -#[derive(Debug)] -pub struct Unary where D: Codec { - body: Option>, - future: F, - head: Option, - message: Option, -} - -/// A stream of a future Response's body items. -#[must_use = "streams do nothing unless polled"] -#[derive(Debug)] -pub struct Streaming { - body: Option, - future: F, -} - -// ====== impl Client ===== - -impl Client { - /// Create a new `Client` over an h2 service. - pub fn new(codec: C, service: S) -> Self { - Client { - codec, - service, - } - } -} - -impl Service for Client -where - C: Codec, - S: Service>, Response=http::Response>, - R: Stream, -{ - type Request = ::Request; - type Response = ::Response>; - type Error = ::Error; - type Future = ResponseFuture; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.service.poll_ready() - .map_err(::Error::Inner) - } - - fn call(&mut self, req: Self::Request) -> Self::Future { - let http = req.into_http(); - let (mut head, body) = http.into_parts(); - - // gRPC headers - head.headers.insert(http::header::TE, HeaderValue::from_static("trailers")); - - let content_type = HeaderValue::from_static(C::CONTENT_TYPE); - head.headers.insert(http::header::CONTENT_TYPE, content_type); - - let encoded = EncodingBody::new(self.codec.clone(), body); - let req = http::Request::from_parts(head, encoded); - let fut = self.service.call(req); - - ResponseFuture { - decoder: Some(self.codec.clone()), - future: fut, - } - } -} - -// ====== impl ResponseFuture ===== - -impl Future for ResponseFuture -where - D: Codec, - F: Future>, -{ - type Item = ::Response>; - type Error = ::Error; - - fn poll(&mut self) -> Poll { - let res = try_ready!(self.future.poll().map_err(::Error::Inner)); - let (head, body) = res.into_parts(); - - if let Some(status) = check_grpc_status(&head.headers) { - return Err(::Error::Grpc(status)); - } - - let decoded = DecodingBody::new(self.decoder.take().unwrap(), body); - let res = http::Response::from_parts(head, decoded); - let grpc = ::Response::from_http(res); - Ok(Async::Ready(grpc)) - } -} - -// ====== impl Unary ===== - -impl Unary -where - D: Codec, -{ - pub fn map_future(future: F) -> Self { - Unary { - body: None, - future, - head: None, - message: None, - } - } -} - -impl Future for Unary -where - F: Future>, Error=::Error>, - D: Codec, -{ - type Item = ::Response; - type Error = ::Error; - - fn poll(&mut self) -> Poll { - let ref mut body = match self.body { - Some(ref mut body) => body, - None => { - let resp = try_ready!(self.future.poll()).into_http(); - let (head, body) = resp.into_parts(); - self.head = Some(head); - self.body = Some(body); - self.body.as_mut().unwrap() - } - }; - - loop { - let message = try_ready!(body.poll() - .map_err(|e| match e { - ::Error::Inner(h2) => ::Error::Grpc(::Status::from(h2)), - ::Error::Grpc(err) => ::Error::Grpc(err), - })); - - match (self.message.is_some(), message) { - (false, Some(msg)) => { - self.message = Some(msg); - continue; - }, - (true, None) => { - let head = self.head.take().expect("polled more than once"); - let body = self.message.take().expect("polled more than once"); - let http = http::Response::from_parts(head, body); - let resp = ::Response::from_http(http); - return Ok(Async::Ready(resp)); - } - (true, Some(_)) => { - debug!("Unary decoder found 2 messages"); - return Err(::Error::Grpc(Status::UNKNOWN)); - } - (false, None) => { - debug!("Unary decoder ended before any messages"); - return Err(::Error::Grpc(Status::UNKNOWN)); - } - } - } - } -} - -// ====== impl Stream ===== - -impl Streaming -where - F: Future>, - B: Stream>, -{ - pub fn map_future(future: F) -> Self { - Streaming { - body: None, - future, - } - } -} - -impl Stream for Streaming -where - F: Future, Error=::Error>, - B: Stream>, -{ - type Item = B::Item; - type Error = ::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - loop { - if let Some(ref mut body) = self.body { - return body.poll().map_err(|e| match e { - ::Error::Inner(h2) => ::Error::Grpc(::Status::from(h2)), - ::Error::Grpc(err) => ::Error::Grpc(err), - }); - } else { - let res = try_ready!(self.future.poll()); - self.body = Some(res.into_http().into_parts().1); - } - } - } -} - -// ====== impl BodyFuture ===== - -impl BodyFuture { - /// Wrap the future. - pub fn new(fut: F) -> Self { - BodyFuture { - future: fut, - } - } -} - -impl Future for BodyFuture -where - F: Future>, -{ - type Item = B; - type Error = F::Error; - - fn poll(&mut self) -> Poll { - let res = try_ready!(self.future.poll()); - Ok(Async::Ready(res.into_http().into_parts().1)) - } -} - -fn check_grpc_status(trailers: &HeaderMap) -> Option { - trailers.get("grpc-status").map(|s| { - Status::from_bytes(s.as_ref()) - }) -} diff --git a/tower-grpc/src/error.rs b/tower-grpc/src/error.rs deleted file mode 100644 index 3622b5e84..000000000 --- a/tower-grpc/src/error.rs +++ /dev/null @@ -1,27 +0,0 @@ -use h2; - -#[derive(Debug)] -pub enum Error { - Grpc(::Status), - Inner(T), -} - -impl From for Error { - fn from(inner: T) -> Self { - Error::Inner(inner) - } -} - -impl From> for h2::Error { - fn from(_err: Error<()>) -> Self { - // TODO: implement - h2::Reason::INTERNAL_ERROR.into() - } -} - -impl From for Error<()> { - fn from(_: h2::Error) -> Self { - // TODO: implement - Error::Inner(()) - } -} diff --git a/tower-grpc/src/lib.rs b/tower-grpc/src/lib.rs deleted file mode 100644 index 833fb1d26..000000000 --- a/tower-grpc/src/lib.rs +++ /dev/null @@ -1,89 +0,0 @@ -#![deny(warnings)] -//#![deny(missing_docs)] -//#![deny(missing_debug_implementations)] - -extern crate bytes; -#[macro_use] extern crate futures; -extern crate http; -extern crate h2; -#[macro_use] extern crate log; -extern crate tower; -extern crate tower_h2; - -#[cfg(feature = "protobuf")] -extern crate prost; - -pub mod client; -pub mod server; - -#[cfg(feature = "protobuf")] -pub mod protobuf; - -mod error; -mod request; -mod response; -mod status; - -pub use self::client::Client; -pub use self::error::Error; -pub use self::status::{Code, Status}; -pub use self::request::Request; -pub use self::response::Response; - -/// Type re-exports used by generated code -pub mod codegen { - /// Type re-exports used by generated server code - pub mod server { - /// Re-export types from this crate - pub mod grpc { - pub use ::{Request, Response, Error, Status}; - pub use ::server::{ - unary, - Unary, - ClientStreaming, - ServerStreaming, - NotImplemented, - }; - pub use ::protobuf::server::{ - Grpc, - GrpcService, - UnaryService, - ClientStreamingService, - ServerStreamingService, - Encode, - Decode, - }; - } - - /// Re-export types from the `bytes` crate. - pub mod bytes { - pub use ::bytes::Bytes; - } - - /// Re-export types from the `future` crate. - pub mod futures { - pub use ::futures::{Future, Poll, Async}; - pub use ::futures::future::{FutureResult, ok}; - } - - /// Re-exported types from the `http` crate. - pub mod http { - pub use ::http::{Request, Response, HeaderMap}; - } - - /// Re-exported types from the `h2` crate. - pub mod h2 { - pub use ::h2::Error; - } - - /// Re-export types from the `tower_h2` crate - pub mod tower_h2 { - pub use ::tower_h2::{Body, RecvBody}; - } - - /// Re-exported types from the `tower` crate. - pub mod tower { - pub use ::tower::{Service, NewService}; - } - } -} diff --git a/tower-grpc/src/protobuf/mod.rs b/tower-grpc/src/protobuf/mod.rs deleted file mode 100644 index ec982d28b..000000000 --- a/tower-grpc/src/protobuf/mod.rs +++ /dev/null @@ -1,433 +0,0 @@ -use client::codec::{EncodeBuf, DecodeBuf}; - -use bytes::{BufMut}; -use prost::Message; - -use ::std::marker::PhantomData; - -/// Protobuf codec -#[derive(Debug)] -pub struct Codec(PhantomData<(T, U)>); - -#[derive(Debug)] -pub struct Encoder(PhantomData); - -#[derive(Debug)] -pub struct Decoder(PhantomData); - -/// Protobuf gRPC type aliases -pub mod server { - use {Request, Response}; - - use futures::{Future, Stream, Poll}; - use {h2, http}; - use tower::Service; - - /// A specialization of tower::Service. - /// - /// Existing tower::Service implementations with the correct form will - /// automatically implement `GrpcService`. - /// - /// TODO: Rename to StreamingService? - pub trait GrpcService: Clone { - /// Protobuf request message type - type Request; - - /// Stream of inbound request messages - type RequestStream: Stream; - - /// Protobuf response message type - type Response; - - /// Stream of outbound response messages - type ResponseStream: Stream; - - /// Response future - type Future: Future, Error = ::Error>; - - /// Returns `Ready` when the service can accept a request - fn poll_ready(&mut self) -> Poll<(), ::Error>; - - /// Call the service - fn call(&mut self, request: Request) -> Self::Future; - } - - impl GrpcService for T - where T: Service, - Response = Response, - Error = ::Error> + Clone, - S1: Stream, - S2: Stream, - { - type Request = S1::Item; - type RequestStream = S1; - type Response = S2::Item; - type ResponseStream = S2; - type Future = T::Future; - - fn poll_ready(&mut self) -> Poll<(), ::Error> { - Service::poll_ready(self) - } - - fn call(&mut self, request: T::Request) -> Self::Future { - Service::call(self, request) - } - } - - /// A specialization of tower::Service. - /// - /// Existing tower::Service implementations with the correct form will - /// automatically implement `UnaryService`. - pub trait UnaryService: Clone { - /// Protobuf request message type - type Request; - - /// Protobuf response message type - type Response; - - /// Response future - type Future: Future, Error = ::Error>; - - /// Returns `Ready` when the service can accept a request - fn poll_ready(&mut self) -> Poll<(), ::Error>; - - /// Call the service - fn call(&mut self, request: Request) -> Self::Future; - } - - impl UnaryService for T - where T: Service, - Response = Response, - Error = ::Error> + Clone, - { - type Request = M1; - type Response = M2; - type Future = T::Future; - - fn poll_ready(&mut self) -> Poll<(), ::Error> { - Service::poll_ready(self) - } - - fn call(&mut self, request: T::Request) -> Self::Future { - Service::call(self, request) - } - } - - /// A specialization of tower::Service. - /// - /// Existing tower::Service implementations with the correct form will - /// automatically implement `UnaryService`. - pub trait ClientStreamingService: Clone { - /// Protobuf request message type - type Request; - - /// Stream of inbound request messages - type RequestStream: Stream; - - /// Protobuf response message type - type Response; - - /// Response future - type Future: Future, Error = ::Error>; - - /// Returns `Ready` when the service can accept a request - fn poll_ready(&mut self) -> Poll<(), ::Error>; - - /// Call the service - fn call(&mut self, request: Request) -> Self::Future; - } - - impl ClientStreamingService for T - where T: Service, - Response = Response, - Error = ::Error> + Clone, - S: Stream, - { - type Request = S::Item; - type RequestStream = S; - type Response = M; - type Future = T::Future; - - fn poll_ready(&mut self) -> Poll<(), ::Error> { - Service::poll_ready(self) - } - - fn call(&mut self, request: T::Request) -> Self::Future { - Service::call(self, request) - } - } - - /// A specialization of tower::Service. - /// - /// Existing tower::Service implementations with the correct form will - /// automatically implement `UnaryService`. - pub trait ServerStreamingService: Clone { - /// Protobuf request message type - type Request; - - /// Protobuf response message type - type Response; - - /// Stream of outbound response messages - type ResponseStream: Stream; - - /// Response future - type Future: Future, Error = ::Error>; - - /// Returns `Ready` when the service can accept a request - fn poll_ready(&mut self) -> Poll<(), ::Error>; - - /// Call the service - fn call(&mut self, request: Request) -> Self::Future; - } - - impl ServerStreamingService for T - where T: Service, - Response = Response, - Error = ::Error> + Clone, - S: Stream, - { - type Request = M; - type Response = S::Item; - type ResponseStream = S; - type Future = T::Future; - - fn poll_ready(&mut self) -> Poll<(), ::Error> { - Service::poll_ready(self) - } - - fn call(&mut self, request: T::Request) -> Self::Future { - Service::call(self, request) - } - } - - #[derive(Debug)] - pub struct Grpc - where T: GrpcService, - { - inner: ::server::Grpc, ::protobuf::Codec>, - } - - #[derive(Debug)] - pub struct ResponseFuture - where T: GrpcService, - { - inner: ::server::streaming::ResponseFuture>, - } - - /// A protobuf encoded gRPC request stream - #[derive(Debug)] - pub struct Decode { - inner: ::server::Decode<::protobuf::Decoder>, - } - - /// A protobuf encoded gRPC response body - pub struct Encode - where T: Stream, - { - inner: ::server::Encode>, - } - - // ===== impl Grpc ===== - - impl Grpc - where T: GrpcService>, - T::Request: ::prost::Message + Default, - T::Response: ::prost::Message, - { - pub fn new(inner: T) -> Self { - let inner = ::server::Grpc::new(Wrap(inner), ::protobuf::Codec::new()); - Grpc { inner } - } - } - - impl Service for Grpc - where T: GrpcService>, - T::Request: ::prost::Message + Default, - T::Response: ::prost::Message, - { - type Request = ::http::Request<::tower_h2::RecvBody>; - type Response = ::http::Response>; - type Error = ::h2::Error; - type Future = ResponseFuture; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.inner.poll_ready() - .map_err(Into::into) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - let inner = self.inner.call(request); - ResponseFuture { inner } - } - } - - impl Clone for Grpc - where T: GrpcService + Clone, - { - fn clone(&self) -> Self { - let inner = self.inner.clone(); - Grpc { inner } - } - } - - // ===== impl ResponseFuture ===== - - impl Future for ResponseFuture - where T: GrpcService, - T::Response: ::prost::Message, - { - type Item = ::http::Response>; - type Error = ::h2::Error; - - fn poll(&mut self) -> Poll { - let response = try_ready!(self.inner.poll()); - let (head, inner) = response.into_parts(); - let body = Encode { inner }; - let response = ::http::Response::from_parts(head, body); - Ok(response.into()) - } - } - - // ===== impl Encode ===== - - impl ::tower_h2::Body for Encode - where T: Stream, - T::Item: ::prost::Message, - { - type Data = ::bytes::Bytes; - - fn is_end_stream(&self) -> bool { - false - } - - fn poll_data(&mut self) -> Poll, ::h2::Error> { - self.inner.poll_data() - } - - fn poll_trailers(&mut self) -> Poll, h2::Error> { - self.inner.poll_trailers() - } - } - - // ===== impl Decode ===== - - impl Stream for Decode - where T: ::prost::Message + Default, - { - type Item = T; - type Error = ::Error; - - fn poll(&mut self) -> Poll, ::Error> { - self.inner.poll() - } - } - - // ===== impl Wrap ===== - - #[derive(Debug, Clone)] - struct Wrap(T); - - impl Service for Wrap - where T: GrpcService>, - T::Request: ::prost::Message + Default, - T::Response: ::prost::Message, - { - type Request = Request<::server::Decode<::protobuf::Decoder>>; - type Response = Response; - type Error = ::Error; - type Future = T::Future; - - fn poll_ready(&mut self) -> Poll<(), ::Error> { - self.0.poll_ready() - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - let request = request.map(|inner| Decode { inner }); - self.0.call(request) - } - } -} - -// ===== impl Codec ===== - -impl Codec -where T: Message, - U: Message + Default, -{ - /// Create a new protobuf codec - pub fn new() -> Self { - Codec(PhantomData) - } -} - -impl ::server::Codec for Codec -where T: Message, - U: Message + Default, -{ - /// Protocol buffer gRPC content type - const CONTENT_TYPE: &'static str = "application/grpc+proto"; - - type Encode = T; - type Encoder = Encoder; - type Decode = U; - type Decoder = Decoder; - - fn encoder(&mut self) -> Self::Encoder { - Encoder(PhantomData) - } - - fn decoder(&mut self) -> Self::Decoder { - Decoder(PhantomData) - } -} - -impl Clone for Codec { - fn clone(&self) -> Self { - Codec(PhantomData) - } -} - -// ===== impl Encoder ===== - -impl ::server::Encoder for Encoder -where T: Message, -{ - type Item = T; - - fn encode(&mut self, item: T, buf: &mut EncodeBuf) -> Result<(), ::Error> { - let len = item.encoded_len(); - - if buf.remaining_mut() < len { - buf.reserve(len); - } - - item.encode(buf) - .map_err(|_| unreachable!("Message only errors if not enough space")) - } -} - -impl Clone for Encoder { - fn clone(&self) -> Self { - Encoder(PhantomData) - } -} - -// ===== impl Decoder ===== - -impl ::server::Decoder for Decoder -where T: Message + Default, -{ - type Item = T; - - fn decode(&mut self, buf: &mut DecodeBuf) -> Result { - Message::decode(buf) - .map_err(|_| unimplemented!()) - } -} - -impl Clone for Decoder { - fn clone(&self) -> Self { - Decoder(PhantomData) - } -} diff --git a/tower-grpc/src/request.rs b/tower-grpc/src/request.rs deleted file mode 100644 index 65d9022a0..000000000 --- a/tower-grpc/src/request.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::str::FromStr; - -use http; - -use ::client::codec::Unary; - -#[derive(Debug)] -pub struct Request { - http: http::Request, -} - -impl Request { - /// Create a new gRPC request - pub fn new(name: &str, message: T) -> Self { - let mut req = http::Request::new(message); - *req.version_mut() = http::Version::HTTP_2; - *req.method_mut() = http::Method::POST; - - //TODO: specifically parse a `http::uri::PathAndQuery` - *req.uri_mut() = http::Uri::from_str(name) - .expect("user supplied illegal RPC name"); - - Request { - http: req, - } - } - - /// Get a reference to the message - pub fn get_ref(&self) -> &T { - self.http.body() - } - - /// Get a mutable reference to the message - pub fn get_mut(&mut self) -> &mut T { - self.http.body_mut() - } - - /// Convert an HTTP request to a gRPC request - pub fn from_http(http: http::Request) -> Self { - // TODO: validate - Request { http } - } - - pub fn into_unary(self) -> Request> { - let (head, body) = self.http.into_parts(); - let http = http::Request::from_parts(head, Unary::new(body)); - Request { - http, - } - } - - pub fn into_http(self) -> http::Request { - self.http - } - - pub fn map(self, f: F) -> Request - where F: FnOnce(T) -> U, - { - let (head, body) = self.http.into_parts(); - let body = f(body); - let http = http::Request::from_parts(head, body); - Request::from_http(http) - } - - // pub fn metadata() - // pub fn metadata_bin() -} diff --git a/tower-grpc/src/response.rs b/tower-grpc/src/response.rs deleted file mode 100644 index 0943aaf9d..000000000 --- a/tower-grpc/src/response.rs +++ /dev/null @@ -1,39 +0,0 @@ -use http; - -#[derive(Debug)] -pub struct Response { - http: http::Response, -} - -impl Response { - pub fn new(message: T) -> Self { - let mut res = http::Response::new(message); - *res.version_mut() = http::Version::HTTP_2; - - Response { - http: res, - } - } - - pub(crate) fn from_http(res: http::Response) -> Self { - Response { - http: res, - } - } - - pub fn into_http(self) -> http::Response { - self.http - } - - pub fn map(self, f: F) -> Response - where F: FnOnce(T) -> U, - { - let (head, body) = self.http.into_parts(); - let body = f(body); - let http = http::Response::from_parts(head, body); - Response::from_http(http) - } - - // pub fn metadata() - // pub fn metadata_bin() -} diff --git a/tower-grpc/src/server/client_streaming.rs b/tower-grpc/src/server/client_streaming.rs deleted file mode 100644 index 71780817a..000000000 --- a/tower-grpc/src/server/client_streaming.rs +++ /dev/null @@ -1,59 +0,0 @@ -use {Request, Response}; -use super::unary::Once; -use protobuf::server::ClientStreamingService; - -use futures::{Future, Poll}; -use tower::Service; - -/// Maps to a client streaming gRPC service. -#[derive(Debug, Clone)] -pub struct ClientStreaming { - inner: T, -} - -#[derive(Debug)] -pub struct ResponseFuture { - inner: T, -} - -// ===== impl ClientStreaming ===== - -impl ClientStreaming -where T: ClientStreamingService, -{ - /// Return a new `ClientStreaming` gRPC service handler - pub fn new(inner: T) -> Self { - ClientStreaming { inner } - } -} - -impl Service for ClientStreaming -where T: ClientStreamingService, -{ - type Request = Request; - type Response = Response>; - type Error = ::Error; - type Future = ResponseFuture; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.inner.poll_ready() - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - let inner = self.inner.call(request); - ResponseFuture { inner } - } -} - -// ===== impl ResponseFuture ====== - -impl Future for ResponseFuture -where T: Future, Error = ::Error> { - type Item = Response>; - type Error = ::Error; - - fn poll(&mut self) -> Poll { - let response = try_ready!(self.inner.poll()); - Ok(Once::map(response).into()) - } -} diff --git a/tower-grpc/src/server/codec.rs b/tower-grpc/src/server/codec.rs deleted file mode 100644 index f4e6f8dc7..000000000 --- a/tower-grpc/src/server/codec.rs +++ /dev/null @@ -1,313 +0,0 @@ -use Status; -// TODO: These types will most likely be moved back to the top level. -use client::codec::{DecodeBuf, EncodeBuf, BytesList}; - -use bytes::{Buf, BufMut, BytesMut, Bytes, BigEndian}; -use futures::{Stream, Poll, Async}; -use h2; -use http::HeaderMap; -use tower_h2::{self, Body}; - -use std::collections::VecDeque; - -/// Encodes and decodes gRPC message types -pub trait Codec { - /// The content-type header for messages using this encoding. - /// - /// Should be `application/grpc+yourencoding`. - const CONTENT_TYPE: &'static str; - - /// The encode type - type Encode; - - /// Encoder type - type Encoder: Encoder; - - /// The decode type - type Decode; - - /// Decoder type - type Decoder: Decoder; - - /// Returns a new encoder - fn encoder(&mut self) -> Self::Encoder; - - /// Returns a new decoder - fn decoder(&mut self) -> Self::Decoder; -} - -/// Encodes gRPC message types -pub trait Encoder { - /// Type that is encoded - type Item; - - /// Encode a message into the provided buffer. - fn encode(&mut self, item: Self::Item, buf: &mut EncodeBuf) -> Result<(), ::Error>; -} - -/// Decodes gRPC message types -pub trait Decoder { - /// Type that is decoded - type Item; - - /// Decode a message from the buffer. - /// - /// The buffer will contain exactly the bytes of a full message. There - /// is no need to get the length from the bytes, gRPC framing is handled - /// for you. - fn decode(&mut self, buf: &mut DecodeBuf) -> Result; -} - -/// Encodes gRPC message types -#[must_use = "futures do nothing unless polled"] -#[derive(Debug)] -pub struct Encode { - inner: EncodeInner, - - /// Destination buffer - buf: BytesMut, -} - -#[derive(Debug)] -enum EncodeInner { - Ok { - /// The source of messages to encode - inner: T, - - /// The encoder - encoder: E, - }, - Err(Status), -} - -/// Decodes gRPC message types -#[must_use = "futures do nothing unless polled"] -#[derive(Debug)] -pub struct Decode { - /// The source of encoded messages - inner: tower_h2::RecvBody, - - /// The decoder - decoder: D, - - /// buffer - bufs: BytesList, - - /// Decoding state - state: State, -} - -#[derive(Debug)] -enum State { - ReadHeader, - ReadBody { - compression: bool, - len: usize, - }, - Done, -} - -// ===== impl Encode ===== - -impl Encode -where T: Stream, - E: Encoder, -{ - pub(crate) fn new(inner: T, encoder: E) -> Self { - Encode { - inner: EncodeInner::Ok { inner, encoder }, - buf: BytesMut::new(), - } - } - - pub(crate) fn error(status: Status) -> Self { - Encode { - inner: EncodeInner::Err(status), - buf: BytesMut::new(), - } - } -} - -impl tower_h2::Body for Encode -where T: Stream, - E: Encoder, -{ - type Data = Bytes; - - fn is_end_stream(&self) -> bool { - false - } - - fn poll_data(&mut self) -> Poll, h2::Error> { - match self.inner { - EncodeInner::Ok { ref mut inner, ref mut encoder } => { - let item = try_ready!(inner.poll().map_err(|_| h2_err())); - - if let Some(item) = item { - self.buf.reserve(5); - unsafe { self.buf.advance_mut(5); } - encoder.encode(item, &mut EncodeBuf { - bytes: &mut self.buf, - }).map_err(|_| h2_err())?; - - // now that we know length, we can write the header - let len = self.buf.len() - 5; - assert!(len <= ::std::u32::MAX as usize); - { - let mut cursor = ::std::io::Cursor::new(&mut self.buf[..5]); - cursor.put_u8(0); // byte must be 0, reserve doesn't auto-zero - cursor.put_u32::(len as u32); - } - - Ok(Async::Ready(Some(self.buf.split_to(len + 5).freeze()))) - } else { - Ok(Async::Ready(None)) - } - } - _ => Ok(Async::Ready(None)), - } - } - - fn poll_trailers(&mut self) -> Poll, h2::Error> { - let mut map = HeaderMap::new(); - - let status = match self.inner { - EncodeInner::Ok { .. } => Status::OK.to_header_value(), - EncodeInner::Err(ref status) => status.to_header_value(), - }; - - // Success - map.insert("grpc-status", status); - - Ok(Some(map).into()) - } -} - -// ===== impl Decode ===== - -impl Decode -where D: Decoder, -{ - pub(crate) fn new(inner: tower_h2::RecvBody, decoder: D) -> Self { - Decode { - inner, - decoder, - bufs: BytesList { - bufs: VecDeque::new(), - }, - state: State::ReadHeader, - } - } - - fn decode(&mut self) -> Result, Status> { - if let State::ReadHeader = self.state { - if self.bufs.remaining() < 5 { - return Ok(None); - } - - let is_compressed = match self.bufs.get_u8() { - 0 => false, - 1 => { - trace!("message compressed, compression not supported yet"); - return Err(Status::UNIMPLEMENTED); - }, - _ => { - trace!("unexpected compression flag"); - return Err(Status::UNKNOWN); - } - }; - let len = self.bufs.get_u32::() as usize; - - self.state = State::ReadBody { - compression: is_compressed, - len, - } - } - - if let State::ReadBody { len, .. } = self.state { - if self.bufs.remaining() < len { - return Ok(None); - } - - match self.decoder.decode(&mut DecodeBuf { - bufs: &mut self.bufs, - len, - }) { - Ok(msg) => { - self.state = State::ReadHeader; - return Ok(Some(msg)); - }, - Err(_) => { - debug!("decoder error"); - return Err(Status::UNKNOWN); - } - } - } - - Ok(None) - } -} - -impl Stream for Decode -where D: Decoder, -{ - type Item = D::Item; - type Error = ::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - loop { - if let State::Done = self.state { - break; - } - - match self.decode() { - Ok(Some(val)) => return Ok(Async::Ready(Some(val))), - Ok(None) => (), - Err(status) => return Err(::Error::Grpc(status)), - } - - let chunk = try_ready!(self.inner.poll_data()); - - if let Some(data) = chunk { - self.bufs.bufs.push_back(data); - } else { - if self.bufs.has_remaining() { - trace!("unexpected EOF decoding stream"); - return Err(::Error::Grpc(Status::UNKNOWN)) - } else { - self.state = State::Done; - break; - } - } - } - - if let Some(trailers) = try_ready!(self.inner.poll_trailers()) { - grpc_status(&trailers).map_err(::Error::Grpc)?; - Ok(Async::Ready(None)) - } else { - trace!("receive body ended without trailers"); - Err(::Error::Grpc(Status::UNKNOWN)) - } - } -} - - -// ===== impl utils ===== - -fn h2_err() -> h2::Error { - unimplemented!("EncodingBody map_err") -} - -fn grpc_status(trailers: &HeaderMap) -> Result<(), Status> { - if let Some(status) = trailers.get("grpc-status") { - let status = Status::from_bytes(status.as_ref()); - if status.code() == ::Code::OK { - Ok(()) - } else { - Err(status) - } - } else { - trace!("trailers missing grpc-status"); - Err(Status::UNKNOWN) - } -} diff --git a/tower-grpc/src/server/mod.rs b/tower-grpc/src/server/mod.rs deleted file mode 100644 index d5ad1558f..000000000 --- a/tower-grpc/src/server/mod.rs +++ /dev/null @@ -1,57 +0,0 @@ -mod codec; -pub mod client_streaming; -pub mod server_streaming; -pub mod streaming; -pub mod unary; - -pub use self::codec::{Codec, Encoder, Decoder, Decode, Encode}; -pub use self::streaming::Grpc; -pub use self::client_streaming::ClientStreaming; -pub use self::server_streaming::ServerStreaming; -pub use self::unary::Unary; - -use {Request, Response}; - -use futures::{Poll}; -use futures::future::{self, FutureResult}; -use tower::Service; - -/// A gRPC service that responds to all requests with not implemented -#[derive(Debug)] -pub struct NotImplemented { - _p: ::std::marker::PhantomData<(T, U)>, -} - -// ===== impl NotImplemented ===== - -impl NotImplemented { - pub fn new() -> Self { - NotImplemented { - _p: ::std::marker::PhantomData, - } - } -} - -impl Service for NotImplemented -{ - type Request = Request; - type Response = Response; - type Error = ::Error; - type Future = FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(().into()) - } - - fn call(&mut self, _: Self::Request) -> Self::Future { - future::err(::Error::Grpc(::Status::UNIMPLEMENTED)) - } -} - -impl Clone for NotImplemented { - fn clone(&self) -> Self { - NotImplemented { - _p: ::std::marker::PhantomData, - } - } -} diff --git a/tower-grpc/src/server/server_streaming.rs b/tower-grpc/src/server/server_streaming.rs deleted file mode 100644 index dc6c7c01c..000000000 --- a/tower-grpc/src/server/server_streaming.rs +++ /dev/null @@ -1,144 +0,0 @@ -use {Request, Response}; -use protobuf::server::ServerStreamingService; - -use futures::{Future, Stream, Poll}; -use tower::Service; - -/// Maps to a server streaming gRPC service. -#[derive(Debug)] -pub struct ServerStreaming { - /// Inner service blueprint. This is used as the source to clone from. - inner: T, - - /// The clone that will be used to handle the next request. - clone: T, - - /// Making the rustc compiler happy since 2014. - _p: ::std::marker::PhantomData, -} - -pub struct ResponseFuture -where T: ServerStreamingService, - S: Stream, -{ - inner: T, - state: Option>, -} - -enum State { - /// Waiting for the request to be received - Requesting(Request), - - /// Waiting for the response future to resolve - Responding(T), -} - -// ===== impl ServerStreaming ===== - -impl ServerStreaming -where T: ServerStreamingService, - S: Stream, -{ - /// Return a new `ServerStreaming` gRPC service handler - pub fn new(inner: T) -> Self { - let clone = inner.clone(); - - ServerStreaming { - inner, - clone, - _p: ::std::marker::PhantomData, - } - } -} - -impl Service for ServerStreaming -where T: ServerStreamingService, - S: Stream, -{ - type Request = Request; - type Response = Response; - type Error = ::Error; - type Future = ResponseFuture; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - // Ensure that the clone is ready to process the request. - self.clone.poll_ready() - .map_err(|_| unimplemented!()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - use std::mem; - - // Create a new clone to replace the old one. - let inner = mem::replace(&mut self.clone, self.inner.clone()); - - ResponseFuture { - inner, - state: Some(State::Requesting(request)), - } - } -} - -impl Clone for ServerStreaming -where T: Clone, -{ - fn clone(&self) -> Self { - let inner = self.inner.clone(); - let clone = inner.clone(); - - ServerStreaming { - inner, - clone, - _p: ::std::marker::PhantomData, - } - } -} - -// ===== impl ResponseFuture ====== - -impl Future for ResponseFuture -where T: ServerStreamingService, - S: Stream, -{ - type Item = Response; - type Error = ::Error; - - fn poll(&mut self) -> Poll { - use self::State::*; - - loop { - let msg = match *self.state.as_mut().unwrap() { - Requesting(ref mut request) => { - try_ready!(request.get_mut().poll()) - } - Responding(ref mut fut) => { - return fut.poll(); - } - }; - - match msg { - Some(msg) => { - match self.state.take().unwrap() { - Requesting(request) => { - // A bunch of junk to map the body type - let http = request.into_http(); - let (head, _) = http.into_parts(); - - let http = ::http::Request::from_parts(head, msg); - let request = Request::from_http(http); - - let response = self.inner.call(request); - - self.state = Some(Responding(response)); - } - _ => unreachable!(), - } - } - None => { - // TODO: Do something - return Err(::Error::Inner(())); - } - } - } - } -} diff --git a/tower-grpc/src/server/streaming.rs b/tower-grpc/src/server/streaming.rs deleted file mode 100644 index 6177bd9ae..000000000 --- a/tower-grpc/src/server/streaming.rs +++ /dev/null @@ -1,122 +0,0 @@ -use {Request, Response}; -use super::codec::{Codec, Encoder, Decode, Encode}; - -use {http, h2}; -use futures::{Future, Stream, Poll, Async}; -use tower::Service; -use tower_h2::RecvBody; - -/// A bidirectional streaming gRPC service. -#[derive(Debug, Clone)] -pub struct Grpc { - inner: T, - codec: C, -} - -#[derive(Debug)] -pub struct ResponseFuture { - inner: T, - encoder: Option, -} - -// ===== impl Grpc ===== - -impl Grpc -where T: Service>, - Response = Response, - Error = ::Error>, - C: Codec, - S: Stream, -{ - pub fn new(inner: T, codec: C) -> Self { - Grpc { - inner, - codec, - } - } -} - -impl Service for Grpc -where T: Service>, - Response = Response, - Error = ::Error>, - C: Codec, - S: Stream, -{ - type Request = http::Request; - type Response = http::Response>; - type Error = h2::Error; - type Future = ResponseFuture; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.inner.poll_ready().map_err(|_| unimplemented!()) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - // Map the request body - let (head, body) = request.into_parts(); - - // Wrap the body stream with a decoder - let body = Decode::new(body, self.codec.decoder()); - - // Reconstruct the HTTP request - let request = http::Request::from_parts(head, body); - - // Convert the HTTP request to a gRPC request - let request = Request::from_http(request); - - // Send the request to the inner service - let inner = self.inner.call(request); - - // Return the response - ResponseFuture { - inner, - encoder: Some(self.codec.encoder()), - } - } -} - -// ===== impl ResponseFuture ===== - -impl Future for ResponseFuture -where T: Future, - Error = ::Error>, - E: Encoder, - S: Stream, -{ - type Item = http::Response>; - type Error = h2::Error; - - fn poll(&mut self) -> Poll { - // Get the gRPC response - let response = match self.inner.poll() { - Ok(Async::Ready(response)) => response, - Ok(Async::NotReady) => return Ok(Async::NotReady), - Err(e) => { - match e { - ::Error::Grpc(status) => { - let response = Response::new(Encode::error(status)); - return Ok(response.into_http().into()); - } - // TODO: Is this correct? - _ => return Err(h2::Reason::INTERNAL_ERROR.into()), - } - } - }; - - // Convert to an HTTP response - let response = response.into_http(); - - // Map the response body - let (head, body) = response.into_parts(); - - // Get the encoder - let encoder = self.encoder.take().expect("encoder consumed"); - - // Encode the body - let body = Encode::new(body, encoder); - - // Success - Ok(http::Response::from_parts(head, body).into()) - } -} diff --git a/tower-grpc/src/server/unary.rs b/tower-grpc/src/server/unary.rs deleted file mode 100644 index 68362c7bd..000000000 --- a/tower-grpc/src/server/unary.rs +++ /dev/null @@ -1,144 +0,0 @@ -use super::server_streaming::{self, ServerStreaming}; - -use {Request, Response}; -use protobuf::server::UnaryService; - -use futures::{Future, Stream, Poll}; -use tower::Service; - -/// Maps to a unary gRPC service. -#[derive(Debug)] -pub struct Unary { - inner: ServerStreaming, S>, -} - -pub struct ResponseFuture -where T: UnaryService, - S: Stream, -{ - inner: server_streaming::ResponseFuture, S>, -} - - -#[derive(Debug)] -pub struct Once { - inner: Option, -} - -/// Maps inbound requests -#[derive(Debug, Clone)] -struct Inner(pub T); -struct InnerFuture(T); - -// ===== impl Unary ===== - -impl Unary -where T: UnaryService, - S: Stream, -{ - /// Return a new `Unary` gRPC service handler - pub fn new(inner: T) -> Self { - let inner = ServerStreaming::new(Inner(inner)); - Unary { inner } - } -} - -impl Service for Unary -where T: UnaryService, - S: Stream, -{ - type Request = Request; - type Response = ::Response>; - type Error = ::Error; - type Future = ResponseFuture; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Service::poll_ready(&mut self.inner) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - let inner = Service::call(&mut self.inner, request); - ResponseFuture { inner } - } -} - -impl Clone for Unary -where T: Clone, -{ - fn clone(&self) -> Self { - Unary { inner: self.inner.clone() } - } -} - -// ===== impl Inner ===== - -impl Service for Inner -where T: UnaryService, -{ - type Request = Request; - type Response = Response>; - type Error = ::Error; - type Future = InnerFuture; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.0.poll_ready() - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - let inner = self.0.call(request); - InnerFuture(inner) - } -} - -// ===== impl ResponseFuture ====== - -impl Future for ResponseFuture -where T: UnaryService, - S: Stream, -{ - type Item = Response>; - type Error = ::Error; - - fn poll(&mut self) -> Poll { - self.inner.poll() - } -} - -// ===== impl InnerFuture ====== - -impl Future for InnerFuture -where T: Future, Error = ::Error> { - type Item = Response>; - type Error = ::Error; - - fn poll(&mut self) -> Poll { - let response = try_ready!(self.0.poll()); - Ok(Once::map(response).into()) - } -} - -// ===== impl Once ===== - -impl Once { - /// Map a response to a response of a `Once` stream - pub(super) fn map(response: Response) -> Response { - // A bunch of junk to map the body type - let http = response.into_http(); - let (head, body) = http.into_parts(); - - // Wrap with `Once` - let body = Once { inner: Some(body) }; - - let http = ::http::Response::from_parts(head, body); - Response::from_http(http) - } -} - -impl Stream for Once { - type Item = T; - type Error = ::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - Ok(self.inner.take().into()) - } -} diff --git a/tower-grpc/src/status.rs b/tower-grpc/src/status.rs deleted file mode 100644 index 9221170db..000000000 --- a/tower-grpc/src/status.rs +++ /dev/null @@ -1,204 +0,0 @@ -use std::fmt; - -use h2; -use http::header::HeaderValue; - -#[derive(Debug, Clone)] -pub struct Status { - code: Code, -} - -#[derive(Clone, Copy, PartialEq, Eq)] -pub struct Code(Code_); - -impl Status { - #[inline] - pub fn code(&self) -> Code { - self.code - } - - pub const OK: Status = Status { - code: Code(Code_::Ok), - }; - - pub const CANCELED: Status = Status { - code: Code(Code_::Canceled), - }; - - pub const UNKNOWN: Status = Status { - code: Code(Code_::Unknown), - }; - - pub const INVALID_ARGUMENT: Status = Status { - code: Code(Code_::InvalidArgument), - }; - - pub const DEADLINE_EXCEEDED: Status = Status { - code: Code(Code_::DeadlineExceeded), - }; - - pub const NOT_FOUND: Status = Status { - code: Code(Code_::NotFound), - }; - - pub const ALREADY_EXISTS: Status = Status { - code: Code(Code_::AlreadyExists), - }; - - pub const PERMISSION_DENIED: Status = Status { - code: Code(Code_::PermissionDenied), - }; - - pub const RESOURCE_EXHAUSTED: Status = Status { - code: Code(Code_::ResourceExhausted), - }; - - pub const FAILED_PRECONDITION: Status = Status { - code: Code(Code_::FailedPrecondition), - }; - - pub const ABORTED: Status = Status { - code: Code(Code_::Aborted), - }; - - pub const OUT_OF_RANGE: Status = Status { - code: Code(Code_::OutOfRange), - }; - - pub const UNIMPLEMENTED: Status = Status { - code: Code(Code_::Unimplemented), - }; - - pub const INTERNAL: Status = Status { - code: Code(Code_::Internal), - }; - - pub const UNAVAILABLE: Status = Status { - code: Code(Code_::Unavailable), - }; - - pub const DATA_LOSS: Status = Status { - code: Code(Code_::DataLoss), - }; - - pub const UNAUTHENTICATED: Status = Status { - code: Code(Code_::Unauthenticated), - }; - - pub(crate) fn from_bytes(bytes: &[u8]) -> Status { - let code = match bytes.len() { - 1 => { - match bytes[0] { - b'0' => Code_::Ok, - b'1' => Code_::Canceled, - b'2' => Code_::Unknown, - b'3' => Code_::InvalidArgument, - b'4' => Code_::DeadlineExceeded, - b'5' => Code_::NotFound, - b'6' => Code_::AlreadyExists, - b'7' => Code_::PermissionDenied, - b'8' => Code_::ResourceExhausted, - b'9' => Code_::FailedPrecondition, - _ => return Status::parse_err(), - } - }, - 2 => { - match (bytes[0], bytes[1]) { - (b'1', b'0') => Code_::Aborted, - (b'1', b'1') => Code_::OutOfRange, - (b'1', b'2') => Code_::Unimplemented, - (b'1', b'3') => Code_::Internal, - (b'1', b'4') => Code_::Unavailable, - (b'1', b'5') => Code_::DataLoss, - (b'1', b'6') => Code_::Unauthenticated, - _ => return Status::parse_err(), - } - }, - _ => return Status::parse_err(), - }; - - Status::new(Code(code)) - } - - // TODO: It would be nice for this not to be public - pub fn to_header_value(&self) -> HeaderValue { - use self::Code_::*; - - match self.code.0 { - Ok => HeaderValue::from_static("0"), - Canceled => HeaderValue::from_static("1"), - Unknown => HeaderValue::from_static("2"), - InvalidArgument => HeaderValue::from_static("3"), - DeadlineExceeded => HeaderValue::from_static("4"), - NotFound => HeaderValue::from_static("5"), - AlreadyExists => HeaderValue::from_static("6"), - PermissionDenied => HeaderValue::from_static("7"), - ResourceExhausted => HeaderValue::from_static("8"), - FailedPrecondition => HeaderValue::from_static("9"), - Aborted => HeaderValue::from_static("10"), - OutOfRange => HeaderValue::from_static("11"), - Unimplemented => HeaderValue::from_static("12"), - Internal => HeaderValue::from_static("13"), - Unavailable => HeaderValue::from_static("14"), - DataLoss => HeaderValue::from_static("15"), - Unauthenticated => HeaderValue::from_static("16"), - } - } - - fn new(code: Code) -> Status { - Status { - code, - } - } - - fn parse_err() -> Status { - trace!("error parsing grpc-status"); - Status::UNKNOWN - } -} - -impl From for Status { - fn from(_err: h2::Error) -> Self { - //TODO: https://grpc.io/docs/guides/wire.html#errors - Status::new(Code(Code_::Internal)) - } -} - -impl From for h2::Error { - fn from(_status: Status) -> Self { - // TODO: implement - h2::Reason::INTERNAL_ERROR.into() - } -} - -impl Code { - pub const OK: Code = Code(Code_::Ok); - //TODO: the rest... -} - -impl fmt::Debug for Code { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.0, f) - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -enum Code_ { - Ok = 0, - Canceled = 1, - Unknown = 2, - InvalidArgument = 3, - DeadlineExceeded = 4, - NotFound = 5, - AlreadyExists = 6, - PermissionDenied = 7, - ResourceExhausted = 8, - FailedPrecondition = 9, - Aborted = 10, - OutOfRange = 11, - Unimplemented = 12, - Internal = 13, - Unavailable = 14, - DataLoss = 15, - Unauthenticated = 16, -} diff --git a/tower-h2/Cargo.toml b/tower-h2/Cargo.toml deleted file mode 100644 index 62723e86c..000000000 --- a/tower-h2/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "tower-h2" -version = "0.2.0" -authors = ["Oliver Gould "] -description = "Exploring tower + h2" -publish = false - -[dependencies] -bytes = "0.4" -futures = "0.1" -h2 = { git = "https://github.com/carllerche/h2" } -http = "0.1" -log = "0.3" -tokio-core = "0.1" -tokio-connect = { git = "https://github.com/carllerche/tokio-connect" } -tokio-io = "0.1" -tower = { git = "https://github.com/tower-rs/tower" } - -[dev-dependencies] -env_logger = "^0.4.3" -string = { git = "https://github.com/carllerche/string" } diff --git a/tower-h2/examples/client.rs b/tower-h2/examples/client.rs deleted file mode 100644 index a1dc98f6e..000000000 --- a/tower-h2/examples/client.rs +++ /dev/null @@ -1,143 +0,0 @@ -extern crate env_logger; -extern crate futures; -extern crate bytes; -extern crate h2; -extern crate http; -extern crate string; -extern crate tokio_connect; -extern crate tokio_core; -extern crate tower; -extern crate tower_h2; - -use futures::*; -use bytes::Bytes; -use http::{Request, Response}; -use std::net::SocketAddr; -use string::{String, TryFrom}; -use tokio_connect::Connect; -use tokio_core::net::TcpStream; -use tokio_core::reactor::{Core, Handle}; -use tower::{NewService, Service}; -use tower_h2::{Body, Client, RecvBody}; -use h2::Reason; - -pub struct Conn(SocketAddr, Handle); - -fn main() { - drop(env_logger::init()); - - let mut core = Core::new().unwrap(); - let reactor = core.handle(); - - let addr = "[::1]:8888".parse().unwrap(); - - impl Connect for Conn { - type Connected = TcpStream; - type Error = ::std::io::Error; - type Future = Box>; - - fn connect(&self) -> Self::Future { - let c = TcpStream::connect(&self.0, &self.1) - .and_then(|tcp| tcp.set_nodelay(true).map(move |_| tcp)); - Box::new(c) - } - } - - let conn = Conn(addr, reactor.clone()); - let h2 = Client::::new(conn, Default::default(), reactor); - - let done = h2.new_service() - .map_err(|_| Reason::REFUSED_STREAM.into()) - .and_then(move |h2| { - Serial { - h2, - count: 500, - pending: None, - } - }) - .map(|_| println!("done")) - .map_err(|e| println!("error: {:?}", e)); - - core.run(done).unwrap(); -} - -/// Avoids overflowing max concurrent streams -struct Serial { - count: usize, - h2: tower_h2::client::Service, - pending: Option>>, -} - -impl Future for Serial { - type Item = (); - type Error = tower_h2::client::Error; - - fn poll(&mut self) -> Poll<(), Self::Error> { - loop { - if let Some(mut fut) = self.pending.take() { - if fut.poll()?.is_not_ready() { - self.pending = Some(fut); - return Ok(Async::NotReady); - } - } - - if self.count == 0 { - return Ok(Async::Ready(())); - } - - let pfx = format!("{}", self.count); - self.count -= 1; - let mut fut = self.h2 - .call(mkreq()) - .and_then(move |rsp| read_response(&pfx, rsp).map_err(Into::into)); - - if fut.poll()?.is_not_ready() { - self.pending = Some(Box::new(fut)); - return Ok(Async::NotReady); - } - } - } -} - -fn mkreq() -> Request<()> { - Request::builder() - .method("GET") - .uri("http://[::1]:8888/") - .version(http::Version::HTTP_2) - .body(()) - .unwrap() -} - -fn read_response(pfx: &str, rsp: Response) -> ReadResponse { - let (parts, body) = rsp.into_parts(); - println!("{}: {}", pfx, parts.status); - let pfx = pfx.to_owned(); - ReadResponse { - pfx, - body, - } -} - -struct ReadResponse { - pfx: ::std::string::String, - body: RecvBody, -} - -impl Future for ReadResponse { - type Item = (); - type Error = tower_h2::client::Error; - fn poll(&mut self) -> Poll<(), Self::Error> { - loop { - match try_ready!(self.body.poll_data()) { - None => return Ok(Async::Ready(())), - Some(b) => { - let b: Bytes = b.into(); - { - let s = String::try_from(b).expect("decode utf8 string"); - println!("{}: {}", self.pfx, &*s); - } - } - } - } - } -} diff --git a/tower-h2/examples/server.rs b/tower-h2/examples/server.rs deleted file mode 100644 index 15093edc2..000000000 --- a/tower-h2/examples/server.rs +++ /dev/null @@ -1,121 +0,0 @@ -extern crate bytes; -extern crate env_logger; -extern crate futures; -extern crate h2; -extern crate http; -#[macro_use] -extern crate log; -extern crate tokio_core; -extern crate tower; -extern crate tower_h2; - -use bytes::Bytes; -use futures::*; -use http::Request; -use tokio_core::net::TcpListener; -use tokio_core::reactor::Core; -use tower::{NewService, Service}; -use tower_h2::{Body, Server, RecvBody}; - -type Response = http::Response; - -struct RspBody(Option); - -impl RspBody { - fn new(body: Bytes) -> Self { - RspBody(Some(body)) - } - - fn empty() -> Self { - RspBody(None) - } -} - - -impl Body for RspBody { - type Data = Bytes; - - fn is_end_stream(&self) -> bool { - self.0.as_ref().map(|b| b.is_empty()).unwrap_or(false) - } - - fn poll_data(&mut self) -> Poll, h2::Error> { - let data = self.0 - .take() - .and_then(|b| if b.is_empty() { None } else { Some(b) }); - Ok(Async::Ready(data)) - } -} - -//const ROOT: &'static str = "/"; -const ROOT: &'static str = "/helloworld.Greeter/SayHello"; - -#[derive(Debug)] -struct Svc; -impl Service for Svc { - type Request = Request; - type Response = Response; - type Error = h2::Error; - type Future = future::FutureResult; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - Ok(Async::Ready(())) - } - - fn call(&mut self, req: Self::Request) -> Self::Future { - let mut rsp = http::Response::builder(); - rsp.version(http::Version::HTTP_2); - - let uri = req.uri(); - if uri.path() != ROOT { - let body = RspBody::empty(); - let rsp = rsp.status(404).body(body).unwrap(); - return future::ok(rsp); - } - - let body = RspBody::new("heyo!".into()); - let rsp = rsp.status(200).body(body).unwrap(); - future::ok(rsp) - } -} - -#[derive(Debug)] -struct NewSvc; -impl NewService for NewSvc { - type Request = Request; - type Response = Response; - type Error = h2::Error; - type InitError = ::std::io::Error; - type Service = Svc; - type Future = future::FutureResult; - - fn new_service(&self) -> Self::Future { - future::ok(Svc) - } -} - -fn main() { - drop(env_logger::init()); - - let mut core = Core::new().unwrap(); - let reactor = core.handle(); - - let h2 = Server::new(NewSvc, Default::default(), reactor.clone()); - - let addr = "[::1]:8888".parse().unwrap(); - let bind = TcpListener::bind(&addr, &reactor).expect("bind"); - - let serve = bind.incoming() - .fold((h2, reactor), |(h2, reactor), (sock, _)| { - if let Err(e) = sock.set_nodelay(true) { - return Err(e); - } - - let serve = h2.serve(sock); - reactor.spawn(serve.map_err(|e| error!("h2 error: {:?}", e))); - - Ok((h2, reactor)) - }); - - core.run(serve).unwrap(); -} diff --git a/tower-h2/src/body.rs b/tower-h2/src/body.rs deleted file mode 100644 index d9969f41a..000000000 --- a/tower-h2/src/body.rs +++ /dev/null @@ -1,48 +0,0 @@ -use h2; -use bytes::IntoBuf; -use futures::{Async, Poll}; -use http::HeaderMap; - -/// A generic h2 client/server request/response body. -pub trait Body { - /// The body chunk type - type Data: IntoBuf + 'static; - - /// Returns `true` when the end of stream has been reached. - /// - /// An end of stream means that both `poll_data` and `poll_trailers` will - /// return `None`. - /// - /// A return value of `false` **does not** guarantee that a value will be - /// returend from `poll_stream` or `poll_trailers`. - fn is_end_stream(&self) -> bool { - false - } - - /// Polls a stream of data. - fn poll_data(&mut self) -> Poll, h2::Error>; - - /// Returns possibly **one** `HeaderMap` for trailers. - fn poll_trailers(&mut self) -> Poll, h2::Error> { - Ok(Async::Ready(None)) - } -} - -impl Body for () { - type Data = &'static [u8]; - - #[inline] - fn is_end_stream(&self) -> bool { - true - } - - #[inline] - fn poll_data(&mut self) -> Poll, h2::Error> { - Ok(Async::Ready(None)) - } - - #[inline] - fn poll_trailers(&mut self) -> Poll, h2::Error> { - Ok(Async::Ready(None)) - } -} diff --git a/tower-h2/src/client/background.rs b/tower-h2/src/client/background.rs deleted file mode 100644 index cdd0866a8..000000000 --- a/tower-h2/src/client/background.rs +++ /dev/null @@ -1,63 +0,0 @@ -use Body; -use flush::Flush; - -use futures::{Future, Poll}; -use h2::client::Connection; -use tokio_connect::Connect; - -/// Task that performs background tasks for a client. -/// -/// This is not used directly by a user of this library. -pub struct Background -where C: Connect, - S: Body, -{ - task: Task, -} - -/// The specific task to execute -enum Task -where C: Connect, - S: Body, -{ - Connection(Connection), - Flush(Flush), -} - -// ===== impl Background ===== - -impl Background -where C: Connect, - S: Body, -{ - pub(crate) fn connection( - connection: Connection) - -> Self - { - let task = Task::Connection(connection); - Background { task } - } - - pub(crate) fn flush(flush: Flush) -> Self { - let task = Task::Flush(flush); - Background { task } - } -} - -impl Future for Background -where C: Connect, - S: Body, -{ - type Item = (); - type Error = (); - - fn poll(&mut self) -> Poll { - use self::Task::*; - - match self.task { - // TODO: Log error? - Connection(ref mut f) => f.poll().map_err(|_| ()), - Flush(ref mut f) => f.poll(), - } - } -} diff --git a/tower-h2/src/client/mod.rs b/tower-h2/src/client/mod.rs deleted file mode 100644 index 5e3c06826..000000000 --- a/tower-h2/src/client/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod background; -mod new_service; -mod service; - -pub use self::background::Background; -pub use self::new_service::{Client, ConnectFuture, ConnectError}; -pub use self::service::{Service, ResponseFuture, Error}; diff --git a/tower-h2/src/client/new_service.rs b/tower-h2/src/client/new_service.rs deleted file mode 100644 index 2019b2cce..000000000 --- a/tower-h2/src/client/new_service.rs +++ /dev/null @@ -1,140 +0,0 @@ -use {Body, RecvBody}; -use super::{Service, Background}; - -use futures::{Future, Async, Poll}; -use futures::future::Executor; -use h2; -use h2::client::Connection; -use http::{Request, Response}; -use tokio_connect::Connect; - -use std::boxed::Box; -use std::marker::PhantomData; - -/// Establishes a Client on an H2 connection. -/// -/// Has a builder-like API for configuring client connections. Currently this only allows -/// the configuration of TLS transport on new services created by this factory. -pub struct Client { - /// Establish new session layer values (usually TCP sockets w/ TLS). - connect: C, - - /// H2 client configuration - builder: h2::client::Builder, - - /// Used to spawn connection management tasks and tasks to flush send - /// body streams. - executor: E, - - /// The HTTP request body type. - _p: PhantomData, -} - -/// Completes with a Service when the H2 connection has been initialized. -pub struct ConnectFuture -where C: Connect + 'static, - S: Body + 'static, -{ - future: Box, Error = ConnectError>>, - executor: E, - _p: PhantomData, -} - -/// The type yielded by an h2 client handshake future -type Connected = (h2::client::Client, Connection); - -/// Error produced when establishing an H2 client connection. -#[derive(Debug)] -pub enum ConnectError { - /// An error occurred when attempting to establish the underlying session - /// layer. - Connect(T), - - /// An error occurred when attempting to perform the HTTP/2.0 handshake. - Proto(h2::Error), - - /// An error occured when attempting to execute a worker task - Execute, -} - -// ===== impl Client ===== - -impl Client -where - C: Connect, - E: Executor> + Clone, - S: Body, -{ - /// Create a new `Client`. - /// - /// The `connect` argument is used to obtain new session layer instances - /// (`AsyncRead` + `AsyncWrite`). For each new client service returned, a - /// task will be spawned onto `executor` that will be used to manage the H2 - /// connection. - pub fn new(connect: C, builder: h2::client::Builder, executor: E) -> Self { - Client { - connect, - executor, - builder, - _p: PhantomData, - } - } -} - -impl ::tower::NewService for Client -where - C: Connect + 'static, - E: Executor> + Clone, - S: Body + 'static, -{ - type Request = Request; - type Response = Response; - type Error = super::Error; - type InitError = ConnectError; - type Service = Service; - type Future = ConnectFuture; - - /// Obtains a Service on a single plaintext h2 connection to a remote. - fn new_service(&self) -> Self::Future { - let client = self.builder.clone(); - let conn = self.connect.connect() - .map_err(ConnectError::Connect) - .and_then(move |io| { - client - .handshake(io) - .map_err(ConnectError::Proto) - }); - - ConnectFuture { - future: Box::new(conn), - executor: self.executor.clone(), - _p: PhantomData, - } - } -} - -// ===== impl ConnectFuture ===== - -impl Future for ConnectFuture -where - C: Connect, - E: Executor> + Clone, - S: Body, -{ - type Item = Service; - type Error = ConnectError; - - fn poll(&mut self) -> Poll { - // Get the session layer instance - let (client, connection) = try_ready!(self.future.poll()); - - // Spawn the worker task - let task = Background::connection(connection); - self.executor.execute(task).map_err(|_| ConnectError::Execute)?; - - // Create an instance of the service - let service = Service::new(client, self.executor.clone()); - - Ok(Async::Ready(service)) - } -} diff --git a/tower-h2/src/client/service.rs b/tower-h2/src/client/service.rs deleted file mode 100644 index 547044d57..000000000 --- a/tower-h2/src/client/service.rs +++ /dev/null @@ -1,204 +0,0 @@ -use {Body, RecvBody}; -use super::Background; -use flush::Flush; - -use bytes::IntoBuf; -use futures::{Future, Poll}; -use futures::future::Executor; -use h2; -use h2::client::{self, Client}; -use http::{self, Request, Response}; -use tokio_connect::Connect; - -use std::marker::PhantomData; - -/// Exposes a request/response API on an h2 client connection.. -pub struct Service -where S: Body, -{ - client: Client, - executor: E, - _p: PhantomData<(C, S)>, -} - -/// Drives the sending of a request (and its body) until a response is received (i.e. the -/// initial HEADERS or RESET frames sent from the remote). -/// -/// This is necessary because, for instance, the remote server may not respond until the -/// request body is fully sent. -pub struct ResponseFuture { - inner: Inner, -} - -/// ResponseFuture inner -enum Inner { - /// Inner response future - Inner(client::ResponseFuture), - - /// Failed to send the request - Error(Option), -} - -/// Errors produced by client `Service` calls. -#[derive(Debug)] -pub struct Error { - kind: Kind, -} - -#[derive(Debug)] -enum Kind { - Inner(h2::Error), - Spawn, -} - -// ===== impl Service ===== - -impl Service -where S: Body, - S::Data: IntoBuf + 'static, - C: Connect, - E: Executor>, -{ - /// Builds Service on an H2 client connection. - pub(super) fn new(client: Client, executor: E) -> Self { - let _p = PhantomData; - - Service { - client, - executor, - _p, - } - } -} - -impl Service -where S: Body, - S::Data: IntoBuf + 'static, - C: Connect, - E: Executor> + Clone, -{ - pub fn clone_handle(&self) -> Service - where S2: Body, - { - Service { - client: self.client.clone(), - executor: self.executor.clone(), - _p: PhantomData, - } - } -} - -impl Clone for Service -where S: Body, - E: Clone, -{ - fn clone(&self) -> Self { - Service { - client: self.client.clone(), - executor: self.executor.clone(), - _p: PhantomData, - } - } -} - -impl ::tower::Service for Service -where S: Body + 'static, - S::Data: IntoBuf + 'static, - C: Connect, - E: Executor>, -{ - type Request = Request; - type Response = Response; - type Error = Error; - type Future = ResponseFuture; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.client.poll_ready() - .map_err(Into::into) - } - - fn call(&mut self, request: Self::Request) -> Self::Future { - trace!("request: {} {}", request.method(), request.uri()); - - // Split the request from the body - let (parts, body) = request.into_parts(); - let request = http::Request::from_parts(parts, ()); - - // If there is no body, then there is no point spawning a task to flush - // it. - let end_of_stream = body.is_end_stream(); - - // Initiate the H2 request - let res = self.client.send_request(request, end_of_stream); - - let (response, send_body) = match res { - Ok(success) => success, - Err(e) => { - let e = Error { kind: Kind::Inner(e) }; - let inner = Inner::Error(Some(e)); - return ResponseFuture { inner }; - } - }; - - if !end_of_stream { - let flush = Flush::new(body, send_body); - let res = self.executor.execute(Background::flush(flush)); - - if let Err(_) = res { - let e = Error { kind: Kind::Spawn }; - let inner = Inner::Error(Some(e)); - return ResponseFuture { inner }; - } - } - - ResponseFuture { inner: Inner::Inner(response) } - } -} - -// ===== impl ResponseFuture ===== - -impl Future for ResponseFuture { - type Item = Response; - type Error = Error; - - fn poll(&mut self) -> Poll { - use self::Inner::*; - - match self.inner { - Inner(ref mut fut) => { - let response = try_ready!(fut.poll()); - - let (parts, body) = response.into_parts(); - let body = RecvBody::new(body); - - Ok(Response::from_parts(parts, body).into()) - } - Error(ref mut e) => { - return Err(e.take().unwrap()); - } - } - } -} - -// ===== impl Error ===== - -impl Error { - pub fn reason(&self) -> Option { - match self.kind { - Kind::Inner(ref h2) => h2.reason(), - _ => None, - } - } -} - -impl From for Error { - fn from(src: h2::Error) -> Self { - Error { kind: Kind::Inner(src) } - } -} - -impl From for Error { - fn from(src: h2::Reason) -> Self { - h2::Error::from(src).into() - } -} diff --git a/tower-h2/src/flush.rs b/tower-h2/src/flush.rs deleted file mode 100644 index 3755b7ce2..000000000 --- a/tower-h2/src/flush.rs +++ /dev/null @@ -1,103 +0,0 @@ -use Body; - -use futures::{Future, Poll, Async}; -use h2::{self, SendStream}; -use http::HeaderMap; - -/// Flush a body to the HTTP/2.0 send stream -pub(crate) struct Flush -where S: Body, -{ - h2: SendStream, - body: S, - state: FlushState, -} - -enum FlushState { - Data, - Trailers, - Done, -} - -enum DataOrTrailers { - Data(B), - Trailers(HeaderMap), -} - -// ===== impl Flush ===== - -impl Flush -where S: Body, -{ - pub fn new(src: S, dst: SendStream) -> Self { - Flush { - h2: dst, - body: src, - state: FlushState::Data, - } - } - - /// Try to flush the body. - fn poll_complete(&mut self) -> Poll<(), h2::Error> { - let mut first = try_ready!(self.poll_body()); - - loop { - if let Some(DataOrTrailers::Data(buf)) = first { - let second = self.poll_body()?; - let eos = if let Async::Ready(None) = second { - true - } else { - false - }; - self.h2.send_data(buf, eos)?; - if eos { - return Ok(Async::Ready(())); - } else if let Async::Ready(item) = second { - first = item; - } else { - return Ok(Async::NotReady); - } - } else if let Some(DataOrTrailers::Trailers(trailers)) = first { - self.h2.send_trailers(trailers)?; - return Ok(Async::Ready(())); - } else { - return Ok(Async::Ready(())); - } - } - } - - /// Get the next message to write, either a data frame or trailers. - fn poll_body(&mut self) -> Poll>, h2::Error> { - loop { - match self.state { - FlushState::Data => { - if let Some(data) = try_ready!(self.body.poll_data()) { - return Ok(Async::Ready(Some(DataOrTrailers::Data(data)))); - } else { - self.state = FlushState::Trailers; - } - } - FlushState::Trailers => { - let trailers = try_ready!(self.body.poll_trailers()); - self.state = FlushState::Done; - if let Some(trailers) = trailers { - return Ok(Async::Ready(Some(DataOrTrailers::Trailers(trailers)))); - } - } - FlushState::Done => return Ok(Async::Ready(None)), - } - } - } -} - -impl Future for Flush -where S: Body, -{ - type Item = (); - type Error = (); - - fn poll(&mut self) -> Poll<(), ()> { - // TODO: Do something with the error - self.poll_complete().map_err(|_| ()) - } -} diff --git a/tower-h2/src/lib.rs b/tower-h2/src/lib.rs deleted file mode 100644 index 308f26049..000000000 --- a/tower-h2/src/lib.rs +++ /dev/null @@ -1,23 +0,0 @@ -extern crate bytes; -#[macro_use] -extern crate futures; -extern crate h2; -extern crate http; -#[macro_use] -extern crate log; -extern crate tokio_connect; -extern crate tokio_core; -extern crate tokio_io; -extern crate tower; - -pub mod client; -pub mod server; - -mod body; -mod flush; -mod recv_body; - -pub use body::Body; -pub use client::Client; -pub use recv_body::{RecvBody, Data}; -pub use server::Server; diff --git a/tower-h2/src/recv_body.rs b/tower-h2/src/recv_body.rs deleted file mode 100644 index 41ddc0b18..000000000 --- a/tower-h2/src/recv_body.rs +++ /dev/null @@ -1,118 +0,0 @@ -use Body; -use bytes::{Bytes, BytesMut, Buf}; -use futures::{Poll, Stream}; -use h2; -use http; - -/// Allows a stream to be read from the remote. -#[derive(Debug, Default)] -pub struct RecvBody { - inner: Option, -} - -#[derive(Debug)] -pub struct Data { - release_capacity: h2::ReleaseCapacity, - bytes: Bytes, -} - -// ===== impl RecvBody ===== - -impl RecvBody { - /// Return a new `RecvBody`. - pub(crate) fn new(inner: h2::RecvStream) -> Self { - RecvBody { inner: Some(inner) } - } -} - -impl Body for RecvBody { - type Data = Data; - - #[inline] - fn is_end_stream(&self) -> bool { - match self.inner { - Some(ref inner) => inner.is_end_stream(), - None => true, - } - } - - fn poll_data(&mut self) -> Poll, h2::Error> { - match self.inner { - Some(ref mut inner) => { - let data = try_ready!(inner.poll()) - .map(|bytes| { - Data { - release_capacity: inner.release_capacity().clone(), - bytes, - } - }); - - Ok(data.into()) - } - None => Ok(None.into()), - } - } - - fn poll_trailers(&mut self) -> Poll, h2::Error> { - match self.inner { - Some(ref mut inner) => inner.poll_trailers(), - None => Ok(None.into()), - } - } -} - -// ===== impl Data ===== - -impl Buf for Data { - fn remaining(&self) -> usize { - self.bytes.len() - } - - fn bytes(&self) -> &[u8] { - self.bytes.as_ref() - } - - fn advance(&mut self, cnt: usize) { - if cnt > self.remaining() { - panic!("advanced past end of buffer"); - } - - trace!("releasing capacity: {} of {}", cnt, self.remaining()); - let _ = self.bytes.split_to(cnt); - - self.release_capacity.release_capacity(cnt) - .expect("flow control error") - } -} - -impl Drop for Data { - fn drop(&mut self) { - let sz = self.remaining(); - trace!("Data::drop: releasing capacity: {}", sz); - self.release_capacity - .release_capacity(sz) - .expect("flow control error"); - } -} - -impl From for Bytes { - fn from(mut src: Data) -> Self { - let bytes = ::std::mem::replace(&mut src.bytes, Bytes::new()); - - src.release_capacity.release_capacity(bytes.len()) - .expect("flow control error"); - - bytes - } -} - -impl From for BytesMut { - fn from(mut src: Data) -> Self { - let bytes = ::std::mem::replace(&mut src.bytes, Bytes::new()); - - src.release_capacity.release_capacity(bytes.len()) - .expect("flow control error"); - - bytes.into() - } -} diff --git a/tower-h2/src/server/mod.rs b/tower-h2/src/server/mod.rs deleted file mode 100644 index e9ec50e30..000000000 --- a/tower-h2/src/server/mod.rs +++ /dev/null @@ -1,357 +0,0 @@ -use {flush, Body, RecvBody}; - -use futures::{Future, Poll, Stream}; -use futures::future::{Executor, Either, Join, MapErr}; -use h2::{self, Reason}; -use h2::server::{Server as Accept, Handshake, Respond}; -use http::{self, Request, Response}; -use tokio_io::{AsyncRead, AsyncWrite}; -use tower::{NewService, Service}; - -use std::marker::PhantomData; - -/// Attaches service implementations to h2 connections. -pub struct Server -where S: NewService, - B: Body, -{ - new_service: S, - builder: h2::server::Builder, - executor: E, - _p: PhantomData, -} - -/// Drives connection-level I/O . -pub struct Connection -where T: AsyncRead + AsyncWrite, - S: NewService, - B: Body, -{ - state: State, - executor: E, - modify: F, -} - -/// Modify a received request -pub trait Modify { - /// Modify a request before calling the service. - fn modify(&mut self, request: &mut Request<()>); -} - -enum State -where T: AsyncRead + AsyncWrite, - S: NewService, - B: Body, -{ - /// Establish the HTTP/2.0 connection and get a service to process inbound - /// requests. - Init(Init), - - /// Both the HTTP/2.0 connection and the service are ready. - Ready { - connection: Accept, - service: S::Service, - }, -} - -type Init = - Join< - MapErr, MapErrA>, - MapErr>>; - -type MapErrA = fn(h2::Error) -> Either; -type MapErrB = fn(E) -> Either; - -/// Task used to process requests -pub struct Background -where B: Body, -{ - state: BackgroundState, -} - -enum BackgroundState -where B: Body, -{ - Respond { - respond: Respond, - response: T, - }, - Flush(flush::Flush), -} - -/// Error produced by a `Connection`. -#[derive(Debug)] -pub enum Error -where S: NewService, -{ - /// Error produced during the HTTP/2.0 handshake. - Handshake(h2::Error), - - /// Error produced by the HTTP/2.0 stream - Protocol(h2::Error), - - /// Error produced when obtaining the service - NewService(S::InitError), - - /// Error produced by the service - Service(S::Error), - - /// Error produced when attempting to spawn a task - Execute, -} - -// ===== impl Server ===== - -impl Server -where S: NewService, Response = Response>, - B: Body, -{ - pub fn new(new_service: S, builder: h2::server::Builder, executor: E) -> Self { - Server { - new_service, - executor, - builder, - _p: PhantomData, - } - } -} - - -impl Server -where S: NewService, Response = Response>, - B: Body, - E: Clone, -{ - /// Produces a future that is satisfied once the h2 connection has been initialized. - pub fn serve(&self, io: T) -> Connection - where T: AsyncRead + AsyncWrite, - { - self.serve_modified(io, ()) - } - - pub fn serve_modified(&self, io: T, modify: F) -> Connection - where T: AsyncRead + AsyncWrite, - F: Modify, - { - // Clone a handle to the executor so that it can be moved into the - // connection handle - let executor = self.executor.clone(); - - let service = self.new_service.new_service() - .map_err(Either::B as MapErrB); - - // TODO we should specify initial settings here! - let handshake = self.builder.handshake(io) - .map_err(Either::A as MapErrA); - - Connection { - state: State::Init(handshake.join(service)), - executor, - modify, - } - } -} - -// B doesn't need to be Clone, it's just a marker type. -impl Clone for Server -where - S: NewService + Clone, - E: Clone, - B: Body, -{ - fn clone(&self) -> Self { - Server { - new_service: self.new_service.clone(), - executor: self.executor.clone(), - builder: self.builder.clone(), - _p: PhantomData, - } - } -} - -// ===== impl Connection ===== - -impl Connection -where T: AsyncRead + AsyncWrite, - S: NewService, Response = Response>, - B: Body, -{ - fn is_ready(&self) -> bool { - use self::State::*; - - match self.state { - Ready { .. } => true, - _ => false, - } - } - - fn try_ready(&mut self) -> Poll<(), Error> { - use self::State::*; - - let (connection, service) = match self.state { - Init(ref mut join) => try_ready!(join.poll().map_err(Error::from_init)), - _ => unreachable!(), - }; - - self.state = Ready { connection, service }; - - Ok(().into()) - } -} - -impl Future for Connection -where T: AsyncRead + AsyncWrite, - S: NewService, Response = Response>, - E: Executor::Future, B>>, - B: Body + 'static, - F: Modify, -{ - type Item = (); - type Error = Error; - - fn poll(&mut self) -> Poll { - if !self.is_ready() { - // Advance the initialization of the service and HTTP/2.0 connection - try_ready!(self.try_ready()); - } - - let (connection, service) = match self.state { - State::Ready { ref mut connection, ref mut service } => { - (connection, service) - } - _ => unreachable!(), - }; - - loop { - // Make sure the service is ready - let ready = service.poll_ready() - // TODO: Don't dump the error - .map_err(Error::Service); - - try_ready!(ready); - - let next = connection.poll() - .map_err(Error::Protocol); - - let (request, respond) = match try_ready!(next) { - Some(next) => next, - None => return Ok(().into()), - }; - - let (parts, body) = request.into_parts(); - - // This is really unfortunate, but the `http` currently lacks the - // APIs to do this better :( - let mut request = Request::from_parts(parts, ()); - self.modify.modify(&mut request); - - let (parts, _) = request.into_parts(); - let request = Request::from_parts(parts, RecvBody::new(body)); - - // Dispatch the request to the service - let response = service.call(request); - - // Spawn a new task to process the response future - if let Err(_) = self.executor.execute(Background::new(respond, response)) { - return Err(Error::Execute) - } - } - } -} - -// ===== impl Modify ===== - -impl Modify for T -where T: FnMut(&mut Request<()>) -{ - fn modify(&mut self, request: &mut Request<()>) { - (*self)(request); - } -} - -impl Modify for () { - fn modify(&mut self, _: &mut Request<()>) { - } -} - -// ===== impl Background ===== - -impl Background -where T: Future, - B: Body, -{ - fn new(respond: Respond, response: T) -> Self { - Background { - state: BackgroundState::Respond { - respond, - response, - }, - } - } -} - -impl Future for Background -where T: Future>, - B: Body, -{ - type Item = (); - type Error = (); - - fn poll(&mut self) -> Poll<(), ()> { - use self::BackgroundState::*; - - loop { - let flush = match self.state { - Respond { ref mut respond, ref mut response } => { - use flush::Flush; - - let response = try_ready!(response.poll().map_err(|_| { - // TODO: do something better the error? - let reason = Reason::INTERNAL_ERROR; - respond.send_reset(reason); - })); - - let (parts, body) = response.into_parts(); - - // Check if the response is immediately an end-of-stream. - let end_stream = body.is_end_stream(); - trace!("send_response eos={} {:?}", end_stream, parts); - - // Try sending the response. - let response = Response::from_parts(parts, ()); - match respond.send_response(response, end_stream) { - Ok(stream) => { - if end_stream { - // Nothing more to do - return Ok(().into()); - } - - // Transition to flushing the body - Flush::new(body, stream) - } - Err(_) => { - // TODO: Do something with the error? - return Ok(().into()); - } - } - } - Flush(ref mut flush) => return flush.poll(), - }; - - self.state = Flush(flush); - } - } -} - -// ===== impl Error ===== - -impl Error -where S: NewService, -{ - fn from_init(err: Either) -> Self { - match err { - Either::A(err) => Error::Handshake(err), - Either::B(err) => Error::NewService(err), - } - } -}