Merge remote-tracking branch 'origin/upstream' am: 93224a77fa am: d87743295d

Original change: undetermined

Change-Id: I7696e82825b8c553ed3757cd2efd70a9292702da
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..a69385b
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,50 @@
+// This file is generated by cargo_embargo.
+// Do not modify this file after the first "rust_*" or "genrule" module
+// because the changes will be overridden on upgrade.
+// Content before the first "rust_*" or "genrule" module is preserved.
+
+package {
+    default_applicable_licenses: ["external_rust_crates_libtower_layer_license"],
+}
+
+license {
+    name: "external_rust_crates_libtower_layer_license",
+    visibility: [":__subpackages__"],
+    license_kinds: ["SPDX-license-identifier-MIT"],
+    license_text: ["LICENSE"],
+}
+
+rust_library {
+    name: "libtower_layer",
+    host_supported: true,
+    crate_name: "tower_layer",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.3.2",
+    crate_root: "src/lib.rs",
+    edition: "2018",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    product_available: true,
+    vendor_available: true,
+}
+
+rust_test {
+    name: "tower-layer_test_src_lib",
+    host_supported: true,
+    crate_name: "tower_layer",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.3.2",
+    crate_root: "src/lib.rs",
+    test_suites: ["general-tests"],
+    auto_gen_config: true,
+    test_options: {
+        unit_test: true,
+    },
+    edition: "2018",
+    rustlibs: [
+        "libtower",
+        "libtower_service",
+    ],
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..761e9a4
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,34 @@
+# 0.3.2 (October 7, 2022)
+
+- Implement `Layer` for tuples of up to 16 elements ([#694])
+
+[#694]: https://github.com/tower-rs/tower/pull/694
+
+# 0.3.1 (January 7, 2021)
+
+- Added `layer_fn`, for constructing a `Layer` from a function taking
+  a `Service` and returning a different `Service` ([#491])
+- Added an implementation of `Layer` for `&Layer` ([#446])
+- Multiple documentation improvements ([#487], [#490])
+
+[#491]: https://github.com/tower-rs/tower/pull/491
+[#446]: https://github.com/tower-rs/tower/pull/446
+[#487]: https://github.com/tower-rs/tower/pull/487
+[#490]: https://github.com/tower-rs/tower/pull/490
+
+# 0.3.0 (November 29, 2019)
+
+- Move layer builder from `tower-util` to tower-layer.
+
+# 0.3.0-alpha.2 (September 30, 2019)
+
+- Move to `futures-*-preview 0.3.0-alpha.19`
+- Move to `pin-project 0.4`
+
+# 0.3.0-alpha.1 (September 11, 2019)
+
+- Move to `std::future`
+
+# 0.1.0 (April 26, 2019)
+
+- Initial release
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..0d7736e
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,35 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "tower-layer"
+version = "0.3.2"
+authors = ["Tower Maintainers <[email protected]>"]
+description = """
+Decorates a `Service` to allow easy composition between `Service`s.
+"""
+homepage = "https://github.com/tower-rs/tower"
+readme = "README.md"
+categories = [
+    "asynchronous",
+    "network-programming",
+]
+license = "MIT"
+repository = "https://github.com/tower-rs/tower"
+
+[dependencies]
+
+[dev-dependencies.tower]
+version = "0.4"
+
+[dev-dependencies.tower-service]
+version = "0.3.0"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..70bedd2
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,25 @@
+[package]
+name = "tower-layer"
+# When releasing to crates.io:
+# - Update doc url
+#   - Cargo.toml
+#   - README.md
+# - Update CHANGELOG.md.
+# - Create "v0.1.x" git tag.
+version = "0.3.2"
+authors = ["Tower Maintainers <[email protected]>"]
+license = "MIT"
+readme = "README.md"
+repository = "https://github.com/tower-rs/tower"
+homepage = "https://github.com/tower-rs/tower"
+description = """
+Decorates a `Service` to allow easy composition between `Service`s.
+"""
+categories = ["asynchronous", "network-programming"]
+edition = "2018"
+
+[dependencies]
+
+[dev-dependencies]
+tower-service = { version = "0.3.0", path = "../tower-service" }
+tower = { version = "0.4", path = "../tower" }
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..b980cac
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2019 Tower Contributors
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..85403fb
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,20 @@
+name: "tower-layer"
+description: "()"
+third_party {
+  identifier {
+    type: "crates.io"
+    value: "tower-layer"
+  }
+  identifier {
+    type: "Archive"
+    value: "https://static.crates.io/crates/tower-layer/tower-layer-0.3.2.crate"
+    primary_source: true
+  }
+  version: "0.3.2"
+  license_type: NOTICE
+  last_upgrade_date {
+    year: 2024
+    month: 5
+    day: 24
+  }
+}
diff --git a/MODULE_LICENSE_MIT b/MODULE_LICENSE_MIT
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_MIT
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..48bea6e
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 688011
+include platform/prebuilts/rust:main:/OWNERS
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..48f9dbb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,43 @@
+# Tower Layer
+
+Decorates a [Tower] `Service`, transforming either the request or the response.
+
+[![Crates.io][crates-badge]][crates-url]
+[![Documentation][docs-badge]][docs-url]
+[![Documentation (master)][docs-master-badge]][docs-master-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
+
+[crates-badge]: https://img.shields.io/crates/v/tower-layer.svg
+[crates-url]: https://crates.io/crates/tower-layer
+[docs-badge]: https://docs.rs/tower-layer/badge.svg
+[docs-url]: https://docs.rs/tower-layer
+[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
+[docs-master-url]: https://tower-rs.github.io/tower/tower_layer
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: LICENSE
+[actions-badge]: https://github.com/tower-rs/tower/workflows/CI/badge.svg
+[actions-url]:https://github.com/tower-rs/tower/actions?query=workflow%3ACI
+[discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white
+[discord-url]: https://discord.gg/EeF3cQw
+
+## Overview
+
+Often, many of the pieces needed for writing network applications can be
+reused across multiple services. The `Layer` trait can be used to write
+reusable components that can be applied to very different kinds of services;
+for example, it can be applied to services operating on different protocols,
+and to both the client and server side of a network transaction.
+
+## License
+
+This project is licensed under the [MIT license](LICENSE).
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Tower by you, shall be licensed as MIT, without any additional
+terms or conditions.
+
+[Tower]: https://crates.io/crates/tower
\ No newline at end of file
diff --git a/cargo_embargo.json b/cargo_embargo.json
new file mode 100644
index 0000000..8c587f2
--- /dev/null
+++ b/cargo_embargo.json
@@ -0,0 +1,5 @@
+{
+  "features": [],
+  "run_cargo": false,
+  "tests": true
+}
diff --git a/src/identity.rs b/src/identity.rs
new file mode 100644
index 0000000..5ce805b
--- /dev/null
+++ b/src/identity.rs
@@ -0,0 +1,37 @@
+use super::Layer;
+use std::fmt;
+
+/// A no-op middleware.
+///
+/// When wrapping a [`Service`], the [`Identity`] layer returns the provided
+/// service without modifying it.
+///
+/// [`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html
+#[derive(Default, Clone)]
+pub struct Identity {
+    _p: (),
+}
+
+impl Identity {
+    /// Create a new [`Identity`] value
+    pub fn new() -> Identity {
+        Identity { _p: () }
+    }
+}
+
+/// Decorates a [`Service`], transforming either the request or the response.
+///
+/// [`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html
+impl<S> Layer<S> for Identity {
+    type Service = S;
+
+    fn layer(&self, inner: S) -> Self::Service {
+        inner
+    }
+}
+
+impl fmt::Debug for Identity {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Identity").finish()
+    }
+}
diff --git a/src/layer_fn.rs b/src/layer_fn.rs
new file mode 100644
index 0000000..06f6e0e
--- /dev/null
+++ b/src/layer_fn.rs
@@ -0,0 +1,114 @@
+use super::Layer;
+use std::fmt;
+
+/// Returns a new [`LayerFn`] that implements [`Layer`] by calling the
+/// given function.
+///
+/// The [`Layer::layer`] method takes a type implementing [`Service`] and
+/// returns a different type implementing [`Service`]. In many cases, this can
+/// be implemented by a function or a closure. The [`LayerFn`] helper allows
+/// writing simple [`Layer`] implementations without needing the boilerplate of
+/// a new struct implementing [`Layer`].
+///
+/// # Example
+/// ```rust
+/// # use tower::Service;
+/// # use std::task::{Poll, Context};
+/// # use tower_layer::{Layer, layer_fn};
+/// # use std::fmt;
+/// # use std::convert::Infallible;
+/// #
+/// // A middleware that logs requests before forwarding them to another service
+/// pub struct LogService<S> {
+///     target: &'static str,
+///     service: S,
+/// }
+///
+/// impl<S, Request> Service<Request> for LogService<S>
+/// where
+///     S: Service<Request>,
+///     Request: fmt::Debug,
+/// {
+///     type Response = S::Response;
+///     type Error = S::Error;
+///     type Future = S::Future;
+///
+///     fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+///         self.service.poll_ready(cx)
+///     }
+///
+///     fn call(&mut self, request: Request) -> Self::Future {
+///         // Log the request
+///         println!("request = {:?}, target = {:?}", request, self.target);
+///
+///         self.service.call(request)
+///     }
+/// }
+///
+/// // A `Layer` that wraps services in `LogService`
+/// let log_layer = layer_fn(|service| {
+///     LogService {
+///         service,
+///         target: "tower-docs",
+///     }
+/// });
+///
+/// // An example service. This one uppercases strings
+/// let uppercase_service = tower::service_fn(|request: String| async move {
+///     Ok::<_, Infallible>(request.to_uppercase())
+/// });
+///
+/// // Wrap our service in a `LogService` so requests are logged.
+/// let wrapped_service = log_layer.layer(uppercase_service);
+/// ```
+///
+/// [`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html
+/// [`Layer::layer`]: crate::Layer::layer
+pub fn layer_fn<T>(f: T) -> LayerFn<T> {
+    LayerFn { f }
+}
+
+/// A `Layer` implemented by a closure. See the docs for [`layer_fn`] for more details.
+#[derive(Clone, Copy)]
+pub struct LayerFn<F> {
+    f: F,
+}
+
+impl<F, S, Out> Layer<S> for LayerFn<F>
+where
+    F: Fn(S) -> Out,
+{
+    type Service = Out;
+
+    fn layer(&self, inner: S) -> Self::Service {
+        (self.f)(inner)
+    }
+}
+
+impl<F> fmt::Debug for LayerFn<F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("LayerFn")
+            .field("f", &format_args!("{}", std::any::type_name::<F>()))
+            .finish()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[allow(dead_code)]
+    #[test]
+    fn layer_fn_has_useful_debug_impl() {
+        struct WrappedService<S> {
+            inner: S,
+        }
+        let layer = layer_fn(|svc| WrappedService { inner: svc });
+        let _svc = layer.layer("foo");
+
+        assert_eq!(
+            "LayerFn { f: tower_layer::layer_fn::tests::layer_fn_has_useful_debug_impl::{{closure}} }".to_string(),
+            format!("{:?}", layer),
+        );
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..8dfae3d
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,112 @@
+#![warn(
+    missing_debug_implementations,
+    missing_docs,
+    rust_2018_idioms,
+    unreachable_pub
+)]
+#![forbid(unsafe_code)]
+// `rustdoc::broken_intra_doc_links` is checked on CI
+
+//! Layer traits and extensions.
+//!
+//! A layer decorates an service and provides additional functionality. It
+//! allows other services to be composed with the service that implements layer.
+//!
+//! A middleware implements the [`Layer`] and [`Service`] trait.
+//!
+//! [`Service`]: https://docs.rs/tower/latest/tower/trait.Service.html
+
+mod identity;
+mod layer_fn;
+mod stack;
+mod tuple;
+
+pub use self::{
+    identity::Identity,
+    layer_fn::{layer_fn, LayerFn},
+    stack::Stack,
+};
+
+/// Decorates a [`Service`], transforming either the request or the response.
+///
+/// Often, many of the pieces needed for writing network applications can be
+/// reused across multiple services. The `Layer` trait can be used to write
+/// reusable components that can be applied to very different kinds of services;
+/// for example, it can be applied to services operating on different protocols,
+/// and to both the client and server side of a network transaction.
+///
+/// # Log
+///
+/// Take request logging as an example:
+///
+/// ```rust
+/// # use tower_service::Service;
+/// # use std::task::{Poll, Context};
+/// # use tower_layer::Layer;
+/// # use std::fmt;
+///
+/// pub struct LogLayer {
+///     target: &'static str,
+/// }
+///
+/// impl<S> Layer<S> for LogLayer {
+///     type Service = LogService<S>;
+///
+///     fn layer(&self, service: S) -> Self::Service {
+///         LogService {
+///             target: self.target,
+///             service
+///         }
+///     }
+/// }
+///
+/// // This service implements the Log behavior
+/// pub struct LogService<S> {
+///     target: &'static str,
+///     service: S,
+/// }
+///
+/// impl<S, Request> Service<Request> for LogService<S>
+/// where
+///     S: Service<Request>,
+///     Request: fmt::Debug,
+/// {
+///     type Response = S::Response;
+///     type Error = S::Error;
+///     type Future = S::Future;
+///
+///     fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+///         self.service.poll_ready(cx)
+///     }
+///
+///     fn call(&mut self, request: Request) -> Self::Future {
+///         // Insert log statement here or other functionality
+///         println!("request = {:?}, target = {:?}", request, self.target);
+///         self.service.call(request)
+///     }
+/// }
+/// ```
+///
+/// The above log implementation is decoupled from the underlying protocol and
+/// is also decoupled from client or server concerns. In other words, the same
+/// log middleware could be used in either a client or a server.
+///
+/// [`Service`]: https://docs.rs/tower/latest/tower/trait.Service.html
+pub trait Layer<S> {
+    /// The wrapped service
+    type Service;
+    /// Wrap the given service with the middleware, returning a new service
+    /// that has been decorated with the middleware.
+    fn layer(&self, inner: S) -> Self::Service;
+}
+
+impl<'a, T, S> Layer<S> for &'a T
+where
+    T: ?Sized + Layer<S>,
+{
+    type Service = T::Service;
+
+    fn layer(&self, inner: S) -> Self::Service {
+        (**self).layer(inner)
+    }
+}
diff --git a/src/stack.rs b/src/stack.rs
new file mode 100644
index 0000000..cc0b826
--- /dev/null
+++ b/src/stack.rs
@@ -0,0 +1,62 @@
+use super::Layer;
+use std::fmt;
+
+/// Two middlewares chained together.
+#[derive(Clone)]
+pub struct Stack<Inner, Outer> {
+    inner: Inner,
+    outer: Outer,
+}
+
+impl<Inner, Outer> Stack<Inner, Outer> {
+    /// Create a new `Stack`.
+    pub fn new(inner: Inner, outer: Outer) -> Self {
+        Stack { inner, outer }
+    }
+}
+
+impl<S, Inner, Outer> Layer<S> for Stack<Inner, Outer>
+where
+    Inner: Layer<S>,
+    Outer: Layer<Inner::Service>,
+{
+    type Service = Outer::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let inner = self.inner.layer(service);
+
+        self.outer.layer(inner)
+    }
+}
+
+impl<Inner, Outer> fmt::Debug for Stack<Inner, Outer>
+where
+    Inner: fmt::Debug,
+    Outer: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // The generated output of nested `Stack`s is very noisy and makes
+        // it harder to understand what is in a `ServiceBuilder`.
+        //
+        // Instead, this output is designed assuming that a `Stack` is
+        // usually quite nested, and inside a `ServiceBuilder`. Therefore,
+        // this skips using `f.debug_struct()`, since each one would force
+        // a new layer of indentation.
+        //
+        // - In compact mode, a nested stack ends up just looking like a flat
+        //   list of layers.
+        //
+        // - In pretty mode, while a newline is inserted between each layer,
+        //   the `DebugStruct` used in the `ServiceBuilder` will inject padding
+        //   to that each line is at the same indentation level.
+        //
+        // Also, the order of [outer, inner] is important, since it reflects
+        // the order that the layers were added to the stack.
+        if f.alternate() {
+            // pretty
+            write!(f, "{:#?},\n{:#?}", self.outer, self.inner)
+        } else {
+            write!(f, "{:?}, {:?}", self.outer, self.inner)
+        }
+    }
+}
diff --git a/src/tuple.rs b/src/tuple.rs
new file mode 100644
index 0000000..14b973a
--- /dev/null
+++ b/src/tuple.rs
@@ -0,0 +1,330 @@
+use crate::Layer;
+
+impl<S> Layer<S> for () {
+    type Service = S;
+
+    fn layer(&self, service: S) -> Self::Service {
+        service
+    }
+}
+
+impl<S, L1> Layer<S> for (L1,)
+where
+    L1: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1,) = self;
+        l1.layer(service)
+    }
+}
+
+impl<S, L1, L2> Layer<S> for (L1, L2)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2) = self;
+        l1.layer(l2.layer(service))
+    }
+}
+
+impl<S, L1, L2, L3> Layer<S> for (L1, L2, L3)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3) = self;
+        l1.layer((l2, l3).layer(service))
+    }
+}
+
+impl<S, L1, L2, L3, L4> Layer<S> for (L1, L2, L3, L4)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4) = self;
+        l1.layer((l2, l3, l4).layer(service))
+    }
+}
+
+impl<S, L1, L2, L3, L4, L5> Layer<S> for (L1, L2, L3, L4, L5)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5) = self;
+        l1.layer((l2, l3, l4, l5).layer(service))
+    }
+}
+
+impl<S, L1, L2, L3, L4, L5, L6> Layer<S> for (L1, L2, L3, L4, L5, L6)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<L6::Service>,
+    L6: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5, l6) = self;
+        l1.layer((l2, l3, l4, l5, l6).layer(service))
+    }
+}
+
+impl<S, L1, L2, L3, L4, L5, L6, L7> Layer<S> for (L1, L2, L3, L4, L5, L6, L7)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<L6::Service>,
+    L6: Layer<L7::Service>,
+    L7: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5, l6, l7) = self;
+        l1.layer((l2, l3, l4, l5, l6, l7).layer(service))
+    }
+}
+
+impl<S, L1, L2, L3, L4, L5, L6, L7, L8> Layer<S> for (L1, L2, L3, L4, L5, L6, L7, L8)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<L6::Service>,
+    L6: Layer<L7::Service>,
+    L7: Layer<L8::Service>,
+    L8: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5, l6, l7, l8) = self;
+        l1.layer((l2, l3, l4, l5, l6, l7, l8).layer(service))
+    }
+}
+
+impl<S, L1, L2, L3, L4, L5, L6, L7, L8, L9> Layer<S> for (L1, L2, L3, L4, L5, L6, L7, L8, L9)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<L6::Service>,
+    L6: Layer<L7::Service>,
+    L7: Layer<L8::Service>,
+    L8: Layer<L9::Service>,
+    L9: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5, l6, l7, l8, l9) = self;
+        l1.layer((l2, l3, l4, l5, l6, l7, l8, l9).layer(service))
+    }
+}
+
+impl<S, L1, L2, L3, L4, L5, L6, L7, L8, L9, L10> Layer<S>
+    for (L1, L2, L3, L4, L5, L6, L7, L8, L9, L10)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<L6::Service>,
+    L6: Layer<L7::Service>,
+    L7: Layer<L8::Service>,
+    L8: Layer<L9::Service>,
+    L9: Layer<L10::Service>,
+    L10: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10) = self;
+        l1.layer((l2, l3, l4, l5, l6, l7, l8, l9, l10).layer(service))
+    }
+}
+
+impl<S, L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11> Layer<S>
+    for (L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<L6::Service>,
+    L6: Layer<L7::Service>,
+    L7: Layer<L8::Service>,
+    L8: Layer<L9::Service>,
+    L9: Layer<L10::Service>,
+    L10: Layer<L11::Service>,
+    L11: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11) = self;
+        l1.layer((l2, l3, l4, l5, l6, l7, l8, l9, l10, l11).layer(service))
+    }
+}
+
+impl<S, L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12> Layer<S>
+    for (L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<L6::Service>,
+    L6: Layer<L7::Service>,
+    L7: Layer<L8::Service>,
+    L8: Layer<L9::Service>,
+    L9: Layer<L10::Service>,
+    L10: Layer<L11::Service>,
+    L11: Layer<L12::Service>,
+    L12: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12) = self;
+        l1.layer((l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12).layer(service))
+    }
+}
+
+impl<S, L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13> Layer<S>
+    for (L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<L6::Service>,
+    L6: Layer<L7::Service>,
+    L7: Layer<L8::Service>,
+    L8: Layer<L9::Service>,
+    L9: Layer<L10::Service>,
+    L10: Layer<L11::Service>,
+    L11: Layer<L12::Service>,
+    L12: Layer<L13::Service>,
+    L13: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13) = self;
+        l1.layer((l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13).layer(service))
+    }
+}
+
+impl<S, L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13, L14> Layer<S>
+    for (L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13, L14)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<L6::Service>,
+    L6: Layer<L7::Service>,
+    L7: Layer<L8::Service>,
+    L8: Layer<L9::Service>,
+    L9: Layer<L10::Service>,
+    L10: Layer<L11::Service>,
+    L11: Layer<L12::Service>,
+    L12: Layer<L13::Service>,
+    L13: Layer<L14::Service>,
+    L14: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14) = self;
+        l1.layer((l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14).layer(service))
+    }
+}
+
+#[rustfmt::skip]
+impl<S, L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13, L14, L15> Layer<S>
+    for (L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13, L14, L15)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<L6::Service>,
+    L6: Layer<L7::Service>,
+    L7: Layer<L8::Service>,
+    L8: Layer<L9::Service>,
+    L9: Layer<L10::Service>,
+    L10: Layer<L11::Service>,
+    L11: Layer<L12::Service>,
+    L12: Layer<L13::Service>,
+    L13: Layer<L14::Service>,
+    L14: Layer<L15::Service>,
+    L15: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15) = self;
+        l1.layer((l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15).layer(service))
+    }
+}
+
+#[rustfmt::skip]
+impl<S, L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13, L14, L15, L16> Layer<S>
+    for (L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13, L14, L15, L16)
+where
+    L1: Layer<L2::Service>,
+    L2: Layer<L3::Service>,
+    L3: Layer<L4::Service>,
+    L4: Layer<L5::Service>,
+    L5: Layer<L6::Service>,
+    L6: Layer<L7::Service>,
+    L7: Layer<L8::Service>,
+    L8: Layer<L9::Service>,
+    L9: Layer<L10::Service>,
+    L10: Layer<L11::Service>,
+    L11: Layer<L12::Service>,
+    L12: Layer<L13::Service>,
+    L13: Layer<L14::Service>,
+    L14: Layer<L15::Service>,
+    L15: Layer<L16::Service>,
+    L16: Layer<S>,
+{
+    type Service = L1::Service;
+
+    fn layer(&self, service: S) -> Self::Service {
+        let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16) = self;
+        l1.layer((l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16).layer(service))
+    }
+}