From 9c521d162aaca815e66a35ed5642331f2885ea89 Mon Sep 17 00:00:00 2001
From: Jiahao XU <Jiahao_XU@outlook.com>
Date: Wed, 9 Aug 2023 17:44:10 +1000
Subject: [PATCH] Enable unstable feature `reqwest/http3` in CI (#1261)

For dev and release build, so that pre-built binaries of
`cargo-binstall` can utilize http3 protocol.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
---
 .github/workflows/ci.yml              |   1 +
 .github/workflows/release-build.yml   |   1 +
 Cargo.lock                            | 143 ++++++++++++++++++++++++--
 crates/bin/Cargo.toml                 |   4 +
 crates/binstalk-downloader/Cargo.toml |   7 ++
 crates/binstalk/Cargo.toml            |   4 +
 justfile                              |  14 ++-
 7 files changed, 163 insertions(+), 11 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e1537371..14358719 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -23,6 +23,7 @@ concurrency:
 env:
   CARGO_TERM_COLOR: always
   CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
+  JUST_ENABLE_H3: true
 
 jobs:
   test:
diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml
index 742e7288..e9e4d4cb 100644
--- a/.github/workflows/release-build.yml
+++ b/.github/workflows/release-build.yml
@@ -48,6 +48,7 @@ jobs:
       JUST_USE_CARGO_ZIGBUILD: ${{ matrix.c }}
       JUST_FOR_RELEASE: true
       JUST_USE_AUDITABLE: true
+      JUST_ENABLE_H3: true
 
     steps:
     - uses: actions/checkout@v3
diff --git a/Cargo.lock b/Cargo.lock
index 36588b25..5cf51c81 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -858,6 +858,15 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
 [[package]]
 name = "fastrand"
 version = "2.0.0"
@@ -940,6 +949,21 @@ dependencies = [
  "windows-sys",
 ]
 
+[[package]]
+name = "futures"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
 [[package]]
 name = "futures-channel"
 version = "0.3.28"
@@ -947,6 +971,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
 dependencies = [
  "futures-core",
+ "futures-sink",
 ]
 
 [[package]]
@@ -955,6 +980,17 @@ version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
 
+[[package]]
+name = "futures-executor"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
 [[package]]
 name = "futures-io"
 version = "0.3.28"
@@ -990,6 +1026,7 @@ version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
 dependencies = [
+ "futures-channel",
  "futures-core",
  "futures-io",
  "futures-macro",
@@ -1730,7 +1767,7 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b85d89dc728613e26e0ed952a19583744e7f5240fcd4aa30d6c824ffd8b52f0f"
 dependencies = [
- "fastrand",
+ "fastrand 2.0.0",
 ]
 
 [[package]]
@@ -1820,6 +1857,34 @@ dependencies = [
  "tracing",
 ]
 
+[[package]]
+name = "h3"
+version = "0.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6de6ca43eed186fd055214af06967b0a7a68336cefec7e8a4004e96efeaccb9e"
+dependencies = [
+ "bytes",
+ "fastrand 1.9.0",
+ "futures-util",
+ "http",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "h3-quinn"
+version = "0.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d4a1a1763e4f3e82ee9f1ecf2cf862b22cc7316ebe14684e42f94532b5ec64d"
+dependencies = [
+ "bytes",
+ "futures",
+ "h3",
+ "quinn 0.10.2",
+ "quinn-proto 0.10.2",
+ "tokio-util",
+]
+
 [[package]]
 name = "hashbrown"
 version = "0.12.3"
@@ -2012,6 +2077,15 @@ dependencies = [
  "hashbrown 0.14.0",
 ]
 
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
 [[package]]
 name = "io-close"
 version = "0.3.7"
@@ -2634,8 +2708,8 @@ dependencies = [
  "futures-channel",
  "futures-util",
  "fxhash",
- "quinn-proto",
- "quinn-udp",
+ "quinn-proto 0.8.4",
+ "quinn-udp 0.1.4",
  "rustls 0.20.8",
  "thiserror",
  "tokio",
@@ -2643,6 +2717,23 @@ dependencies = [
  "webpki",
 ]
 
+[[package]]
+name = "quinn"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75"
+dependencies = [
+ "bytes",
+ "pin-project-lite",
+ "quinn-proto 0.10.2",
+ "quinn-udp 0.4.0",
+ "rustc-hash",
+ "rustls 0.21.6",
+ "thiserror",
+ "tokio",
+ "tracing",
+]
+
 [[package]]
 name = "quinn-proto"
 version = "0.8.4"
@@ -2663,6 +2754,23 @@ dependencies = [
  "webpki",
 ]
 
+[[package]]
+name = "quinn-proto"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8c8bb234e70c863204303507d841e7fa2295e95c822b2bb4ca8ebf57f17b1cb"
+dependencies = [
+ "bytes",
+ "rand",
+ "ring",
+ "rustc-hash",
+ "rustls 0.21.6",
+ "slab",
+ "thiserror",
+ "tinyvec",
+ "tracing",
+]
+
 [[package]]
 name = "quinn-udp"
 version = "0.1.4"
@@ -2671,12 +2779,25 @@ checksum = "b07946277141531aea269befd949ed16b2c85a780ba1043244eda0969e538e54"
 dependencies = [
  "futures-util",
  "libc",
- "quinn-proto",
+ "quinn-proto 0.8.4",
  "socket2 0.4.9",
  "tokio",
  "tracing",
 ]
 
+[[package]]
+name = "quinn-udp"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6df19e284d93757a9fb91d63672f7741b129246a669db09d1c0063071debc0c0"
+dependencies = [
+ "bytes",
+ "libc",
+ "socket2 0.5.3",
+ "tracing",
+ "windows-sys",
+]
+
 [[package]]
 name = "quote"
 version = "1.0.32"
@@ -2795,9 +2916,12 @@ dependencies = [
  "base64 0.21.2",
  "bytes",
  "encoding_rs",
+ "futures-channel",
  "futures-core",
  "futures-util",
  "h2",
+ "h3",
+ "h3-quinn",
  "http",
  "http-body",
  "hyper",
@@ -2811,6 +2935,7 @@ dependencies = [
  "once_cell",
  "percent-encoding",
  "pin-project-lite",
+ "quinn 0.10.2",
  "rustls 0.21.6",
  "rustls-pemfile 1.0.3",
  "serde",
@@ -2862,6 +2987,12 @@ version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
 
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
 [[package]]
 name = "rustc_version"
 version = "0.4.0"
@@ -3296,7 +3427,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651"
 dependencies = [
  "cfg-if",
- "fastrand",
+ "fastrand 2.0.0",
  "redox_syscall 0.3.5",
  "rustix",
  "windows-sys",
@@ -3630,7 +3761,7 @@ dependencies = [
  "ipnet",
  "lazy_static",
  "native-tls",
- "quinn",
+ "quinn 0.8.5",
  "rand",
  "ring",
  "rustls 0.20.8",
diff --git a/crates/bin/Cargo.toml b/crates/bin/Cargo.toml
index 851362c1..1e226507 100644
--- a/crates/bin/Cargo.toml
+++ b/crates/bin/Cargo.toml
@@ -67,6 +67,10 @@ native-tls = ["binstalk/native-tls"]
 
 trust-dns = ["binstalk/trust-dns"]
 
+# Experimental HTTP/3 client, this would require `--cfg reqwest_unstable`
+# to be passed to `rustc`.
+http3 = ["binstalk/http3"]
+
 zstd-thin = ["binstalk/zstd-thin"]
 cross-lang-fat-lto = ["binstalk/cross-lang-fat-lto"]
 
diff --git a/crates/binstalk-downloader/Cargo.toml b/crates/binstalk-downloader/Cargo.toml
index 7fa4b3c8..6c6d873d 100644
--- a/crates/binstalk-downloader/Cargo.toml
+++ b/crates/binstalk-downloader/Cargo.toml
@@ -23,6 +23,9 @@ generic-array = "0.14.7"
 httpdate = "1.0.2"
 reqwest = { version = "0.11.18", features = ["stream", "gzip", "brotli", "deflate"], default-features = false }
 percent-encoding = "2.2.0"
+# Pull in due to https://github.com/seanmonstar/reqwest/pull/1846 , please
+# remove this once new reqwest release is out.
+quinn = { version = "0.10", default-features = false, features = ["runtime-tokio"], optional = true }
 serde = { version = "1.0.163", features = ["derive"], optional = true }
 serde-tuple-vec-map = "1.0.1"
 serde_json = { version = "1.0.96", optional = true }
@@ -77,6 +80,10 @@ native-tls = ["__tls", "reqwest/native-tls", "trust-dns-resolver?/dns-over-nativ
 # Enable trust-dns-resolver so that features on it will also be enabled.
 trust-dns = ["trust-dns-resolver", "reqwest/trust-dns"]
 
+# Experimental HTTP/3 client, this would require `--cfg reqwest_unstable`
+# to be passed to `rustc`.
+http3 = ["reqwest/http3", "dep:quinn"]
+
 zstd-thin = ["zstd/thin"]
 
 cross-lang-fat-lto = ["zstd/fat-lto"]
diff --git a/crates/binstalk/Cargo.toml b/crates/binstalk/Cargo.toml
index 469eeb30..d7130803 100644
--- a/crates/binstalk/Cargo.toml
+++ b/crates/binstalk/Cargo.toml
@@ -65,6 +65,10 @@ native-tls = ["binstalk-downloader/native-tls"]
 
 trust-dns = ["binstalk-downloader/trust-dns"]
 
+# Experimental HTTP/3 client, this would require `--cfg reqwest_unstable`
+# to be passed to `rustc`.
+http3 = ["binstalk-downloader/http3"]
+
 zstd-thin = ["binstalk-downloader/zstd-thin"]
 cross-lang-fat-lto = ["binstalk-downloader/cross-lang-fat-lto"]
 
diff --git a/justfile b/justfile
index 1bdf106c..3c2ad504 100644
--- a/justfile
+++ b/justfile
@@ -11,6 +11,7 @@ glibc-version := env_var_or_default("GLIBC_VERSION", "")
 use-auditable := env_var_or_default("JUST_USE_AUDITABLE", "")
 timings := env_var_or_default("JUST_TIMINGS", "")
 build-std := env_var_or_default("JUST_BUILD_STD", "")
+enable-h3 := env_var_or_default("JUST_ENABLE_H3", "")
 
 export BINSTALL_LOG_LEVEL := if env_var_or_default("RUNNER_DEBUG", "0") == "1" { "debug" } else { "info" }
 export BINSTALL_RATE_LIMIT := "30/1"
@@ -97,10 +98,13 @@ git-max-perf-feature := if target == "x86_64-apple-darwin" {
     ""
 }
 
-cargo-features := trim_end_match(if override-features != "" { override-features
-    } else if (cargo-profile / ci-or-no) == "dev/ci" { "git,rustls,fancy-with-backtrace,zstd-thin,log_max_level_debug" + git-max-perf-feature + (if support-pkg-config != "" { ",pkg-config" } else { "" }) + extra-features
-    } else if (cargo-profile / ci-or-no) == "release/ci" { "git,static,rustls,trust-dns,fancy-no-backtrace,zstd-thin,log_release_max_level_debug,cross-lang-fat-lto"  + git-max-perf-feature + extra-features
-    } else { extra-features
+h3-features := if enable-h3 != "" { ",http3" } else { "" }
+cargo-features := trim_end_match(if override-features != "" { override-features + h3-features
+    } else if (cargo-profile / ci-or-no) == "dev/ci" { "git,rustls,fancy-with-backtrace,zstd-thin,log_max_level_debug" + git-max-perf-feature + (if support-pkg-config != "" { ",pkg-config" } else { "" }) + h3-features + extra-features
+    } else if (cargo-profile / ci-or-no) == "release/ci" { "git,static,rustls,trust-dns,fancy-no-backtrace,zstd-thin,log_release_max_level_debug,cross-lang-fat-lto"  + git-max-perf-feature + h3-features + extra-features
+    } else if extra-features != "" { extra-features + h3-features
+    } else if enable-h3 != "" { "http3"
+    } else { ""
 }, ",")
 
 # it seems we can't split debuginfo for non-buildstd builds
@@ -174,7 +178,7 @@ target-glibc-ver-postfix := if glibc-version != "" {
 
 cargo-check-args := (" --target ") + (target) + (target-glibc-ver-postfix) + (cargo-buildstd) + (if extra-build-args != "" { " " + extra-build-args } else { "" }) + (cargo-split-debuginfo) + (win-arm64-ring16)
 cargo-build-args := (if for-release != "" { " --release" } else { "" }) + (cargo-check-args) + (cargo-no-default-features) + (if cargo-features != "" { " --features " + cargo-features } else { "" }) + (if timings != "" { " --timings" } else { "" })
-export RUSTFLAGS := (linker-plugin-lto) + (rustc-gcclibs) + (rustc-miropt) + (rust-lld) + (rustc-icf)
+export RUSTFLAGS := (linker-plugin-lto) + (rustc-gcclibs) + (rustc-miropt) + (rust-lld) + (rustc-icf) + (if enable-h3 != "" { " --cfg reqwest_unstable" } else { "" })
 
 
 # libblocksruntime-dev provides compiler-rt