Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
+120
View File
@@ -0,0 +1,120 @@
use http::HeaderMap;
/// A frame of any kind related to an HTTP stream (body).
#[derive(Debug)]
pub struct Frame<T> {
kind: Kind<T>,
}
#[derive(Debug)]
enum Kind<T> {
// The first two variants are "inlined" since they are undoubtedly
// the most common. This saves us from having to allocate a
// boxed trait object for them.
Data(T),
Trailers(HeaderMap),
//Unknown(Box<dyn Frameish>),
}
impl<T> Frame<T> {
/// Create a DATA frame with the provided `Buf`.
pub fn data(buf: T) -> Self {
Self {
kind: Kind::Data(buf),
}
}
/// Create a trailers frame.
pub fn trailers(map: HeaderMap) -> Self {
Self {
kind: Kind::Trailers(map),
}
}
/// Maps this frame's data to a different type.
pub fn map_data<F, D>(self, f: F) -> Frame<D>
where
F: FnOnce(T) -> D,
{
match self.kind {
Kind::Data(data) => Frame {
kind: Kind::Data(f(data)),
},
Kind::Trailers(trailers) => Frame {
kind: Kind::Trailers(trailers),
},
}
}
/// Returns whether this is a DATA frame.
pub fn is_data(&self) -> bool {
matches!(self.kind, Kind::Data(..))
}
/// Consumes self into the buf of the DATA frame.
///
/// Returns an [`Err`] containing the original [`Frame`] when frame is not a DATA frame.
/// `Frame::is_data` can also be used to determine if the frame is a DATA frame.
pub fn into_data(self) -> Result<T, Self> {
match self.kind {
Kind::Data(data) => Ok(data),
_ => Err(self),
}
}
/// If this is a DATA frame, returns a reference to it.
///
/// Returns `None` if not a DATA frame.
pub fn data_ref(&self) -> Option<&T> {
match self.kind {
Kind::Data(ref data) => Some(data),
_ => None,
}
}
/// If this is a DATA frame, returns a mutable reference to it.
///
/// Returns `None` if not a DATA frame.
pub fn data_mut(&mut self) -> Option<&mut T> {
match self.kind {
Kind::Data(ref mut data) => Some(data),
_ => None,
}
}
/// Returns whether this is a trailers frame.
pub fn is_trailers(&self) -> bool {
matches!(self.kind, Kind::Trailers(..))
}
/// Consumes self into the buf of the trailers frame.
///
/// Returns an [`Err`] containing the original [`Frame`] when frame is not a trailers frame.
/// `Frame::is_trailers` can also be used to determine if the frame is a trailers frame.
pub fn into_trailers(self) -> Result<HeaderMap, Self> {
match self.kind {
Kind::Trailers(trailers) => Ok(trailers),
_ => Err(self),
}
}
/// If this is a trailers frame, returns a reference to it.
///
/// Returns `None` if not a trailers frame.
pub fn trailers_ref(&self) -> Option<&HeaderMap> {
match self.kind {
Kind::Trailers(ref trailers) => Some(trailers),
_ => None,
}
}
/// If this is a trailers frame, returns a mutable reference to it.
///
/// Returns `None` if not a trailers frame.
pub fn trailers_mut(&mut self) -> Option<&mut HeaderMap> {
match self.kind {
Kind::Trailers(ref mut trailers) => Some(trailers),
_ => None,
}
}
}
+232
View File
@@ -0,0 +1,232 @@
#![deny(
missing_debug_implementations,
missing_docs,
unreachable_pub,
clippy::missing_safety_doc,
clippy::undocumented_unsafe_blocks
)]
#![cfg_attr(test, deny(warnings))]
//! Asynchronous HTTP request or response body.
//!
//! See [`Body`] for more details.
//!
//! [`Body`]: trait.Body.html
mod frame;
mod size_hint;
pub use self::frame::Frame;
pub use self::size_hint::SizeHint;
use bytes::{Buf, Bytes};
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.
///
/// Individual frames are streamed via the `poll_frame` function, which asynchronously yields
/// instances of [`Frame<Data>`].
///
/// Frames can contain a data buffer of type `Self::Data`. Frames can also contain an optional
/// set of trailers used to finalize the request/response exchange. This is mostly used when using
/// the HTTP/2.0 protocol.
///
/// The `size_hint` function provides insight into the total number of bytes that will be streamed.
pub trait Body {
/// Values yielded by the `Body`.
type Data: Buf;
/// The error type this `Body` might generate.
type Error;
#[allow(clippy::type_complexity)]
/// Attempt to pull out the next frame of this stream.
///
/// # Return value
///
/// This function returns:
///
/// - `Poll::Pending` if the next frame is not ready yet.
/// - `Poll::Ready(Some(Ok(frame)))` when the next frame is available.
/// - `Poll::Ready(Some(Err(error)))` when an error has been reached.
/// - `Poll::Ready(None)` means that all of the frames in this stream have been returned, and
/// that the end of the stream has been reached.
///
/// If `Poll::Ready(Some(Err(error)))` is returned, this body should be discarded.
///
/// Once the end of the stream is reached, implementations should continue to return
/// `Poll::Ready(None)`.
fn poll_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>>;
/// A hint that may return `true` when the end of stream has been reached.
///
/// An end of stream means that `poll_frame` will return `None`.
///
/// A return value of `false` **does not** guarantee that a value will be
/// returned from `poll_frame`. Combinators or other implementations may
/// not be able to know the end of stream has been reached for this hint.
///
/// Returning `true` allows consumers of this body to optimize, such as not
/// calling `poll_frame` again.
fn is_end_stream(&self) -> bool {
false
}
/// A hint that 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()
}
}
impl<T: Body + Unpin + ?Sized> Body for &mut T {
type Data = T::Data;
type Error = T::Error;
fn poll_frame(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
Pin::new(&mut **self).poll_frame(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_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
Pin::get_mut(self).as_mut().poll_frame(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_frame(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
Pin::new(&mut **self).poll_frame(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_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
// SAFETY:
// A pin projection.
unsafe {
self.map_unchecked_mut(http::Request::body_mut)
.poll_frame(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_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
// SAFETY:
// A pin projection.
unsafe {
self.map_unchecked_mut(http::Response::body_mut)
.poll_frame(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_frame(
mut self: Pin<&mut Self>,
_cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
if !self.is_empty() {
let s = std::mem::take(&mut *self);
Poll::Ready(Some(Ok(Frame::data(s.into_bytes().into()))))
} else {
Poll::Ready(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>) {}
}
+207
View File
@@ -0,0 +1,207 @@
/// A `Body` size hint
///
/// The default implementation returns:
///
/// * 0 for `lower`
/// * `None` for `upper`.
#[derive(Debug, Default, Clone, Copy)]
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);
}
}
/// Perfectly adds two `SizeHint'`s
impl core::ops::Add for SizeHint {
type Output = SizeHint;
fn add(self, rhs: Self) -> Self::Output {
SizeHint {
lower: self.lower() + rhs.lower(),
upper: self
.upper()
.and_then(|this| rhs.upper().map(|rhs| this + rhs)),
}
}
}
/// Asserts that SizeHint addition is perfect with a basic proof
#[test]
fn size_hint_addition_proof() {
/// Converts a SizeHint to a tuple for equality checks and matching
fn to_parts(s: SizeHint) -> (u64, Option<u64>) {
(s.lower(), s.upper())
}
// assuming addition itself is perfect, there are 3 distinct states:
// (_, Some(_)) + (_, Some(_)) => (_ + _, Some(_ + _))
// (_, Some(_)) + (_, None) => (_ + _, None)
// (_, None) + (_, None) => (_ + _, None)
//
// we can assert this in the typesystem! (and name them for our tests)
match (to_parts(SizeHint::new()), to_parts(SizeHint::new())) {
((_, Some(_)), (_, Some(_))) => {} // 1
((_, None), (_, None)) => {} // 2
// note that these cases are identical if we can prove lhs + rhs is equivalent to rhs + lhs
// see below, we do prove that!
((_, Some(_)), (_, None)) => {} // 3
((_, None), (_, Some(_))) => {}
}
//
// Additionally, we assert a with_exact remains intact if we add two with_exact's together
//
// Additionally, we assert that all operations are equivalent if we do a + b vs b + a
// asserts a + b == b + a == eq
macro_rules! reciprocal_add_eq {
($a:expr, $b:expr, $eq:expr) => {
assert_eq!(to_parts($a.clone() + $b.clone()), $eq);
assert_eq!(to_parts($b.clone() + $a.clone()), $eq);
};
}
// note that we use increasing powers of two every time we fetch a number, this ensures all
// numbers will add uniquely
let exact_1 = SizeHint::with_exact(1);
let exact_2 = SizeHint::with_exact(2);
// with_exact
reciprocal_add_eq!(exact_1, exact_2, to_parts(SizeHint::with_exact(1 + 2)));
let some_lhs = SizeHint {
lower: 4,
upper: Some(8),
};
let some_rhs = SizeHint {
lower: 16,
upper: Some(32),
};
// case 1
reciprocal_add_eq!(some_lhs, some_rhs, (4 + 16, Some(8 + 32)));
let none_lhs = SizeHint {
lower: 64,
upper: None,
};
let none_rhs = SizeHint {
lower: 128,
upper: None,
};
// case 2
reciprocal_add_eq!(none_lhs, none_rhs, (64 + 128, None));
// case 3
reciprocal_add_eq!(some_lhs, none_rhs, (4 + 128, None));
}
/// Asserts that some "real data" gets passed through without issue
#[test]
fn size_hint_addition_basic() {
let exact_l = SizeHint::with_exact(20);
let exact_r = SizeHint::with_exact(5);
assert_eq!(Some(25), (exact_l + exact_r).exact());
let inexact_l = SizeHint {
lower: 25,
upper: None,
};
let inexact_r = SizeHint {
lower: 10,
upper: Some(50),
};
let inexact = inexact_l + inexact_r;
assert_eq!(inexact.lower(), 35);
assert_eq!(inexact.upper(), None);
let exact_inexact = exact_l + inexact_r;
assert_eq!(exact_inexact.lower(), 30);
assert_eq!(exact_inexact.upper(), Some(70));
// same as previous but reversed operation order
let inexact_exact = inexact_r + exact_l;
assert_eq!(inexact_exact.lower(), 30);
assert_eq!(inexact_exact.upper(), Some(70));
}