forked from openkylin/rust-http-body
Compare commits
No commits in common. "pristine-tar" and "openkylin/yangtze" have entirely different histories.
pristine-t
...
openkylin/
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"git": {
|
||||||
|
"sha1": "6f722a14f7c6488cd53dcc4126a84e6ee201964f"
|
||||||
|
},
|
||||||
|
"path_in_vcs": ""
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
name: CI
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
style:
|
||||||
|
name: Check Style
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
- name: Install Rustfmt
|
||||||
|
run: rustup component add rustfmt
|
||||||
|
- name: Check formatting
|
||||||
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
|
test:
|
||||||
|
name: Test
|
||||||
|
needs: [style]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
rust:
|
||||||
|
- stable
|
||||||
|
- beta
|
||||||
|
- nightly
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
- name: Install Rust
|
||||||
|
run: rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
|
||||||
|
- name: Run tests
|
||||||
|
run: cargo test
|
|
@ -0,0 +1,2 @@
|
||||||
|
target
|
||||||
|
Cargo.lock
|
|
@ -0,0 +1,62 @@
|
||||||
|
# Unreleased
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
# 0.4.5 (May 20, 2022)
|
||||||
|
|
||||||
|
- Add `String` impl for `Body`.
|
||||||
|
- Add `Limited` body implementation.
|
||||||
|
|
||||||
|
# 0.4.4 (October 22, 2021)
|
||||||
|
|
||||||
|
- Add `UnsyncBoxBody` and `Body::boxed_unsync`.
|
||||||
|
|
||||||
|
# 0.4.3 (August 8, 2021)
|
||||||
|
|
||||||
|
- Implement `Default` for `BoxBody`.
|
||||||
|
|
||||||
|
# 0.4.2 (May 8, 2021)
|
||||||
|
|
||||||
|
- Correctly override `Body::size_hint` and `Body::is_end_stream` for `Empty`.
|
||||||
|
- Add `Full` which is a body that consists of a single chunk.
|
||||||
|
|
||||||
|
# 0.4.1 (March 18, 2021)
|
||||||
|
|
||||||
|
- Add combinators to `Body`:
|
||||||
|
- `map_data`: Change the `Data` chunks produced by the body.
|
||||||
|
- `map_err`: Change the `Error`s produced by the body.
|
||||||
|
- `boxed`: Convert the `Body` into a boxed trait object.
|
||||||
|
- Add `Empty`.
|
||||||
|
|
||||||
|
# 0.4.0 (December 23, 2020)
|
||||||
|
|
||||||
|
- Update `bytes` to v1.0.
|
||||||
|
|
||||||
|
# 0.3.1 (December 13, 2019)
|
||||||
|
|
||||||
|
- Implement `Body` for `http::Request<impl Body>` and `http::Response<impl Body>`.
|
||||||
|
|
||||||
|
# 0.3.0 (December 4, 2019)
|
||||||
|
|
||||||
|
- Rename `next` combinator to `data`.
|
||||||
|
|
||||||
|
# 0.2.0 (December 3, 2019)
|
||||||
|
|
||||||
|
- Update `http` to v0.2.
|
||||||
|
- Update `bytes` to v0.5.
|
||||||
|
|
||||||
|
# 0.2.0-alpha.3 (October 1, 2019)
|
||||||
|
|
||||||
|
- Fix `Body` to be object-safe.
|
||||||
|
|
||||||
|
# 0.2.0-alpha.2 (October 1, 2019)
|
||||||
|
|
||||||
|
- Add `next` and `trailers` combinator methods.
|
||||||
|
|
||||||
|
# 0.2.0-alpha.1 (August 20, 2019)
|
||||||
|
|
||||||
|
- Update to use `Pin` in `poll_data` and `poll_trailers`.
|
||||||
|
|
||||||
|
# 0.1.0 (May 7, 2019)
|
||||||
|
|
||||||
|
- Initial release
|
|
@ -0,0 +1,45 @@
|
||||||
|
# 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 = "http-body"
|
||||||
|
version = "0.4.5"
|
||||||
|
authors = [
|
||||||
|
"Carl Lerche <me@carllerche.com>",
|
||||||
|
"Lucio Franco <luciofranco14@gmail.com>",
|
||||||
|
"Sean McArthur <sean@seanmonstar.com>",
|
||||||
|
]
|
||||||
|
description = """
|
||||||
|
Trait representing an asynchronous, streaming, HTTP request or response body.
|
||||||
|
"""
|
||||||
|
documentation = "https://docs.rs/http-body"
|
||||||
|
readme = "README.md"
|
||||||
|
keywords = ["http"]
|
||||||
|
categories = ["web-programming"]
|
||||||
|
license = "MIT"
|
||||||
|
repository = "https://github.com/hyperium/http-body"
|
||||||
|
|
||||||
|
[dependencies.bytes]
|
||||||
|
version = "1"
|
||||||
|
|
||||||
|
[dependencies.http]
|
||||||
|
version = "0.2"
|
||||||
|
|
||||||
|
[dependencies.pin-project-lite]
|
||||||
|
version = "0.2"
|
||||||
|
|
||||||
|
[dev-dependencies.tokio]
|
||||||
|
version = "1"
|
||||||
|
features = [
|
||||||
|
"macros",
|
||||||
|
"rt",
|
||||||
|
]
|
|
@ -0,0 +1,34 @@
|
||||||
|
[package]
|
||||||
|
name = "http-body"
|
||||||
|
# When releasing to crates.io:
|
||||||
|
# - Remove path dependencies
|
||||||
|
# - Update html_root_url.
|
||||||
|
# - Update doc url
|
||||||
|
# - Cargo.toml
|
||||||
|
# - README.md
|
||||||
|
# - Update CHANGELOG.md.
|
||||||
|
# - Create "vx.y.z" git tag.
|
||||||
|
version = "0.4.5"
|
||||||
|
authors = [
|
||||||
|
"Carl Lerche <me@carllerche.com>",
|
||||||
|
"Lucio Franco <luciofranco14@gmail.com>",
|
||||||
|
"Sean McArthur <sean@seanmonstar.com>",
|
||||||
|
]
|
||||||
|
edition = "2018"
|
||||||
|
readme = "README.md"
|
||||||
|
documentation = "https://docs.rs/http-body"
|
||||||
|
repository = "https://github.com/hyperium/http-body"
|
||||||
|
license = "MIT"
|
||||||
|
description = """
|
||||||
|
Trait representing an asynchronous, streaming, HTTP request or response body.
|
||||||
|
"""
|
||||||
|
keywords = ["http"]
|
||||||
|
categories = ["web-programming"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bytes = "1"
|
||||||
|
http = "0.2"
|
||||||
|
pin-project-lite = "0.2"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tokio = { version = "1", features = ["macros", "rt"] }
|
|
@ -0,0 +1,25 @@
|
||||||
|
Copyright (c) 2019 Hyper 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.
|
|
@ -0,0 +1,27 @@
|
||||||
|
# HTTP Body
|
||||||
|
|
||||||
|
A trait representing asynchronous operations on an HTTP body.
|
||||||
|
|
||||||
|
[![crates.io][crates-badge]][crates-url]
|
||||||
|
[![documentation][docs-badge]][docs-url]
|
||||||
|
[![MIT License][mit-badge]][mit-url]
|
||||||
|
[![CI Status][ci-badge]][ci-url]
|
||||||
|
|
||||||
|
[crates-badge]: https://img.shields.io/crates/v/http-body.svg
|
||||||
|
[crates-url]: https://crates.io/crates/http-body
|
||||||
|
[docs-badge]: https://docs.rs/http-body/badge.svg
|
||||||
|
[docs-url]: https://docs.rs/http-body
|
||||||
|
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
||||||
|
[mit-url]: LICENSE
|
||||||
|
[ci-badge]: https://github.com/hyperium/http-body/workflows/CI/badge.svg
|
||||||
|
[ci-url]: https://github.com/hyperium/http-body/actions?query=workflow%3ACI
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the [MIT license](LICENSE).
|
||||||
|
|
||||||
|
### Contribution
|
||||||
|
|
||||||
|
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||||
|
for inclusion in `http-body` by you, shall be licensed as MIT, without any additional
|
||||||
|
terms or conditions.
|
|
@ -0,0 +1 @@
|
||||||
|
{"package":"d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1","files":{}}
|
|
@ -0,0 +1,23 @@
|
||||||
|
rust-http-body (0.4.5-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Team upload.
|
||||||
|
* Package http-body 0.4.5 from crates.io using debcargo 2.5.0
|
||||||
|
|
||||||
|
[ Fabian Gruenbichler ]
|
||||||
|
* Package http-body 0.4.4 from crates.io using debcargo 2.5.0
|
||||||
|
|
||||||
|
-- Daniel Kahn Gillmor <dkg@fifthhorseman.net> Sat, 21 May 2022 20:26:34 -0400
|
||||||
|
|
||||||
|
rust-http-body (0.1.0-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Team upload.
|
||||||
|
* Package http-body 0.1.0 from crates.io using debcargo 2.2.10
|
||||||
|
* Source upload for migration
|
||||||
|
|
||||||
|
-- Sylvestre Ledru <sylvestre@debian.org> Tue, 06 Aug 2019 18:10:37 +0200
|
||||||
|
|
||||||
|
rust-http-body (0.1.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Package http-body 0.1.0 from crates.io using debcargo 2.2.10
|
||||||
|
|
||||||
|
-- Robin Krahl <robin.krahl@ireas.org> Sat, 13 Jul 2019 22:14:15 +0200
|
|
@ -0,0 +1 @@
|
||||||
|
12
|
|
@ -0,0 +1,38 @@
|
||||||
|
Source: rust-http-body
|
||||||
|
Section: rust
|
||||||
|
Priority: optional
|
||||||
|
Build-Depends: debhelper (>= 12),
|
||||||
|
dh-cargo (>= 25),
|
||||||
|
cargo:native <!nocheck>,
|
||||||
|
rustc:native <!nocheck>,
|
||||||
|
libstd-rust-dev <!nocheck>,
|
||||||
|
librust-bytes-1+default-dev <!nocheck>,
|
||||||
|
librust-http-0.2+default-dev <!nocheck>,
|
||||||
|
librust-pin-project-lite-0.2+default-dev <!nocheck>
|
||||||
|
Maintainer: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
|
||||||
|
Uploaders:
|
||||||
|
Robin Krahl <robin.krahl@ireas.org>
|
||||||
|
Standards-Version: 4.5.1
|
||||||
|
Vcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/http-body]
|
||||||
|
Vcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/http-body
|
||||||
|
Rules-Requires-Root: no
|
||||||
|
|
||||||
|
Package: librust-http-body-dev
|
||||||
|
Architecture: any
|
||||||
|
Multi-Arch: same
|
||||||
|
Depends:
|
||||||
|
${misc:Depends},
|
||||||
|
librust-bytes-1+default-dev,
|
||||||
|
librust-http-0.2+default-dev,
|
||||||
|
librust-pin-project-lite-0.2+default-dev
|
||||||
|
Provides:
|
||||||
|
librust-http-body+default-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0+default-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0.4-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0.4+default-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0.4.5-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0.4.5+default-dev (= ${binary:Version})
|
||||||
|
Description: trait representing asynchronous operations on an HTTP body - Rust source code
|
||||||
|
This package contains the source for the Rust http-body crate, packaged by
|
||||||
|
debcargo for use with cargo and dh-cargo.
|
|
@ -0,0 +1,40 @@
|
||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: http-body
|
||||||
|
Upstream-Contact:
|
||||||
|
Carl Lerche <me@carllerche.com>
|
||||||
|
Lucio Franco <luciofranco14@gmail.com>
|
||||||
|
Sean McArthur <sean@seanmonstar.com>
|
||||||
|
Source: https://github.com/hyperium/http-body
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright:
|
||||||
|
2019 Carl Lerche <me@carllerche.com>
|
||||||
|
2019 Lucio Franco <luciofranco14@gmail.com>
|
||||||
|
2019 Sean McArthur <sean@seanmonstar.com>
|
||||||
|
2019 Hyper Contributors
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright:
|
||||||
|
2019 Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
|
||||||
|
2019 Robin Krahl <robin.krahl@ireas.org>
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
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.
|
|
@ -0,0 +1,51 @@
|
||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: http-body
|
||||||
|
Upstream-Contact:
|
||||||
|
Carl Lerche <me@carllerche.com>
|
||||||
|
Lucio Franco <luciofranco14@gmail.com>
|
||||||
|
Sean McArthur <sean@seanmonstar.com>
|
||||||
|
Source: https://github.com/hyperium/http-body
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright:
|
||||||
|
FIXME (overlay) UNKNOWN-YEARS Carl Lerche <me@carllerche.com>
|
||||||
|
FIXME (overlay) UNKNOWN-YEARS Lucio Franco <luciofranco14@gmail.com>
|
||||||
|
FIXME (overlay) UNKNOWN-YEARS Sean McArthur <sean@seanmonstar.com>
|
||||||
|
License: MIT
|
||||||
|
Comment:
|
||||||
|
FIXME (overlay): Since upstream copyright years are not available in
|
||||||
|
Cargo.toml, they were extracted from the upstream Git repository. This may not
|
||||||
|
be correct information so you should review and fix this before uploading to
|
||||||
|
the archive.
|
||||||
|
|
||||||
|
Files: ./LICENSE
|
||||||
|
Copyright: 2019 Hyper Contributors
|
||||||
|
License: UNKNOWN-LICENSE; FIXME (overlay)
|
||||||
|
Comment:
|
||||||
|
FIXME (overlay): These notices are extracted from files. Please review them
|
||||||
|
before uploading to the archive.
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright:
|
||||||
|
2019-2022 Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
|
||||||
|
2019-2022 Robin Krahl <robin.krahl@ireas.org>
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
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.
|
|
@ -0,0 +1,3 @@
|
||||||
|
overlay = "."
|
||||||
|
uploaders = ["Robin Krahl <robin.krahl@ireas.org>"]
|
||||||
|
summary = "trait representing asynchronous operations on an HTTP body"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/make -f
|
||||||
|
%:
|
||||||
|
dh $@ --buildsystem cargo
|
|
@ -0,0 +1 @@
|
||||||
|
3.0 (quilt)
|
|
@ -0,0 +1,14 @@
|
||||||
|
Test-Command: /usr/share/cargo/bin/cargo-auto-test http-body 0.4.5 --all-targets --all-features
|
||||||
|
Features: test-name=rust-http-body:@
|
||||||
|
Depends: dh-cargo (>= 18), librust-tokio-1+default-dev, librust-tokio-1+macros-dev, librust-tokio-1+rt-dev, @
|
||||||
|
Restrictions: allow-stderr, skip-not-installable
|
||||||
|
|
||||||
|
Test-Command: /usr/share/cargo/bin/cargo-auto-test http-body 0.4.5 --all-targets
|
||||||
|
Features: test-name=librust-http-body-dev:default
|
||||||
|
Depends: dh-cargo (>= 18), librust-tokio-1+default-dev, librust-tokio-1+macros-dev, librust-tokio-1+rt-dev, @
|
||||||
|
Restrictions: allow-stderr, skip-not-installable
|
||||||
|
|
||||||
|
Test-Command: /usr/share/cargo/bin/cargo-auto-test http-body 0.4.5 --all-targets --no-default-features
|
||||||
|
Features: test-name=librust-http-body-dev:
|
||||||
|
Depends: dh-cargo (>= 18), librust-tokio-1+default-dev, librust-tokio-1+macros-dev, librust-tokio-1+rt-dev, @
|
||||||
|
Restrictions: allow-stderr, skip-not-installable
|
|
@ -0,0 +1,4 @@
|
||||||
|
version=4
|
||||||
|
opts=filenamemangle=s/.*\/(.*)\/download/http-body-$1\.tar\.gz/g,\
|
||||||
|
uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\d*)$/$1~$2/ \
|
||||||
|
https://qa.debian.org/cgi-bin/fakeupstream.cgi?upstream=crates.io/http-body .*/crates/http-body/@ANY_VERSION@/download
|
|
@ -0,0 +1 @@
|
||||||
|
{"package":"d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1","files":{}}
|
|
@ -0,0 +1,5 @@
|
||||||
|
rust-http-body (0.4.5-ok1) yangtze; urgency=medium
|
||||||
|
|
||||||
|
* Build for openKylin.
|
||||||
|
|
||||||
|
-- denghao <denghao@kylinos.cn> Mon, 10 Apr 2023 14:38:49 +0800
|
|
@ -0,0 +1 @@
|
||||||
|
12
|
|
@ -0,0 +1,36 @@
|
||||||
|
Source: rust-http-body
|
||||||
|
Section: rust
|
||||||
|
Priority: optional
|
||||||
|
Build-Depends: debhelper (>= 12),
|
||||||
|
dh-cargo (>= 25),
|
||||||
|
cargo:native <!nocheck>,
|
||||||
|
rustc:native <!nocheck>,
|
||||||
|
libstd-rust-dev <!nocheck>,
|
||||||
|
librust-bytes-1+default-dev <!nocheck>,
|
||||||
|
librust-http-0.2+default-dev <!nocheck>,
|
||||||
|
librust-pin-project-lite-0.2+default-dev <!nocheck>
|
||||||
|
Maintainer: Openkylin Developers <packaging@lists.openkylin.top>
|
||||||
|
Standards-Version: 4.5.1
|
||||||
|
Vcs-Git:https://gitee.com/openkylin/rust-http-body.git
|
||||||
|
Vcs-Browser:https://gitee.com/openkylin/rust-http-body
|
||||||
|
Rules-Requires-Root: no
|
||||||
|
|
||||||
|
Package: librust-http-body-dev
|
||||||
|
Architecture: any
|
||||||
|
Multi-Arch: same
|
||||||
|
Depends:
|
||||||
|
${misc:Depends},
|
||||||
|
librust-bytes-1+default-dev,
|
||||||
|
librust-http-0.2+default-dev,
|
||||||
|
librust-pin-project-lite-0.2+default-dev
|
||||||
|
Provides:
|
||||||
|
librust-http-body+default-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0+default-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0.4-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0.4+default-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0.4.5-dev (= ${binary:Version}),
|
||||||
|
librust-http-body-0.4.5+default-dev (= ${binary:Version})
|
||||||
|
Description: trait representing asynchronous operations on an HTTP body - Rust source code
|
||||||
|
This package contains the source for the Rust http-body crate, packaged by
|
||||||
|
debcargo for use with cargo and dh-cargo.
|
|
@ -0,0 +1,130 @@
|
||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: rust-http-body
|
||||||
|
Source: <url://example.com>
|
||||||
|
#
|
||||||
|
# Please double check copyright with the licensecheck(1) command.
|
||||||
|
|
||||||
|
Files: .cargo_vcs_info.json
|
||||||
|
.github/workflows/CI.yml
|
||||||
|
.gitignore
|
||||||
|
CHANGELOG.md
|
||||||
|
Cargo.toml
|
||||||
|
Cargo.toml.orig
|
||||||
|
README.md
|
||||||
|
debian-orig/cargo-checksum.json
|
||||||
|
debian-orig/compat
|
||||||
|
debian-orig/debcargo.toml
|
||||||
|
debian-orig/rules
|
||||||
|
debian-orig/source/format
|
||||||
|
debian-orig/tests/control
|
||||||
|
debian-orig/watch
|
||||||
|
src/combinators/box_body.rs
|
||||||
|
src/combinators/map_data.rs
|
||||||
|
src/combinators/map_err.rs
|
||||||
|
src/combinators/mod.rs
|
||||||
|
src/empty.rs
|
||||||
|
src/full.rs
|
||||||
|
src/lib.rs
|
||||||
|
src/limited.rs
|
||||||
|
src/next.rs
|
||||||
|
src/size_hint.rs
|
||||||
|
tests/is_end_stream.rs
|
||||||
|
Copyright: __NO_COPYRIGHT_NOR_LICENSE__
|
||||||
|
License: __NO_COPYRIGHT_NOR_LICENSE__
|
||||||
|
|
||||||
|
Files: debian-orig/copyright
|
||||||
|
Copyright: __NO_COPYRIGHT__ in: debian-orig/copyright
|
||||||
|
License: Expat
|
||||||
|
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.
|
||||||
|
|
||||||
|
Files: debian-orig/copyright.debcargo.hint
|
||||||
|
Copyright: : 2019 Hyper Contributors License: UNKNOWN-LICENSE; FIXME (overlay) Comment:
|
||||||
|
License: Expat
|
||||||
|
FIXME (overlay): These notices are extracted from files. Please review them
|
||||||
|
before uploading to the archive.
|
||||||
|
.
|
||||||
|
Files: debian/*
|
||||||
|
Copyright:
|
||||||
|
2019-2022 Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
|
||||||
|
2019-2022 Robin Krahl <robin.krahl@ireas.org>
|
||||||
|
License: MIT
|
||||||
|
.
|
||||||
|
License: MIT
|
||||||
|
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.
|
||||||
|
|
||||||
|
Files: debian-orig/control
|
||||||
|
Copyright: __NO_COPYRIGHT__ in: debian-orig/control
|
||||||
|
License: __UNKNOWN__
|
||||||
|
Package: librust-http-body-dev
|
||||||
|
Architecture: any
|
||||||
|
Multi-Arch: same
|
||||||
|
Depends:
|
||||||
|
${misc:Depends},
|
||||||
|
librust-bytes-1+default-dev,
|
||||||
|
librust-http-0.2+default-dev,
|
||||||
|
librust-pin-project-lite-0.2+default-dev
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
# Files marked as NO_LICENSE_TEXT_FOUND may be covered by the following
|
||||||
|
# license/copyright files.
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
# License file: LICENSE
|
||||||
|
Copyright (c) 2019 Hyper 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.
|
|
@ -0,0 +1,51 @@
|
||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: http-body
|
||||||
|
Upstream-Contact:
|
||||||
|
Carl Lerche <me@carllerche.com>
|
||||||
|
Lucio Franco <luciofranco14@gmail.com>
|
||||||
|
Sean McArthur <sean@seanmonstar.com>
|
||||||
|
Source: https://github.com/hyperium/http-body
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright:
|
||||||
|
FIXME (overlay) UNKNOWN-YEARS Carl Lerche <me@carllerche.com>
|
||||||
|
FIXME (overlay) UNKNOWN-YEARS Lucio Franco <luciofranco14@gmail.com>
|
||||||
|
FIXME (overlay) UNKNOWN-YEARS Sean McArthur <sean@seanmonstar.com>
|
||||||
|
License: MIT
|
||||||
|
Comment:
|
||||||
|
FIXME (overlay): Since upstream copyright years are not available in
|
||||||
|
Cargo.toml, they were extracted from the upstream Git repository. This may not
|
||||||
|
be correct information so you should review and fix this before uploading to
|
||||||
|
the archive.
|
||||||
|
|
||||||
|
Files: ./LICENSE
|
||||||
|
Copyright: 2019 Hyper Contributors
|
||||||
|
License: UNKNOWN-LICENSE; FIXME (overlay)
|
||||||
|
Comment:
|
||||||
|
FIXME (overlay): These notices are extracted from files. Please review them
|
||||||
|
before uploading to the archive.
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright:
|
||||||
|
2019-2022 Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
|
||||||
|
2019-2022 Robin Krahl <robin.krahl@ireas.org>
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
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.
|
|
@ -0,0 +1,3 @@
|
||||||
|
overlay = "."
|
||||||
|
uploaders = ["Robin Krahl <robin.krahl@ireas.org>"]
|
||||||
|
summary = "trait representing asynchronous operations on an HTTP body"
|
|
@ -0,0 +1 @@
|
||||||
|
# You must remove unused comment lines for the released package.
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/make -f
|
||||||
|
%:
|
||||||
|
dh $@ --buildsystem cargo
|
|
@ -0,0 +1 @@
|
||||||
|
3.0 (native)
|
|
@ -0,0 +1,14 @@
|
||||||
|
Test-Command: /usr/share/cargo/bin/cargo-auto-test http-body 0.4.5 --all-targets --all-features
|
||||||
|
Features: test-name=rust-http-body:@
|
||||||
|
Depends: dh-cargo (>= 18), librust-tokio-1+default-dev, librust-tokio-1+macros-dev, librust-tokio-1+rt-dev, @
|
||||||
|
Restrictions: allow-stderr, skip-not-installable
|
||||||
|
|
||||||
|
Test-Command: /usr/share/cargo/bin/cargo-auto-test http-body 0.4.5 --all-targets
|
||||||
|
Features: test-name=librust-http-body-dev:default
|
||||||
|
Depends: dh-cargo (>= 18), librust-tokio-1+default-dev, librust-tokio-1+macros-dev, librust-tokio-1+rt-dev, @
|
||||||
|
Restrictions: allow-stderr, skip-not-installable
|
||||||
|
|
||||||
|
Test-Command: /usr/share/cargo/bin/cargo-auto-test http-body 0.4.5 --all-targets --no-default-features
|
||||||
|
Features: test-name=librust-http-body-dev:
|
||||||
|
Depends: dh-cargo (>= 18), librust-tokio-1+default-dev, librust-tokio-1+macros-dev, librust-tokio-1+rt-dev, @
|
||||||
|
Restrictions: allow-stderr, skip-not-installable
|
|
@ -0,0 +1,4 @@
|
||||||
|
version=4
|
||||||
|
opts=filenamemangle=s/.*\/(.*)\/download/http-body-$1\.tar\.gz/g,\
|
||||||
|
uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\d*)$/$1~$2/ \
|
||||||
|
https://qa.debian.org/cgi-bin/fakeupstream.cgi?upstream=crates.io/http-body .*/crates/http-body/@ANY_VERSION@/download
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
b4c76019a627454d3037b2edd392f677c043d4ae
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
use crate::Body;
|
||||||
|
use bytes::Buf;
|
||||||
|
use std::{
|
||||||
|
fmt,
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A boxed [`Body`] trait object.
|
||||||
|
pub struct BoxBody<D, E> {
|
||||||
|
inner: Pin<Box<dyn Body<Data = D, Error = E> + Send + Sync + 'static>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A boxed [`Body`] trait object that is !Sync.
|
||||||
|
pub struct UnsyncBoxBody<D, E> {
|
||||||
|
inner: Pin<Box<dyn Body<Data = D, Error = E> + Send + 'static>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D, E> BoxBody<D, E> {
|
||||||
|
/// Create a new `BoxBody`.
|
||||||
|
pub fn new<B>(body: B) -> Self
|
||||||
|
where
|
||||||
|
B: Body<Data = D, Error = E> + Send + Sync + 'static,
|
||||||
|
D: Buf,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
inner: Box::pin(body),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D, E> fmt::Debug for BoxBody<D, E> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("BoxBody").finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D, E> Body for BoxBody<D, E>
|
||||||
|
where
|
||||||
|
D: Buf,
|
||||||
|
{
|
||||||
|
type Data = D;
|
||||||
|
type Error = E;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
self.inner.as_mut().poll_data(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
|
||||||
|
self.inner.as_mut().poll_trailers(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
self.inner.is_end_stream()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> crate::SizeHint {
|
||||||
|
self.inner.size_hint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D, E> Default for BoxBody<D, E>
|
||||||
|
where
|
||||||
|
D: Buf + 'static,
|
||||||
|
{
|
||||||
|
fn default() -> Self {
|
||||||
|
BoxBody::new(crate::Empty::new().map_err(|err| match err {}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === UnsyncBoxBody ===
|
||||||
|
impl<D, E> UnsyncBoxBody<D, E> {
|
||||||
|
/// Create a new `BoxBody`.
|
||||||
|
pub fn new<B>(body: B) -> Self
|
||||||
|
where
|
||||||
|
B: Body<Data = D, Error = E> + Send + 'static,
|
||||||
|
D: Buf,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
inner: Box::pin(body),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D, E> fmt::Debug for UnsyncBoxBody<D, E> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("UnsyncBoxBody").finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D, E> Body for UnsyncBoxBody<D, E>
|
||||||
|
where
|
||||||
|
D: Buf,
|
||||||
|
{
|
||||||
|
type Data = D;
|
||||||
|
type Error = E;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
self.inner.as_mut().poll_data(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
|
||||||
|
self.inner.as_mut().poll_trailers(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
self.inner.is_end_stream()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> crate::SizeHint {
|
||||||
|
self.inner.size_hint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D, E> Default for UnsyncBoxBody<D, E>
|
||||||
|
where
|
||||||
|
D: Buf + 'static,
|
||||||
|
{
|
||||||
|
fn default() -> Self {
|
||||||
|
UnsyncBoxBody::new(crate::Empty::new().map_err(|err| match err {}))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
use crate::Body;
|
||||||
|
use bytes::Buf;
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
use std::{
|
||||||
|
any::type_name,
|
||||||
|
fmt,
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
|
||||||
|
pin_project! {
|
||||||
|
/// Body returned by the [`map_data`] combinator.
|
||||||
|
///
|
||||||
|
/// [`map_data`]: crate::util::BodyExt::map_data
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct MapData<B, F> {
|
||||||
|
#[pin]
|
||||||
|
inner: B,
|
||||||
|
f: F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, F> MapData<B, F> {
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn new(body: B, f: F) -> Self {
|
||||||
|
Self { inner: body, f }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the inner body
|
||||||
|
pub fn get_ref(&self) -> &B {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a mutable reference to the inner body
|
||||||
|
pub fn get_mut(&mut self) -> &mut B {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a pinned mutable reference to the inner body
|
||||||
|
pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut B> {
|
||||||
|
self.project().inner
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consume `self`, returning the inner body
|
||||||
|
pub fn into_inner(self) -> B {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, F, B2> Body for MapData<B, F>
|
||||||
|
where
|
||||||
|
B: Body,
|
||||||
|
F: FnMut(B::Data) -> B2,
|
||||||
|
B2: Buf,
|
||||||
|
{
|
||||||
|
type Data = B2;
|
||||||
|
type Error = B::Error;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
let this = self.project();
|
||||||
|
match this.inner.poll_data(cx) {
|
||||||
|
Poll::Pending => Poll::Pending,
|
||||||
|
Poll::Ready(None) => Poll::Ready(None),
|
||||||
|
Poll::Ready(Some(Ok(data))) => Poll::Ready(Some(Ok((this.f)(data)))),
|
||||||
|
Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err(err))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
|
||||||
|
self.project().inner.poll_trailers(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
self.inner.is_end_stream()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, F> fmt::Debug for MapData<B, F>
|
||||||
|
where
|
||||||
|
B: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("MapData")
|
||||||
|
.field("inner", &self.inner)
|
||||||
|
.field("f", &type_name::<F>())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
use crate::Body;
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
use std::{
|
||||||
|
any::type_name,
|
||||||
|
fmt,
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
|
||||||
|
pin_project! {
|
||||||
|
/// Body returned by the [`map_err`] combinator.
|
||||||
|
///
|
||||||
|
/// [`map_err`]: crate::util::BodyExt::map_err
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct MapErr<B, F> {
|
||||||
|
#[pin]
|
||||||
|
inner: B,
|
||||||
|
f: F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, F> MapErr<B, F> {
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn new(body: B, f: F) -> Self {
|
||||||
|
Self { inner: body, f }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the inner body
|
||||||
|
pub fn get_ref(&self) -> &B {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a mutable reference to the inner body
|
||||||
|
pub fn get_mut(&mut self) -> &mut B {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a pinned mutable reference to the inner body
|
||||||
|
pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut B> {
|
||||||
|
self.project().inner
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consume `self`, returning the inner body
|
||||||
|
pub fn into_inner(self) -> B {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, F, E> Body for MapErr<B, F>
|
||||||
|
where
|
||||||
|
B: Body,
|
||||||
|
F: FnMut(B::Error) -> E,
|
||||||
|
{
|
||||||
|
type Data = B::Data;
|
||||||
|
type Error = E;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
let this = self.project();
|
||||||
|
match this.inner.poll_data(cx) {
|
||||||
|
Poll::Pending => Poll::Pending,
|
||||||
|
Poll::Ready(None) => Poll::Ready(None),
|
||||||
|
Poll::Ready(Some(Ok(data))) => Poll::Ready(Some(Ok(data))),
|
||||||
|
Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err((this.f)(err)))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
|
||||||
|
let this = self.project();
|
||||||
|
this.inner.poll_trailers(cx).map_err(this.f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
self.inner.is_end_stream()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> crate::SizeHint {
|
||||||
|
self.inner.size_hint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, F> fmt::Debug for MapErr<B, F>
|
||||||
|
where
|
||||||
|
B: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("MapErr")
|
||||||
|
.field("inner", &self.inner)
|
||||||
|
.field("f", &type_name::<F>())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
//! Combinators for the `Body` trait.
|
||||||
|
|
||||||
|
mod box_body;
|
||||||
|
mod map_data;
|
||||||
|
mod map_err;
|
||||||
|
|
||||||
|
pub use self::{
|
||||||
|
box_body::{BoxBody, UnsyncBoxBody},
|
||||||
|
map_data::MapData,
|
||||||
|
map_err::MapErr,
|
||||||
|
};
|
|
@ -0,0 +1,75 @@
|
||||||
|
use super::{Body, SizeHint};
|
||||||
|
use bytes::Buf;
|
||||||
|
use http::HeaderMap;
|
||||||
|
use std::{
|
||||||
|
convert::Infallible,
|
||||||
|
fmt,
|
||||||
|
marker::PhantomData,
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A body that is always empty.
|
||||||
|
pub struct Empty<D> {
|
||||||
|
_marker: PhantomData<fn() -> D>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> Empty<D> {
|
||||||
|
/// Create a new `Empty`.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Buf> Body for Empty<D> {
|
||||||
|
type Data = D;
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn poll_data(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
Poll::Ready(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
Poll::Ready(Ok(None))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> SizeHint {
|
||||||
|
SizeHint::with_exact(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> fmt::Debug for Empty<D> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("Empty").finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> Default for Empty<D> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> Clone for Empty<D> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> Copy for Empty<D> {}
|
|
@ -0,0 +1,151 @@
|
||||||
|
use crate::{Body, SizeHint};
|
||||||
|
use bytes::{Buf, Bytes};
|
||||||
|
use http::HeaderMap;
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::convert::{Infallible, TryFrom};
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
|
pin_project! {
|
||||||
|
/// A body that consists of a single chunk.
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct Full<D> {
|
||||||
|
data: Option<D>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> Full<D>
|
||||||
|
where
|
||||||
|
D: Buf,
|
||||||
|
{
|
||||||
|
/// Create a new `Full`.
|
||||||
|
pub fn new(data: D) -> Self {
|
||||||
|
let data = if data.has_remaining() {
|
||||||
|
Some(data)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
Full { data }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> Body for Full<D>
|
||||||
|
where
|
||||||
|
D: Buf,
|
||||||
|
{
|
||||||
|
type Data = D;
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<D, Self::Error>>> {
|
||||||
|
Poll::Ready(self.data.take().map(Ok))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
Poll::Ready(Ok(None))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
self.data.is_none()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> SizeHint {
|
||||||
|
self.data
|
||||||
|
.as_ref()
|
||||||
|
.map(|data| SizeHint::with_exact(u64::try_from(data.remaining()).unwrap()))
|
||||||
|
.unwrap_or_else(|| SizeHint::with_exact(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> Default for Full<D>
|
||||||
|
where
|
||||||
|
D: Buf,
|
||||||
|
{
|
||||||
|
/// Create an empty `Full`.
|
||||||
|
fn default() -> Self {
|
||||||
|
Full { data: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> From<Bytes> for Full<D>
|
||||||
|
where
|
||||||
|
D: Buf + From<Bytes>,
|
||||||
|
{
|
||||||
|
fn from(bytes: Bytes) -> Self {
|
||||||
|
Full::new(D::from(bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> From<Vec<u8>> for Full<D>
|
||||||
|
where
|
||||||
|
D: Buf + From<Vec<u8>>,
|
||||||
|
{
|
||||||
|
fn from(vec: Vec<u8>) -> Self {
|
||||||
|
Full::new(D::from(vec))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> From<&'static [u8]> for Full<D>
|
||||||
|
where
|
||||||
|
D: Buf + From<&'static [u8]>,
|
||||||
|
{
|
||||||
|
fn from(slice: &'static [u8]) -> Self {
|
||||||
|
Full::new(D::from(slice))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D, B> From<Cow<'static, B>> for Full<D>
|
||||||
|
where
|
||||||
|
D: Buf + From<&'static B> + From<B::Owned>,
|
||||||
|
B: ToOwned + ?Sized,
|
||||||
|
{
|
||||||
|
fn from(cow: Cow<'static, B>) -> Self {
|
||||||
|
match cow {
|
||||||
|
Cow::Borrowed(b) => Full::new(D::from(b)),
|
||||||
|
Cow::Owned(o) => Full::new(D::from(o)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> From<String> for Full<D>
|
||||||
|
where
|
||||||
|
D: Buf + From<String>,
|
||||||
|
{
|
||||||
|
fn from(s: String) -> Self {
|
||||||
|
Full::new(D::from(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> From<&'static str> for Full<D>
|
||||||
|
where
|
||||||
|
D: Buf + From<&'static str>,
|
||||||
|
{
|
||||||
|
fn from(slice: &'static str) -> Self {
|
||||||
|
Full::new(D::from(slice))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn full_returns_some() {
|
||||||
|
let mut full = Full::new(&b"hello"[..]);
|
||||||
|
assert_eq!(full.size_hint().exact(), Some(b"hello".len() as u64));
|
||||||
|
assert_eq!(full.data().await, Some(Ok(&b"hello"[..])));
|
||||||
|
assert!(full.data().await.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn empty_full_returns_none() {
|
||||||
|
assert!(Full::<&[u8]>::default().data().await.is_none());
|
||||||
|
assert!(Full::new(&b""[..]).data().await.is_none());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,324 @@
|
||||||
|
#![doc(html_root_url = "https://docs.rs/http-body/0.4.5")]
|
||||||
|
#![deny(
|
||||||
|
missing_debug_implementations,
|
||||||
|
missing_docs,
|
||||||
|
unreachable_pub,
|
||||||
|
broken_intra_doc_links
|
||||||
|
)]
|
||||||
|
#![cfg_attr(test, deny(warnings))]
|
||||||
|
|
||||||
|
//! Asynchronous HTTP request or response body.
|
||||||
|
//!
|
||||||
|
//! See [`Body`] for more details.
|
||||||
|
//!
|
||||||
|
//! [`Body`]: trait.Body.html
|
||||||
|
|
||||||
|
mod empty;
|
||||||
|
mod full;
|
||||||
|
mod limited;
|
||||||
|
mod next;
|
||||||
|
mod size_hint;
|
||||||
|
|
||||||
|
pub mod combinators;
|
||||||
|
|
||||||
|
pub use self::empty::Empty;
|
||||||
|
pub use self::full::Full;
|
||||||
|
pub use self::limited::{LengthLimitError, Limited};
|
||||||
|
pub use self::next::{Data, Trailers};
|
||||||
|
pub use self::size_hint::SizeHint;
|
||||||
|
|
||||||
|
use self::combinators::{BoxBody, MapData, MapErr, UnsyncBoxBody};
|
||||||
|
use bytes::{Buf, Bytes};
|
||||||
|
use http::HeaderMap;
|
||||||
|
use std::convert::Infallible;
|
||||||
|
use std::ops;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
|
/// Trait representing a streaming body of a Request or Response.
|
||||||
|
///
|
||||||
|
/// Data is streamed via the `poll_data` function, which asynchronously yields `T: Buf` values. The
|
||||||
|
/// `size_hint` function provides insight into the total number of bytes that will be streamed.
|
||||||
|
///
|
||||||
|
/// The `poll_trailers` function returns an optional set of trailers used to finalize the request /
|
||||||
|
/// response exchange. This is mostly used when using the HTTP/2.0 protocol.
|
||||||
|
///
|
||||||
|
pub trait Body {
|
||||||
|
/// Values yielded by the `Body`.
|
||||||
|
type Data: Buf;
|
||||||
|
|
||||||
|
/// The error type this `Body` might generate.
|
||||||
|
type Error;
|
||||||
|
|
||||||
|
/// Attempt to pull out the next data buffer of this stream.
|
||||||
|
fn poll_data(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>>;
|
||||||
|
|
||||||
|
/// Poll for an optional **single** `HeaderMap` of trailers.
|
||||||
|
///
|
||||||
|
/// This function should only be called once `poll_data` returns `None`.
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>>;
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// returned from `poll_stream` or `poll_trailers`.
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the bounds on the remaining length of the stream.
|
||||||
|
///
|
||||||
|
/// When the **exact** remaining length of the stream is known, the upper bound will be set and
|
||||||
|
/// will equal the lower bound.
|
||||||
|
fn size_hint(&self) -> SizeHint {
|
||||||
|
SizeHint::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns future that resolves to next data chunk, if any.
|
||||||
|
fn data(&mut self) -> Data<'_, Self>
|
||||||
|
where
|
||||||
|
Self: Unpin + Sized,
|
||||||
|
{
|
||||||
|
Data(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns future that resolves to trailers, if any.
|
||||||
|
fn trailers(&mut self) -> Trailers<'_, Self>
|
||||||
|
where
|
||||||
|
Self: Unpin + Sized,
|
||||||
|
{
|
||||||
|
Trailers(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Maps this body's data value to a different value.
|
||||||
|
fn map_data<F, B>(self, f: F) -> MapData<Self, F>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
F: FnMut(Self::Data) -> B,
|
||||||
|
B: Buf,
|
||||||
|
{
|
||||||
|
MapData::new(self, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Maps this body's error value to a different value.
|
||||||
|
fn map_err<F, E>(self, f: F) -> MapErr<Self, F>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
F: FnMut(Self::Error) -> E,
|
||||||
|
{
|
||||||
|
MapErr::new(self, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Turn this body into a boxed trait object.
|
||||||
|
fn boxed(self) -> BoxBody<Self::Data, Self::Error>
|
||||||
|
where
|
||||||
|
Self: Sized + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
BoxBody::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Turn this body into a boxed trait object that is !Sync.
|
||||||
|
fn boxed_unsync(self) -> UnsyncBoxBody<Self::Data, Self::Error>
|
||||||
|
where
|
||||||
|
Self: Sized + Send + 'static,
|
||||||
|
{
|
||||||
|
UnsyncBoxBody::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Body + Unpin + ?Sized> Body for &mut T {
|
||||||
|
type Data = T::Data;
|
||||||
|
type Error = T::Error;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
Pin::new(&mut **self).poll_data(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
Pin::new(&mut **self).poll_trailers(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
Pin::new(&**self).is_end_stream()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> SizeHint {
|
||||||
|
Pin::new(&**self).size_hint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P> Body for Pin<P>
|
||||||
|
where
|
||||||
|
P: Unpin + ops::DerefMut,
|
||||||
|
P::Target: Body,
|
||||||
|
{
|
||||||
|
type Data = <<P as ops::Deref>::Target as Body>::Data;
|
||||||
|
type Error = <<P as ops::Deref>::Target as Body>::Error;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
Pin::get_mut(self).as_mut().poll_data(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
Pin::get_mut(self).as_mut().poll_trailers(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
self.as_ref().is_end_stream()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> SizeHint {
|
||||||
|
self.as_ref().size_hint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Body + Unpin + ?Sized> Body for Box<T> {
|
||||||
|
type Data = T::Data;
|
||||||
|
type Error = T::Error;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
Pin::new(&mut **self).poll_data(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
Pin::new(&mut **self).poll_trailers(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
self.as_ref().is_end_stream()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> SizeHint {
|
||||||
|
self.as_ref().size_hint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: Body> Body for http::Request<B> {
|
||||||
|
type Data = B::Data;
|
||||||
|
type Error = B::Error;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
unsafe {
|
||||||
|
self.map_unchecked_mut(http::Request::body_mut)
|
||||||
|
.poll_data(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
unsafe {
|
||||||
|
self.map_unchecked_mut(http::Request::body_mut)
|
||||||
|
.poll_trailers(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
self.body().is_end_stream()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> SizeHint {
|
||||||
|
self.body().size_hint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: Body> Body for http::Response<B> {
|
||||||
|
type Data = B::Data;
|
||||||
|
type Error = B::Error;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
unsafe {
|
||||||
|
self.map_unchecked_mut(http::Response::body_mut)
|
||||||
|
.poll_data(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
unsafe {
|
||||||
|
self.map_unchecked_mut(http::Response::body_mut)
|
||||||
|
.poll_trailers(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
self.body().is_end_stream()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> SizeHint {
|
||||||
|
self.body().size_hint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Body for String {
|
||||||
|
type Data = Bytes;
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
if !self.is_empty() {
|
||||||
|
let s = std::mem::take(&mut *self);
|
||||||
|
Poll::Ready(Some(Ok(s.into_bytes().into())))
|
||||||
|
} else {
|
||||||
|
Poll::Ready(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
Poll::Ready(Ok(None))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
self.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> SizeHint {
|
||||||
|
SizeHint::with_exact(self.len() as u64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn _assert_bounds() {
|
||||||
|
fn can_be_trait_object(_: &dyn Body<Data = std::io::Cursor<Vec<u8>>, Error = std::io::Error>) {}
|
||||||
|
}
|
|
@ -0,0 +1,299 @@
|
||||||
|
use crate::{Body, SizeHint};
|
||||||
|
use bytes::Buf;
|
||||||
|
use http::HeaderMap;
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
|
pin_project! {
|
||||||
|
/// A length limited body.
|
||||||
|
///
|
||||||
|
/// This body will return an error if more than the configured number
|
||||||
|
/// of bytes are returned on polling the wrapped body.
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct Limited<B> {
|
||||||
|
remaining: usize,
|
||||||
|
#[pin]
|
||||||
|
inner: B,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B> Limited<B> {
|
||||||
|
/// Create a new `Limited`.
|
||||||
|
pub fn new(inner: B, limit: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
remaining: limit,
|
||||||
|
inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B> Body for Limited<B>
|
||||||
|
where
|
||||||
|
B: Body,
|
||||||
|
B::Error: Into<Box<dyn Error + Send + Sync>>,
|
||||||
|
{
|
||||||
|
type Data = B::Data;
|
||||||
|
type Error = Box<dyn Error + Send + Sync>;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
let this = self.project();
|
||||||
|
let res = match this.inner.poll_data(cx) {
|
||||||
|
Poll::Pending => return Poll::Pending,
|
||||||
|
Poll::Ready(None) => None,
|
||||||
|
Poll::Ready(Some(Ok(data))) => {
|
||||||
|
if data.remaining() > *this.remaining {
|
||||||
|
*this.remaining = 0;
|
||||||
|
Some(Err(LengthLimitError.into()))
|
||||||
|
} else {
|
||||||
|
*this.remaining -= data.remaining();
|
||||||
|
Some(Ok(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Poll::Ready(Some(Err(err))) => Some(Err(err.into())),
|
||||||
|
};
|
||||||
|
|
||||||
|
Poll::Ready(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
let this = self.project();
|
||||||
|
let res = match this.inner.poll_trailers(cx) {
|
||||||
|
Poll::Pending => return Poll::Pending,
|
||||||
|
Poll::Ready(Ok(data)) => Ok(data),
|
||||||
|
Poll::Ready(Err(err)) => Err(err.into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
Poll::Ready(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_end_stream(&self) -> bool {
|
||||||
|
self.inner.is_end_stream()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> SizeHint {
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
match u64::try_from(self.remaining) {
|
||||||
|
Ok(n) => {
|
||||||
|
let mut hint = self.inner.size_hint();
|
||||||
|
if hint.lower() >= n {
|
||||||
|
hint.set_exact(n)
|
||||||
|
} else if let Some(max) = hint.upper() {
|
||||||
|
hint.set_upper(n.min(max))
|
||||||
|
} else {
|
||||||
|
hint.set_upper(n)
|
||||||
|
}
|
||||||
|
hint
|
||||||
|
}
|
||||||
|
Err(_) => self.inner.size_hint(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An error returned when body length exceeds the configured limit.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct LengthLimitError;
|
||||||
|
|
||||||
|
impl fmt::Display for LengthLimitError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.write_str("length limit exceeded")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for LengthLimitError {}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::Full;
|
||||||
|
use bytes::Bytes;
|
||||||
|
use std::convert::Infallible;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn read_for_body_under_limit_returns_data() {
|
||||||
|
const DATA: &[u8] = b"testing";
|
||||||
|
let inner = Full::new(Bytes::from(DATA));
|
||||||
|
let body = &mut Limited::new(inner, 8);
|
||||||
|
|
||||||
|
let mut hint = SizeHint::new();
|
||||||
|
hint.set_upper(7);
|
||||||
|
assert_eq!(body.size_hint().upper(), hint.upper());
|
||||||
|
|
||||||
|
let data = body.data().await.unwrap().unwrap();
|
||||||
|
assert_eq!(data, DATA);
|
||||||
|
hint.set_upper(0);
|
||||||
|
assert_eq!(body.size_hint().upper(), hint.upper());
|
||||||
|
|
||||||
|
assert!(matches!(body.data().await, None));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn read_for_body_over_limit_returns_error() {
|
||||||
|
const DATA: &[u8] = b"testing a string that is too long";
|
||||||
|
let inner = Full::new(Bytes::from(DATA));
|
||||||
|
let body = &mut Limited::new(inner, 8);
|
||||||
|
|
||||||
|
let mut hint = SizeHint::new();
|
||||||
|
hint.set_upper(8);
|
||||||
|
assert_eq!(body.size_hint().upper(), hint.upper());
|
||||||
|
|
||||||
|
let error = body.data().await.unwrap().unwrap_err();
|
||||||
|
assert!(matches!(error.downcast_ref(), Some(LengthLimitError)));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Chunky(&'static [&'static [u8]]);
|
||||||
|
|
||||||
|
impl Body for Chunky {
|
||||||
|
type Data = &'static [u8];
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
let mut this = self;
|
||||||
|
match this.0.split_first().map(|(&head, tail)| (Ok(head), tail)) {
|
||||||
|
Some((data, new_tail)) => {
|
||||||
|
this.0 = new_tail;
|
||||||
|
|
||||||
|
Poll::Ready(Some(data))
|
||||||
|
}
|
||||||
|
None => Poll::Ready(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
Poll::Ready(Ok(Some(HeaderMap::new())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn read_for_chunked_body_around_limit_returns_first_chunk_but_returns_error_on_over_limit_chunk(
|
||||||
|
) {
|
||||||
|
const DATA: &[&[u8]] = &[b"testing ", b"a string that is too long"];
|
||||||
|
let inner = Chunky(DATA);
|
||||||
|
let body = &mut Limited::new(inner, 8);
|
||||||
|
|
||||||
|
let mut hint = SizeHint::new();
|
||||||
|
hint.set_upper(8);
|
||||||
|
assert_eq!(body.size_hint().upper(), hint.upper());
|
||||||
|
|
||||||
|
let data = body.data().await.unwrap().unwrap();
|
||||||
|
assert_eq!(data, DATA[0]);
|
||||||
|
hint.set_upper(0);
|
||||||
|
assert_eq!(body.size_hint().upper(), hint.upper());
|
||||||
|
|
||||||
|
let error = body.data().await.unwrap().unwrap_err();
|
||||||
|
assert!(matches!(error.downcast_ref(), Some(LengthLimitError)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn read_for_chunked_body_over_limit_on_first_chunk_returns_error() {
|
||||||
|
const DATA: &[&[u8]] = &[b"testing a string", b" that is too long"];
|
||||||
|
let inner = Chunky(DATA);
|
||||||
|
let body = &mut Limited::new(inner, 8);
|
||||||
|
|
||||||
|
let mut hint = SizeHint::new();
|
||||||
|
hint.set_upper(8);
|
||||||
|
assert_eq!(body.size_hint().upper(), hint.upper());
|
||||||
|
|
||||||
|
let error = body.data().await.unwrap().unwrap_err();
|
||||||
|
assert!(matches!(error.downcast_ref(), Some(LengthLimitError)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn read_for_chunked_body_under_limit_is_okay() {
|
||||||
|
const DATA: &[&[u8]] = &[b"test", b"ing!"];
|
||||||
|
let inner = Chunky(DATA);
|
||||||
|
let body = &mut Limited::new(inner, 8);
|
||||||
|
|
||||||
|
let mut hint = SizeHint::new();
|
||||||
|
hint.set_upper(8);
|
||||||
|
assert_eq!(body.size_hint().upper(), hint.upper());
|
||||||
|
|
||||||
|
let data = body.data().await.unwrap().unwrap();
|
||||||
|
assert_eq!(data, DATA[0]);
|
||||||
|
hint.set_upper(4);
|
||||||
|
assert_eq!(body.size_hint().upper(), hint.upper());
|
||||||
|
|
||||||
|
let data = body.data().await.unwrap().unwrap();
|
||||||
|
assert_eq!(data, DATA[1]);
|
||||||
|
hint.set_upper(0);
|
||||||
|
assert_eq!(body.size_hint().upper(), hint.upper());
|
||||||
|
|
||||||
|
assert!(matches!(body.data().await, None));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn read_for_trailers_propagates_inner_trailers() {
|
||||||
|
const DATA: &[&[u8]] = &[b"test", b"ing!"];
|
||||||
|
let inner = Chunky(DATA);
|
||||||
|
let body = &mut Limited::new(inner, 8);
|
||||||
|
let trailers = body.trailers().await.unwrap();
|
||||||
|
assert_eq!(trailers, Some(HeaderMap::new()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum ErrorBodyError {
|
||||||
|
Data,
|
||||||
|
Trailers,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ErrorBodyError {
|
||||||
|
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ErrorBodyError {}
|
||||||
|
|
||||||
|
struct ErrorBody;
|
||||||
|
|
||||||
|
impl Body for ErrorBody {
|
||||||
|
type Data = &'static [u8];
|
||||||
|
type Error = ErrorBodyError;
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
Poll::Ready(Some(Err(ErrorBodyError::Data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
Poll::Ready(Err(ErrorBodyError::Trailers))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn read_for_body_returning_error_propagates_error() {
|
||||||
|
let body = &mut Limited::new(ErrorBody, 8);
|
||||||
|
let error = body.data().await.unwrap().unwrap_err();
|
||||||
|
assert!(matches!(error.downcast_ref(), Some(ErrorBodyError::Data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn trailers_for_body_returning_error_propagates_error() {
|
||||||
|
let body = &mut Limited::new(ErrorBody, 8);
|
||||||
|
let error = body.trailers().await.unwrap_err();
|
||||||
|
assert!(matches!(
|
||||||
|
error.downcast_ref(),
|
||||||
|
Some(ErrorBodyError::Trailers)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
use crate::Body;
|
||||||
|
|
||||||
|
use core::future::Future;
|
||||||
|
use core::pin::Pin;
|
||||||
|
use core::task;
|
||||||
|
|
||||||
|
#[must_use = "futures don't do anything unless polled"]
|
||||||
|
#[derive(Debug)]
|
||||||
|
/// Future that resolves to the next data chunk from `Body`
|
||||||
|
pub struct Data<'a, T: ?Sized>(pub(crate) &'a mut T);
|
||||||
|
|
||||||
|
impl<'a, T: Body + Unpin + ?Sized> Future for Data<'a, T> {
|
||||||
|
type Output = Option<Result<T::Data, T::Error>>;
|
||||||
|
|
||||||
|
fn poll(mut self: Pin<&mut Self>, ctx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
|
||||||
|
Pin::new(&mut self.0).poll_data(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use = "futures don't do anything unless polled"]
|
||||||
|
#[derive(Debug)]
|
||||||
|
/// Future that resolves to the optional trailers from `Body`
|
||||||
|
pub struct Trailers<'a, T: ?Sized>(pub(crate) &'a mut T);
|
||||||
|
|
||||||
|
impl<'a, T: Body + Unpin + ?Sized> Future for Trailers<'a, T> {
|
||||||
|
type Output = Result<Option<http::HeaderMap>, T::Error>;
|
||||||
|
|
||||||
|
fn poll(mut self: Pin<&mut Self>, ctx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
|
||||||
|
Pin::new(&mut self.0).poll_trailers(ctx)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
use std::u64;
|
||||||
|
|
||||||
|
/// A `Body` size hint
|
||||||
|
///
|
||||||
|
/// The default implementation returns:
|
||||||
|
///
|
||||||
|
/// * 0 for `lower`
|
||||||
|
/// * `None` for `upper`.
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct SizeHint {
|
||||||
|
lower: u64,
|
||||||
|
upper: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SizeHint {
|
||||||
|
/// Returns a new `SizeHint` with default values
|
||||||
|
#[inline]
|
||||||
|
pub fn new() -> SizeHint {
|
||||||
|
SizeHint::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new `SizeHint` with both upper and lower bounds set to the
|
||||||
|
/// given value.
|
||||||
|
#[inline]
|
||||||
|
pub fn with_exact(value: u64) -> SizeHint {
|
||||||
|
SizeHint {
|
||||||
|
lower: value,
|
||||||
|
upper: Some(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the lower bound of data that the `Body` will yield before
|
||||||
|
/// completing.
|
||||||
|
#[inline]
|
||||||
|
pub fn lower(&self) -> u64 {
|
||||||
|
self.lower
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the value of the `lower` hint.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// The function panics if `value` is greater than `upper`.
|
||||||
|
#[inline]
|
||||||
|
pub fn set_lower(&mut self, value: u64) {
|
||||||
|
assert!(value <= self.upper.unwrap_or(u64::MAX));
|
||||||
|
self.lower = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the upper bound of data the `Body` will yield before
|
||||||
|
/// completing, or `None` if the value is unknown.
|
||||||
|
#[inline]
|
||||||
|
pub fn upper(&self) -> Option<u64> {
|
||||||
|
self.upper
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the value of the `upper` hint value.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function panics if `value` is less than `lower`.
|
||||||
|
#[inline]
|
||||||
|
pub fn set_upper(&mut self, value: u64) {
|
||||||
|
assert!(value >= self.lower, "`value` is less than than `lower`");
|
||||||
|
|
||||||
|
self.upper = Some(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the exact size of data that will be yielded **if** the
|
||||||
|
/// `lower` and `upper` bounds are equal.
|
||||||
|
#[inline]
|
||||||
|
pub fn exact(&self) -> Option<u64> {
|
||||||
|
if Some(self.lower) == self.upper {
|
||||||
|
self.upper
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the value of the `lower` and `upper` bounds to exactly the same.
|
||||||
|
#[inline]
|
||||||
|
pub fn set_exact(&mut self, value: u64) {
|
||||||
|
self.lower = value;
|
||||||
|
self.upper = Some(value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
use http::HeaderMap;
|
||||||
|
use http_body::{Body, SizeHint};
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
|
struct Mock {
|
||||||
|
size_hint: SizeHint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Body for Mock {
|
||||||
|
type Data = ::std::io::Cursor<Vec<u8>>;
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn poll_data(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||||
|
Poll::Ready(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_trailers(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
|
Poll::Ready(Ok(None))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> SizeHint {
|
||||||
|
self.size_hint.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn is_end_stream_true() {
|
||||||
|
let combos = [
|
||||||
|
(None, None, false),
|
||||||
|
(Some(123), None, false),
|
||||||
|
(Some(0), Some(123), false),
|
||||||
|
(Some(123), Some(123), false),
|
||||||
|
(Some(0), Some(0), false),
|
||||||
|
];
|
||||||
|
|
||||||
|
for &(lower, upper, is_end_stream) in &combos {
|
||||||
|
let mut size_hint = SizeHint::new();
|
||||||
|
assert_eq!(0, size_hint.lower());
|
||||||
|
assert!(size_hint.upper().is_none());
|
||||||
|
|
||||||
|
if let Some(lower) = lower {
|
||||||
|
size_hint.set_lower(lower);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(upper) = upper {
|
||||||
|
size_hint.set_upper(upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mock = Mock { size_hint };
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
is_end_stream,
|
||||||
|
Pin::new(&mut mock).is_end_stream(),
|
||||||
|
"size_hint = {:?}",
|
||||||
|
mock.size_hint.clone()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn is_end_stream_default_false() {
|
||||||
|
let mut mock = Mock {
|
||||||
|
size_hint: SizeHint::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
false,
|
||||||
|
Pin::new(&mut mock).is_end_stream(),
|
||||||
|
"size_hint = {:?}",
|
||||||
|
mock.size_hint.clone()
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue