Avoid double-boxing bodies where possible (#569)

* Avoid double-boxing bodies where possible

* Extract `try_downcast` to `util` module
This commit is contained in:
Kai Jewson 2021-11-27 09:20:31 +00:00 committed by GitHub
parent 96b353b556
commit decdd4c948
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 17 deletions

View file

@ -1,6 +1,6 @@
//! HTTP body utilities.
use crate::{BoxError, Error};
use crate::{util::try_downcast, BoxError, Error};
mod stream_body;
@ -27,7 +27,7 @@ where
B: http_body::Body<Data = Bytes> + Send + 'static,
B::Error: Into<BoxError>,
{
body.map_err(Error::new).boxed_unsync()
try_downcast(body).unwrap_or_else(|body| body.map_err(Error::new).boxed_unsync())
}
pub(crate) fn empty() -> BoxBody {

View file

@ -8,7 +8,7 @@ use crate::{
MatchedPath, OriginalUri,
},
routing::strip_prefix::StripPrefix,
util::{ByteStr, PercentDecodedByteStr},
util::{try_downcast, ByteStr, PercentDecodedByteStr},
BoxError,
};
use bytes::Bytes;
@ -657,20 +657,6 @@ impl<B, E> Fallback<B, E> {
}
}
fn try_downcast<T, K>(k: K) -> Result<T, K>
where
T: 'static,
K: Send + 'static,
{
use std::any::Any;
let k = Box::new(k) as Box<dyn Any + Send + 'static>;
match k.downcast() {
Ok(t) => Ok(*t),
Err(other) => Err(*other.downcast().unwrap()),
}
}
enum Endpoint<B> {
MethodRouter(MethodRouter<B>),
Route(Route<B>),

View file

@ -65,3 +65,22 @@ pin_project! {
B { #[pin] inner: B },
}
}
pub(crate) fn try_downcast<T, K>(k: K) -> Result<T, K>
where
T: 'static,
K: Send + 'static,
{
let mut k = Some(k);
if let Some(k) = <dyn std::any::Any>::downcast_mut::<Option<T>>(&mut k) {
Ok(k.take().unwrap())
} else {
Err(k.unwrap())
}
}
#[test]
fn test_try_downcast() {
assert_eq!(try_downcast::<i32, _>(5_u32), Err(5_u32));
assert_eq!(try_downcast::<i32, _>(5_i32), Ok(5_i32));
}