diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/tower-service | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/tower-service')
-rw-r--r-- | third_party/rust/tower-service/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/tower-service/CHANGELOG.md | 39 | ||||
-rw-r--r-- | third_party/rust/tower-service/Cargo.toml | 28 | ||||
-rw-r--r-- | third_party/rust/tower-service/LICENSE | 25 | ||||
-rw-r--r-- | third_party/rust/tower-service/README.md | 36 | ||||
-rw-r--r-- | third_party/rust/tower-service/src/lib.rs | 271 |
6 files changed, 400 insertions, 0 deletions
diff --git a/third_party/rust/tower-service/.cargo-checksum.json b/third_party/rust/tower-service/.cargo-checksum.json new file mode 100644 index 0000000000..012c4f3a0f --- /dev/null +++ b/third_party/rust/tower-service/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"f27f052f43dce93f155dd4ed266b839bf248362b397c4257d522a03deccd677d","Cargo.toml":"5faca0916e798cd3dc035b976aabdc551e3a470242a0f6a4a2b3260fd4b2afe3","LICENSE":"4249c8e6c5ebb85f97c77e6457c6fafc1066406eb8f1ef61e796fbdc5ff18482","README.md":"7960fa603065260070c6f538f7e521f6829794e823080c29041e30a9c95970d9","src/lib.rs":"35582b17016726fbc69688d20d946143e541855b47e04b9efc65a90baa91d515"},"package":"e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"}
\ No newline at end of file diff --git a/third_party/rust/tower-service/CHANGELOG.md b/third_party/rust/tower-service/CHANGELOG.md new file mode 100644 index 0000000000..19df4f5ccc --- /dev/null +++ b/third_party/rust/tower-service/CHANGELOG.md @@ -0,0 +1,39 @@ +# 0.3.0 (November 29, 2019) + +- Update to `futures 0.3`. +- Update documentation for `std::future::Future`. + +# 0.3.0-alpha.2 (September 30, 2019) + +- Documentation fixes. + +# 0.3.0-alpha.1 (Aug 20, 2019) + +* Switch to `std::future::Future` + +# 0.2.0 (Dec 12, 2018) + +* Change `Service`'s `Request` associated type to be a generic instead. + * Before: + + ```rust + impl Service for Client { + type Request = HttpRequest; + type Response = HttpResponse; + // ... + } + ``` + * After: + + ```rust + impl Service<HttpRequest> for Client { + type Response = HttpResponse; + // ... + } + ``` +* Remove `NewService`, use `tower_util::MakeService` instead. +* Remove `Service::ready` and `Ready`, use `tower_util::ServiceExt` instead. + +# 0.1.0 (Aug 9, 2018) + +* Initial release diff --git a/third_party/rust/tower-service/Cargo.toml b/third_party/rust/tower-service/Cargo.toml new file mode 100644 index 0000000000..8c8c6dedb0 --- /dev/null +++ b/third_party/rust/tower-service/Cargo.toml @@ -0,0 +1,28 @@ +# 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 believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "tower-service" +version = "0.3.0" +authors = ["Tower Maintainers <team@tower-rs.com>"] +description = "Trait representing an asynchronous, request / response based, client or server.\n" +homepage = "https://github.com/tower-rs/tower" +documentation = "https://docs.rs/tower-service/0.3.0" +readme = "README.md" +categories = ["asynchronous", "network-programming"] +license = "MIT" +repository = "https://github.com/tower-rs/tower" + +[dependencies] +[dev-dependencies.http] +version = "0.1" diff --git a/third_party/rust/tower-service/LICENSE b/third_party/rust/tower-service/LICENSE new file mode 100644 index 0000000000..b980cacc77 --- /dev/null +++ b/third_party/rust/tower-service/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/third_party/rust/tower-service/README.md b/third_party/rust/tower-service/README.md new file mode 100644 index 0000000000..240649eb3f --- /dev/null +++ b/third_party/rust/tower-service/README.md @@ -0,0 +1,36 @@ +# Tower Service + +The foundational `Service` trait that Tower is based on. + +## Overview + +The [`Service`] trait provides the foundation upon which Tower is built. It is a +simple, but powerful trait. At its heart, `Service` is just an asynchronous +function of request to response. + +``` +async fn(Request) -> Result<Response, Error> +``` + +Implementations of `Service` take a request, the type of which varies per +protocol, and returns a future representing the eventual completion or failure +of the response. + +Services are used to represent both clients and servers. An *instance* of +`Service` is used through a client; a server *implements* `Service`. + +By using standardizing the interface, middleware can be created. Middleware +*implement* `Service` by passing the request to another `Service`. The +middleware may take actions such as modify the request. + +[`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html + +## 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. diff --git a/third_party/rust/tower-service/src/lib.rs b/third_party/rust/tower-service/src/lib.rs new file mode 100644 index 0000000000..ba90c0dcab --- /dev/null +++ b/third_party/rust/tower-service/src/lib.rs @@ -0,0 +1,271 @@ +#![doc(html_root_url = "https://docs.rs/tower-service/0.3.0")] +#![warn( + missing_debug_implementations, + missing_docs, + rust_2018_idioms, + unreachable_pub +)] + +//! Definition of the core `Service` trait to Tower +//! +//! The [`Service`] trait provides the necessary abstractions for defining +//! request / response clients and servers. It is simple but powerful and is +//! used as the foundation for the rest of Tower. + +use std::future::Future; +use std::task::{Context, Poll}; + +/// An asynchronous function from a `Request` to a `Response`. +/// +/// The `Service` trait is a simplified interface making it easy to write +/// network applications in a modular and reusable way, decoupled from the +/// underlying protocol. It is one of Tower's fundamental abstractions. +/// +/// # Functional +/// +/// A `Service` is a function of a `Request`. It immediately returns a +/// `Future` representing the eventual completion of processing the +/// request. The actual request processing may happen at any time in the +/// future, on any thread or executor. The processing may depend on calling +/// other services. At some point in the future, the processing will complete, +/// and the `Future` will resolve to a response or error. +/// +/// At a high level, the `Service::call` function represents an RPC request. The +/// `Service` value can be a server or a client. +/// +/// # Server +/// +/// An RPC server *implements* the `Service` trait. Requests received by the +/// server over the network are deserialized and then passed as an argument to the +/// server value. The returned response is sent back over the network. +/// +/// As an example, here is how an HTTP request is processed by a server: +/// +/// ```rust +/// # use std::pin::Pin; +/// # use std::task::{Poll, Context}; +/// # use std::future::Future; +/// # use tower_service::Service; +/// +/// use http::{Request, Response, StatusCode}; +/// +/// struct HelloWorld; +/// +/// impl Service<Request<Vec<u8>>> for HelloWorld { +/// type Response = Response<Vec<u8>>; +/// type Error = http::Error; +/// type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>; +/// +/// fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { +/// Poll::Ready(Ok(())) +/// } +/// +/// fn call(&mut self, req: Request<Vec<u8>>) -> Self::Future { +/// // create the body +/// let body: Vec<u8> = "hello, world!\n" +/// .as_bytes() +/// .to_owned(); +/// // Create the HTTP response +/// let resp = Response::builder() +/// .status(StatusCode::OK) +/// .body(body) +/// .expect("Unable to create `http::Response`"); +/// +/// // create a response in a future. +/// let fut = async { +/// Ok(resp) +/// }; +/// +/// // Return the response as an immediate future +/// Box::pin(fut) +/// } +/// } +/// ``` +/// +/// # Client +/// +/// A client consumes a service by using a `Service` value. The client may +/// issue requests by invoking `call` and passing the request as an argument. +/// It then receives the response by waiting for the returned future. +/// +/// As an example, here is how a Redis request would be issued: +/// +/// ```rust,ignore +/// let client = redis::Client::new() +/// .connect("127.0.0.1:6379".parse().unwrap()) +/// .unwrap(); +/// +/// let resp = client.call(Cmd::set("foo", "this is the value of foo")).await?; +/// +/// // Wait for the future to resolve +/// println!("Redis response: {:?}", resp); +/// ``` +/// +/// # Middleware / Layer +/// +/// More often than not, all the pieces needed for writing robust, scalable +/// network applications are the same no matter the underlying protocol. By +/// unifying the API for both clients and servers in a protocol agnostic way, +/// it is possible to write middleware that provide these pieces in a +/// reusable way. +/// +/// Take timeouts as an example: +/// +/// ```rust,ignore +/// use tower_service::Service; +/// use tower_layer::Layer; +/// use futures::FutureExt; +/// use std::future::Future; +/// use std::task::{Context, Poll}; +/// use std::time::Duration; +/// use std::pin::Pin; +/// +/// +/// pub struct Timeout<T> { +/// inner: T, +/// timeout: Duration, +/// } +/// +/// pub struct TimeoutLayer(Duration); +/// +/// pub struct Expired; +/// +/// impl<T> Timeout<T> { +/// pub fn new(inner: T, timeout: Duration) -> Timeout<T> { +/// Timeout { +/// inner, +/// timeout +/// } +/// } +/// } +/// +/// impl<T, Request> Service<Request> for Timeout<T> +/// where +/// T: Service<Request>, +/// T::Future: 'static, +/// T::Error: From<Expired> + 'static, +/// T::Response: 'static +/// { +/// type Response = T::Response; +/// type Error = T::Error; +/// type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>; +/// +/// fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { +/// self.inner.poll_ready(cx).map_err(Into::into) +/// } +/// +/// fn call(&mut self, req: Request) -> Self::Future { +/// let timeout = tokio_timer::delay_for(self.timeout) +/// .map(|_| Err(Self::Error::from(Expired))); +/// +/// let fut = Box::pin(self.inner.call(req)); +/// let f = futures::select(fut, timeout) +/// .map(|either| either.factor_first().0); +/// +/// Box::pin(f) +/// } +/// } +/// +/// impl TimeoutLayer { +/// pub fn new(delay: Duration) -> Self { +/// TimeoutLayer(delay) +/// } +/// } +/// +/// impl<S> Layer<S> for TimeoutLayer +/// { +/// type Service = Timeout<S>; +/// +/// fn layer(&self, service: S) -> Timeout<S> { +/// Timeout::new(service, self.0) +/// } +/// } +/// +/// ``` +/// +/// The above timeout implementation is decoupled from the underlying protocol +/// and is also decoupled from client or server concerns. In other words, the +/// same timeout middleware could be used in either a client or a server. +/// +/// # Backpressure +/// +/// Calling a `Service` which is at capacity (i.e., it is temporarily unable to process a +/// request) should result in an error. The caller is responsible for ensuring +/// that the service is ready to receive the request before calling it. +/// +/// `Service` provides a mechanism by which the caller is able to coordinate +/// readiness. `Service::poll_ready` returns `Ready` if the service expects that +/// it is able to process a request. +pub trait Service<Request> { + /// Responses given by the service. + type Response; + + /// Errors produced by the service. + type Error; + + /// The future response value. + type Future: Future<Output = Result<Self::Response, Self::Error>>; + + /// Returns `Poll::Ready(Ok(()))` when the service is able to process requests. + /// + /// If the service is at capacity, then `Poll::Pending` is returned and the task + /// is notified when the service becomes ready again. This function is + /// expected to be called while on a task. Generally, this can be done with + /// a simple `futures::future::poll_fn` call. + /// + /// If `Poll::Ready(Err(_))` is returned, the service is no longer able to service requests + /// and the caller should discard the service instance. + /// + /// Once `poll_ready` returns `Poll::Ready(Ok(()))`, a request may be dispatched to the + /// service using `call`. Until a request is dispatched, repeated calls to + /// `poll_ready` must return either `Poll::Ready(Ok(()))` or `Poll::Ready(Err(_))`. + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>; + + /// Process the request and return the response asynchronously. + /// + /// This function is expected to be callable off task. As such, + /// implementations should take care to not call `poll_ready`. + /// + /// Before dispatching a request, `poll_ready` must be called and return + /// `Poll::Ready(Ok(()))`. + /// + /// # Panics + /// + /// Implementations are permitted to panic if `call` is invoked without + /// obtaining `Poll::Ready(Ok(()))` from `poll_ready`. + fn call(&mut self, req: Request) -> Self::Future; +} + +impl<'a, S, Request> Service<Request> for &'a mut S +where + S: Service<Request> + 'a, +{ + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), S::Error>> { + (**self).poll_ready(cx) + } + + fn call(&mut self, request: Request) -> S::Future { + (**self).call(request) + } +} + +impl<S, Request> Service<Request> for Box<S> +where + S: Service<Request> + ?Sized, +{ + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), S::Error>> { + (**self).poll_ready(cx) + } + + fn call(&mut self, request: Request) -> S::Future { + (**self).call(request) + } +} |