Squashed 'third_party/rules_rust/' content from commit bf59038ca

git-subtree-dir: third_party/rules_rust
git-subtree-split: bf59038cac11798cbaef9f3bf965bad8182b97fa
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
Change-Id: I5a20e403203d670df467ea97dde9a4ac40339a8d
diff --git a/examples/proto/BUILD.bazel b/examples/proto/BUILD.bazel
new file mode 100644
index 0000000..9ddf0e3
--- /dev/null
+++ b/examples/proto/BUILD.bazel
@@ -0,0 +1,8 @@
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+package(default_visibility = ["//proto:__subpackages__"])
+
+proto_library(
+    name = "common",
+    srcs = ["common.proto"],
+)
diff --git a/examples/proto/basic/BUILD.bazel b/examples/proto/basic/BUILD.bazel
new file mode 100644
index 0000000..9853a2e
--- /dev/null
+++ b/examples/proto/basic/BUILD.bazel
@@ -0,0 +1,24 @@
+load("@rules_rust//proto:proto.bzl", "rust_proto_library")
+load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library")
+
+package(default_visibility = ["//proto:__subpackages__"])
+
+rust_proto_library(
+    name = "common_proto_rust",
+    deps = ["//proto:common"],
+)
+
+rust_library(
+    name = "common_lib",
+    srcs = ["lib.rs"],
+    deps = [":common_proto_rust"],
+)
+
+rust_binary(
+    name = "common_bin",
+    srcs = ["main.rs"],
+    deps = [
+        ":common_lib",
+        ":common_proto_rust",
+    ],
+)
diff --git a/examples/proto/basic/lib.rs b/examples/proto/basic/lib.rs
new file mode 100644
index 0000000..2146b3c
--- /dev/null
+++ b/examples/proto/basic/lib.rs
@@ -0,0 +1,5 @@
+extern crate common_proto_rust;
+
+pub fn do_something(_x: &common_proto_rust::Config) -> bool {
+    true
+}
diff --git a/examples/proto/basic/main.rs b/examples/proto/basic/main.rs
new file mode 100644
index 0000000..12ed82f
--- /dev/null
+++ b/examples/proto/basic/main.rs
@@ -0,0 +1,6 @@
+extern crate common_lib;
+extern crate common_proto_rust;
+
+pub fn main() {
+    common_lib::do_something(&common_proto_rust::Config::new());
+}
diff --git a/examples/proto/common.proto b/examples/proto/common.proto
new file mode 100644
index 0000000..56bac18
--- /dev/null
+++ b/examples/proto/common.proto
@@ -0,0 +1,13 @@
+syntax = "proto3";
+
+option java_package = "org.pubref.rules_protobuf.examples";
+option java_outer_classname = "CommonProto";
+
+package common;
+
+// A configuration object.  This is used to test the viability of
+// protobuf imports.
+message Config {
+  bool verbose = 1;
+}
+
diff --git a/examples/proto/helloworld/BUILD.bazel b/examples/proto/helloworld/BUILD.bazel
new file mode 100644
index 0000000..db30a9d
--- /dev/null
+++ b/examples/proto/helloworld/BUILD.bazel
@@ -0,0 +1,25 @@
+load("@rules_proto//proto:defs.bzl", "proto_library")
+load("@rules_rust//proto:proto.bzl", "rust_grpc_library")
+load("@rules_rust//rust:defs.bzl", "rust_test")
+
+proto_library(
+    name = "helloworld",
+    srcs = ["helloworld.proto"],
+    deps = ["//proto:common"],
+)
+
+rust_grpc_library(
+    name = "helloworld_proto",
+    visibility = ["//proto/helloworld:__subpackages__"],
+    deps = [":helloworld"],
+)
+
+rust_test(
+    name = "helloworld_test",
+    srcs = ["helloworld_test.rs"],
+    data = [
+        "//proto/helloworld/greeter_client",
+        "//proto/helloworld/greeter_server",
+    ],
+    deps = ["@rules_rust//tools/runfiles"],
+)
diff --git a/examples/proto/helloworld/greeter_client/BUILD.bazel b/examples/proto/helloworld/greeter_client/BUILD.bazel
new file mode 100644
index 0000000..b35435e
--- /dev/null
+++ b/examples/proto/helloworld/greeter_client/BUILD.bazel
@@ -0,0 +1,11 @@
+load("@rules_rust//proto:toolchain.bzl", "GRPC_COMPILE_DEPS")
+load("@rules_rust//rust:defs.bzl", "rust_binary")
+
+rust_binary(
+    name = "greeter_client",
+    srcs = ["greeter_client.rs"],
+    visibility = ["//proto/helloworld:__subpackages__"],
+    deps = [
+        "//proto/helloworld:helloworld_proto",
+    ] + GRPC_COMPILE_DEPS,
+)
diff --git a/examples/proto/helloworld/greeter_client/greeter_client.rs b/examples/proto/helloworld/greeter_client/greeter_client.rs
new file mode 100644
index 0000000..ade62eb
--- /dev/null
+++ b/examples/proto/helloworld/greeter_client/greeter_client.rs
@@ -0,0 +1,44 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// 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.
+
+extern crate grpc;
+extern crate helloworld_proto;
+
+use grpc::ClientStubExt;
+use std::env;
+use std::str::FromStr;
+
+use helloworld_proto::*;
+
+fn parse_args() -> (String, u16) {
+    let mut name = "world".to_owned();
+    let mut port = 50051;
+    for arg in env::args().skip(1) {
+        if let Some(argp) = arg.strip_prefix("-p=") {
+            port = u16::from_str(argp).unwrap()
+        } else {
+            name = arg.to_owned();
+        }
+    }
+    (name, port)
+}
+
+fn main() {
+    let (name, port) = parse_args();
+    let client = GreeterClient::new_plain("::1", port, Default::default()).unwrap();
+    let mut req = HelloRequest::new();
+    req.set_name(name);
+    let resp = client.say_hello(grpc::RequestOptions::new(), req);
+    println!("{:?}", resp.wait());
+}
diff --git a/examples/proto/helloworld/greeter_server/BUILD.bazel b/examples/proto/helloworld/greeter_server/BUILD.bazel
new file mode 100644
index 0000000..616ecb5
--- /dev/null
+++ b/examples/proto/helloworld/greeter_server/BUILD.bazel
@@ -0,0 +1,11 @@
+load("@rules_rust//proto:toolchain.bzl", "GRPC_COMPILE_DEPS")
+load("@rules_rust//rust:defs.bzl", "rust_binary")
+
+rust_binary(
+    name = "greeter_server",
+    srcs = ["greeter_server.rs"],
+    visibility = ["//proto/helloworld:__subpackages__"],
+    deps = [
+        "//proto/helloworld:helloworld_proto",
+    ] + GRPC_COMPILE_DEPS,
+)
diff --git a/examples/proto/helloworld/greeter_server/greeter_server.rs b/examples/proto/helloworld/greeter_server/greeter_server.rs
new file mode 100644
index 0000000..17a09a1
--- /dev/null
+++ b/examples/proto/helloworld/greeter_server/greeter_server.rs
@@ -0,0 +1,58 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// 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.
+
+extern crate grpc;
+extern crate helloworld_proto;
+extern crate tls_api_stub;
+
+use std::env;
+use std::str::FromStr;
+use std::thread;
+
+use helloworld_proto::*;
+
+struct GreeterImpl;
+
+impl Greeter for GreeterImpl {
+    fn say_hello(
+        &self,
+        _m: grpc::RequestOptions,
+        req: HelloRequest,
+    ) -> grpc::SingleResponse<HelloReply> {
+        let mut r = HelloReply::new();
+        let name = if req.get_name().is_empty() {
+            "world"
+        } else {
+            req.get_name()
+        };
+        println!("greeting request from {}", name);
+        r.set_message(format!("Hello {}", name));
+        grpc::SingleResponse::completed(r)
+    }
+}
+
+fn main() {
+    let mut server = grpc::ServerBuilder::<tls_api_stub::TlsAcceptor>::new();
+    let port = u16::from_str(&env::args().nth(1).unwrap_or_else(|| "50051".to_owned())).unwrap();
+    server.http.set_port(port);
+    server.add_service(GreeterServer::new_service_def(GreeterImpl));
+    server.http.set_cpu_pool_threads(4);
+    let server = server.build().expect("server");
+    let port = server.local_addr().port().unwrap();
+    println!("greeter server started on port {}", port);
+
+    loop {
+        thread::park();
+    }
+}
diff --git a/examples/proto/helloworld/helloworld.proto b/examples/proto/helloworld/helloworld.proto
new file mode 100644
index 0000000..e0c7598
--- /dev/null
+++ b/examples/proto/helloworld/helloworld.proto
@@ -0,0 +1,23 @@
+
+syntax = "proto3";
+
+import "proto/common.proto";
+
+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;
+  common.Config config = 2;
+}
+
+// The response message containing the greetings
+message HelloReply {
+  string message = 1;
+}
diff --git a/examples/proto/helloworld/helloworld_test.rs b/examples/proto/helloworld/helloworld_test.rs
new file mode 100644
index 0000000..c82e474
--- /dev/null
+++ b/examples/proto/helloworld/helloworld_test.rs
@@ -0,0 +1,109 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// 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.
+
+// Integration tests for the greeter client/server
+extern crate runfiles;
+
+use std::io::BufRead;
+use std::io::BufReader;
+use std::process::{Child, Command, Stdio};
+use std::str::FromStr;
+
+use runfiles::Runfiles;
+
+struct ServerInfo {
+    process: Child,
+    port: u16,
+}
+
+macro_rules! assert_contains {
+    ($s: expr, $e: expr) => {
+        assert!($s.find($e).is_some());
+    };
+}
+
+impl ServerInfo {
+    fn new() -> ServerInfo {
+        let r = Runfiles::create().unwrap();
+        let mut c =
+            Command::new(r.rlocation("examples/proto/helloworld/greeter_server/greeter_server"))
+                .arg("0")
+                .stdout(Stdio::piped())
+                .spawn()
+                .expect("Unable to start server");
+        let mut port: u16 = 0;
+        {
+            let mut stdout = BufReader::new(c.stdout.as_mut().expect("Failed to open stdout"));
+            let port_prefix = "greeter server started on port ";
+            while port == 0 {
+                let mut line = String::new();
+                stdout
+                    .read_line(&mut line)
+                    .expect("Waiting for server startup");
+                line = line.trim().to_owned();
+                if let Some(argp) = line.strip_prefix(port_prefix) {
+                    port = u16::from_str(argp)
+                        .unwrap_or_else(|_| panic!("Invalid port number {}", argp))
+                }
+            }
+        }
+        println!("Started server on port {}", port);
+        ServerInfo { process: c, port }
+    }
+
+    fn run_client_impl(&self, arg: Option<String>) -> String {
+        let r = Runfiles::create().unwrap();
+
+        let mut cmd0 =
+            Command::new(r.rlocation("examples/proto/helloworld/greeter_client/greeter_client"));
+        let cmd = cmd0.arg(format!("-p={}", self.port));
+
+        let output = if let Some(s) = arg { cmd.arg(s) } else { cmd }
+            .output()
+            .expect("Unable to start client");
+        assert!(output.status.success());
+        String::from_utf8(output.stdout).expect("Non UTF-8 output from the client")
+    }
+
+    fn run_client(&self) -> String {
+        self.run_client_impl(None)
+    }
+    fn run_client_with_arg(&self, arg: &str) -> String {
+        self.run_client_impl(Some(arg.to_owned()))
+    }
+
+    fn expect_log(&mut self, log: &str) {
+        let mut reader =
+            BufReader::new(self.process.stdout.as_mut().expect("Failed to open stdout"));
+        let mut line = String::new();
+        reader
+            .read_line(&mut line)
+            .expect("Failed to read line from the server");
+        assert_contains!(line, log);
+    }
+
+    fn destroy(&mut self) {
+        self.process.kill().unwrap();
+    }
+}
+
+#[test]
+fn test_client_server() {
+    let mut s = ServerInfo::new();
+    assert_contains!(s.run_client(), "message: \"Hello world\"");
+    s.expect_log("greeting request from world");
+    assert_contains!(s.run_client_with_arg("thou"), "message: \"Hello thou\"");
+    s.expect_log("greeting request from thou");
+    s.destroy();
+}