Improve value and reference passing efficiency (#3406)

This commit is contained in:
Theodore Bjernhed
2025-07-11 05:38:45 +02:00
committed by GitHub
parent 420d7b6aaa
commit 6bc0717b06
17 changed files with 117 additions and 107 deletions
+6
View File
@@ -29,6 +29,7 @@ exit = "warn"
filter_map_next = "warn" filter_map_next = "warn"
fn_params_excessive_bools = "warn" fn_params_excessive_bools = "warn"
if_let_mutex = "warn" if_let_mutex = "warn"
implicit_clone = "warn"
imprecise_flops = "warn" imprecise_flops = "warn"
inefficient_to_string = "warn" inefficient_to_string = "warn"
linkedlist = "warn" linkedlist = "warn"
@@ -41,13 +42,18 @@ mem_forget = "warn"
must_use_candidate = "warn" must_use_candidate = "warn"
needless_borrow = "warn" needless_borrow = "warn"
needless_continue = "warn" needless_continue = "warn"
needless_pass_by_ref_mut = "warn"
needless_pass_by_value = "warn"
option_option = "warn" option_option = "warn"
redundant_clone = "warn"
ref_option = "warn"
rest_pat_in_fully_bound_structs = "warn" rest_pat_in_fully_bound_structs = "warn"
return_self_not_must_use = "warn" return_self_not_must_use = "warn"
single_match_else = "warn" single_match_else = "warn"
str_to_string = "warn" str_to_string = "warn"
suboptimal_flops = "warn" suboptimal_flops = "warn"
todo = "warn" todo = "warn"
trivially_copy_pass_by_ref = "warn"
uninlined_format_args = "warn" uninlined_format_args = "warn"
unnested_or_patterns = "warn" unnested_or_patterns = "warn"
unused_self = "warn" unused_self = "warn"
+2 -2
View File
@@ -206,7 +206,7 @@ impl IntoResponseParts for CookieJar {
type Error = Infallible; type Error = Infallible;
fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> { fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
set_cookies(self.jar, res.headers_mut()); set_cookies(&self.jar, res.headers_mut());
Ok(res) Ok(res)
} }
} }
@@ -217,7 +217,7 @@ impl IntoResponse for CookieJar {
} }
} }
fn set_cookies(jar: cookie::CookieJar, headers: &mut HeaderMap) { fn set_cookies(jar: &cookie::CookieJar, headers: &mut HeaderMap) {
for cookie in jar.delta() { for cookie in jar.delta() {
if let Ok(header_value) = cookie.encoded().to_string().parse() { if let Ok(header_value) = cookie.encoded().to_string().parse() {
headers.append(SET_COOKIE, header_value); headers.append(SET_COOKIE, header_value);
+1 -1
View File
@@ -274,7 +274,7 @@ impl<K> IntoResponseParts for PrivateCookieJar<K> {
type Error = Infallible; type Error = Infallible;
fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> { fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
set_cookies(self.jar, res.headers_mut()); set_cookies(&self.jar, res.headers_mut());
Ok(res) Ok(res)
} }
} }
+1 -1
View File
@@ -292,7 +292,7 @@ impl<K> IntoResponseParts for SignedCookieJar<K> {
type Error = Infallible; type Error = Infallible;
fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> { fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
set_cookies(self.jar, res.headers_mut()); set_cookies(&self.jar, res.headers_mut());
Ok(res) Ok(res)
} }
} }
+3 -5
View File
@@ -172,7 +172,7 @@ mod tests {
let app = Router::new().route( let app = Router::new().route(
"/", "/",
post(|input: Protobuf<Input>| async move { input.foo.to_owned() }), post(|Protobuf(input): Protobuf<Input>| async move { input.foo }),
); );
let input = Input { let input = Input {
@@ -228,10 +228,8 @@ mod tests {
} }
#[axum::debug_handler] #[axum::debug_handler]
async fn handler(input: Protobuf<Input>) -> Protobuf<Output> { async fn handler(Protobuf(input): Protobuf<Input>) -> Protobuf<Output> {
let output = Output { let output = Output { result: input.foo };
result: input.foo.to_owned(),
};
Protobuf(output) Protobuf(output)
} }
+12 -12
View File
@@ -8,16 +8,16 @@ use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote, quote_spanned}; use quote::{format_ident, quote, quote_spanned};
use syn::{parse::Parse, spanned::Spanned, FnArg, ItemFn, ReturnType, Token, Type}; use syn::{parse::Parse, spanned::Spanned, FnArg, ItemFn, ReturnType, Token, Type};
pub(crate) fn expand(attr: Attrs, item_fn: ItemFn, kind: FunctionKind) -> TokenStream { pub(crate) fn expand(attr: Attrs, item_fn: &ItemFn, kind: FunctionKind) -> TokenStream {
let Attrs { state_ty } = attr; let Attrs { state_ty } = attr;
let mut state_ty = state_ty.map(second); let mut state_ty = state_ty.map(second);
let check_extractor_count = check_extractor_count(&item_fn, kind); let check_extractor_count = check_extractor_count(item_fn, kind);
let check_path_extractor = check_path_extractor(&item_fn, kind); let check_path_extractor = check_path_extractor(item_fn, kind);
let check_output_tuples = check_output_tuples(&item_fn); let check_output_tuples = check_output_tuples(item_fn);
let check_output_impls_into_response = if check_output_tuples.is_empty() { let check_output_impls_into_response = if check_output_tuples.is_empty() {
check_output_impls_into_response(&item_fn) check_output_impls_into_response(item_fn)
} else { } else {
check_output_tuples check_output_tuples
}; };
@@ -28,7 +28,7 @@ pub(crate) fn expand(attr: Attrs, item_fn: ItemFn, kind: FunctionKind) -> TokenS
let mut err = None; let mut err = None;
if state_ty.is_none() { if state_ty.is_none() {
let state_types_from_args = state_types_from_args(&item_fn); let state_types_from_args = state_types_from_args(item_fn);
#[allow(clippy::comparison_chain)] #[allow(clippy::comparison_chain)]
if state_types_from_args.len() == 1 { if state_types_from_args.len() == 1 {
@@ -50,16 +50,16 @@ pub(crate) fn expand(attr: Attrs, item_fn: ItemFn, kind: FunctionKind) -> TokenS
err.unwrap_or_else(|| { err.unwrap_or_else(|| {
let state_ty = state_ty.unwrap_or_else(|| syn::parse_quote!(())); let state_ty = state_ty.unwrap_or_else(|| syn::parse_quote!(()));
let check_future_send = check_future_send(&item_fn, kind); let check_future_send = check_future_send(item_fn, kind);
if let Some(check_input_order) = check_input_order(&item_fn, kind) { if let Some(check_input_order) = check_input_order(item_fn, kind) {
quote! { quote! {
#check_input_order #check_input_order
#check_future_send #check_future_send
} }
} else { } else {
let check_inputs_impls_from_request = let check_inputs_impls_from_request =
check_inputs_impls_from_request(&item_fn, state_ty, kind); check_inputs_impls_from_request(item_fn, &state_ty, kind);
quote! { quote! {
#check_inputs_impls_from_request #check_inputs_impls_from_request
@@ -76,7 +76,7 @@ pub(crate) fn expand(attr: Attrs, item_fn: ItemFn, kind: FunctionKind) -> TokenS
}; };
let middleware_takes_next_as_last_arg = let middleware_takes_next_as_last_arg =
matches!(kind, FunctionKind::Middleware).then(|| next_is_last_input(&item_fn)); matches!(kind, FunctionKind::Middleware).then(|| next_is_last_input(item_fn));
quote! { quote! {
#item_fn #item_fn
@@ -104,7 +104,7 @@ impl fmt::Display for FunctionKind {
} }
impl FunctionKind { impl FunctionKind {
fn name_uppercase_plural(&self) -> &'static str { fn name_uppercase_plural(self) -> &'static str {
match self { match self {
Self::Handler => "Handlers", Self::Handler => "Handlers",
Self::Middleware => "Middleware", Self::Middleware => "Middleware",
@@ -222,7 +222,7 @@ fn is_self_pat_type(typed: &syn::PatType) -> bool {
fn check_inputs_impls_from_request( fn check_inputs_impls_from_request(
item_fn: &ItemFn, item_fn: &ItemFn,
state_ty: Type, state_ty: &Type,
kind: FunctionKind, kind: FunctionKind,
) -> TokenStream { ) -> TokenStream {
let takes_self = item_fn.sig.inputs.first().is_some_and(|arg| match arg { let takes_self = item_fn.sig.inputs.first().is_some_and(|arg| match arg {
+34 -34
View File
@@ -19,7 +19,7 @@ pub(crate) enum Trait {
} }
impl Trait { impl Trait {
fn via_marker_type(&self) -> Option<Type> { fn via_marker_type(self) -> Option<Type> {
match self { match self {
Self::FromRequest => Some(parse_quote!(M)), Self::FromRequest => Some(parse_quote!(M)),
Self::FromRequestParts => None, Self::FromRequestParts => None,
@@ -132,17 +132,17 @@ pub(crate) fn expand(item: syn::Item, tr: Trait) -> syn::Result<TokenStream> {
let trait_impl = match (via.map(second), rejection.map(second)) { let trait_impl = match (via.map(second), rejection.map(second)) {
(Some(via), rejection) => impl_struct_by_extracting_all_at_once( (Some(via), rejection) => impl_struct_by_extracting_all_at_once(
ident, &ident,
fields, fields,
via, &via,
rejection, rejection.as_ref(),
generic_ident, generic_ident.as_ref(),
&state, &state,
tr, tr,
)?, )?,
(None, rejection) => { (None, rejection) => {
error_on_generic_ident(generic_ident, tr)?; error_on_generic_ident(generic_ident, tr)?;
impl_struct_by_extracting_each_field(ident, fields, rejection, &state, tr)? impl_struct_by_extracting_each_field(&ident, &fields, rejection, &state, tr)?
} }
}; };
@@ -206,11 +206,11 @@ pub(crate) fn expand(item: syn::Item, tr: Trait) -> syn::Result<TokenStream> {
match (via.map(second), rejection) { match (via.map(second), rejection) {
(Some(via), rejection) => impl_enum_by_extracting_all_at_once( (Some(via), rejection) => impl_enum_by_extracting_all_at_once(
ident, &ident,
variants, variants,
via, &via,
rejection.map(second), rejection.map(second).as_ref(),
state, &state,
tr, tr,
), ),
(None, Some((rejection_kw, _))) => Err(syn::Error::new_spanned( (None, Some((rejection_kw, _))) => Err(syn::Error::new_spanned(
@@ -328,8 +328,8 @@ fn error_on_generic_ident(generic_ident: Option<Ident>, tr: Trait) -> syn::Resul
} }
fn impl_struct_by_extracting_each_field( fn impl_struct_by_extracting_each_field(
ident: syn::Ident, ident: &syn::Ident,
fields: syn::Fields, fields: &syn::Fields,
rejection: Option<syn::Path>, rejection: Option<syn::Path>,
state: &State, state: &State,
tr: Trait, tr: Trait,
@@ -339,7 +339,7 @@ fn impl_struct_by_extracting_each_field(
::std::unimplemented!() ::std::unimplemented!()
} }
} else { } else {
let extract_fields = extract_fields(&fields, &rejection, tr)?; let extract_fields = extract_fields(fields, rejection.as_ref(), tr)?;
quote! { quote! {
::std::result::Result::Ok(Self { ::std::result::Result::Ok(Self {
#(#extract_fields)* #(#extract_fields)*
@@ -349,7 +349,7 @@ fn impl_struct_by_extracting_each_field(
let rejection_ident = if let Some(rejection) = rejection { let rejection_ident = if let Some(rejection) = rejection {
quote!(#rejection) quote!(#rejection)
} else if has_no_fields(&fields) { } else if has_no_fields(fields) {
quote!(::std::convert::Infallible) quote!(::std::convert::Infallible)
} else { } else {
quote!(::axum::response::Response) quote!(::axum::response::Response)
@@ -411,7 +411,7 @@ fn has_no_fields(fields: &syn::Fields) -> bool {
fn extract_fields( fn extract_fields(
fields: &syn::Fields, fields: &syn::Fields,
rejection: &Option<syn::Path>, rejection: Option<&syn::Path>,
tr: Trait, tr: Trait,
) -> syn::Result<Vec<TokenStream>> { ) -> syn::Result<Vec<TokenStream>> {
fn member(field: &syn::Field, index: usize) -> TokenStream { fn member(field: &syn::Field, index: usize) -> TokenStream {
@@ -426,7 +426,7 @@ fn extract_fields(
} }
} }
fn into_inner(via: &Option<(attr::kw::via, syn::Path)>, ty_span: Span) -> TokenStream { fn into_inner(via: Option<&(attr::kw::via, syn::Path)>, ty_span: Span) -> TokenStream {
if let Some((_, path)) = via { if let Some((_, path)) = via {
let span = path.span(); let span = path.span();
quote_spanned! {span=> quote_spanned! {span=>
@@ -440,7 +440,7 @@ fn extract_fields(
} }
fn into_outer( fn into_outer(
via: &Option<(attr::kw::via, syn::Path)>, via: Option<&(attr::kw::via, syn::Path)>,
ty_span: Span, ty_span: Span,
field_ty: &Type, field_ty: &Type,
) -> TokenStream { ) -> TokenStream {
@@ -472,10 +472,10 @@ fn extract_fields(
let member = member(field, index); let member = member(field, index);
let ty_span = field.ty.span(); let ty_span = field.ty.span();
let into_inner = into_inner(&via, ty_span); let into_inner = into_inner(via.as_ref(), ty_span);
if peel_option(&field.ty).is_some() { if peel_option(&field.ty).is_some() {
let field_ty = into_outer(&via, ty_span, peel_option(&field.ty).unwrap()); let field_ty = into_outer(via.as_ref(), ty_span, peel_option(&field.ty).unwrap());
let tokens = match tr { let tokens = match tr {
Trait::FromRequest => { Trait::FromRequest => {
quote_spanned! {ty_span=> quote_spanned! {ty_span=>
@@ -510,7 +510,7 @@ fn extract_fields(
}; };
Ok(tokens) Ok(tokens)
} else if peel_result_ok(&field.ty).is_some() { } else if peel_result_ok(&field.ty).is_some() {
let field_ty = into_outer(&via,ty_span, peel_result_ok(&field.ty).unwrap()); let field_ty = into_outer(via.as_ref(), ty_span, peel_result_ok(&field.ty).unwrap());
let tokens = match tr { let tokens = match tr {
Trait::FromRequest => { Trait::FromRequest => {
quote_spanned! {ty_span=> quote_spanned! {ty_span=>
@@ -543,7 +543,7 @@ fn extract_fields(
}; };
Ok(tokens) Ok(tokens)
} else { } else {
let field_ty = into_outer(&via,ty_span,&field.ty); let field_ty = into_outer(via.as_ref(), ty_span, &field.ty);
let map_err = if let Some(rejection) = rejection { let map_err = if let Some(rejection) = rejection {
quote! { <#rejection as ::std::convert::From<_>>::from } quote! { <#rejection as ::std::convert::From<_>>::from }
} else { } else {
@@ -593,10 +593,10 @@ fn extract_fields(
let member = member(field, fields.len() - 1); let member = member(field, fields.len() - 1);
let ty_span = field.ty.span(); let ty_span = field.ty.span();
let into_inner = into_inner(&via, ty_span); let into_inner = into_inner(via.as_ref(), ty_span);
let item = if peel_option(&field.ty).is_some() { let item = if peel_option(&field.ty).is_some() {
let field_ty = into_outer(&via, ty_span, peel_option(&field.ty).unwrap()); let field_ty = into_outer(via.as_ref(), ty_span, peel_option(&field.ty).unwrap());
quote_spanned! {ty_span=> quote_spanned! {ty_span=>
#member: { #member: {
<#field_ty as ::axum::extract::FromRequest<_, _>>::from_request(req, state) <#field_ty as ::axum::extract::FromRequest<_, _>>::from_request(req, state)
@@ -606,7 +606,7 @@ fn extract_fields(
}, },
} }
} else if peel_result_ok(&field.ty).is_some() { } else if peel_result_ok(&field.ty).is_some() {
let field_ty = into_outer(&via, ty_span, peel_result_ok(&field.ty).unwrap()); let field_ty = into_outer(via.as_ref(), ty_span, peel_result_ok(&field.ty).unwrap());
quote_spanned! {ty_span=> quote_spanned! {ty_span=>
#member: { #member: {
<#field_ty as ::axum::extract::FromRequest<_, _>>::from_request(req, state) <#field_ty as ::axum::extract::FromRequest<_, _>>::from_request(req, state)
@@ -615,7 +615,7 @@ fn extract_fields(
}, },
} }
} else { } else {
let field_ty = into_outer(&via, ty_span, &field.ty); let field_ty = into_outer(via.as_ref(), ty_span, &field.ty);
let map_err = if let Some(rejection) = rejection { let map_err = if let Some(rejection) = rejection {
quote! { <#rejection as ::std::convert::From<_>>::from } quote! { <#rejection as ::std::convert::From<_>>::from }
} else { } else {
@@ -697,11 +697,11 @@ fn peel_result_ok(ty: &syn::Type) -> Option<&syn::Type> {
} }
fn impl_struct_by_extracting_all_at_once( fn impl_struct_by_extracting_all_at_once(
ident: syn::Ident, ident: &syn::Ident,
fields: syn::Fields, fields: syn::Fields,
via_path: syn::Path, via_path: &syn::Path,
rejection: Option<syn::Path>, rejection: Option<&syn::Path>,
generic_ident: Option<Ident>, generic_ident: Option<&Ident>,
state: &State, state: &State,
tr: Trait, tr: Trait,
) -> syn::Result<TokenStream> { ) -> syn::Result<TokenStream> {
@@ -750,7 +750,7 @@ fn impl_struct_by_extracting_all_at_once(
// - `State`, not other extractors // - `State`, not other extractors
// //
// honestly not sure why but the tests all pass // honestly not sure why but the tests all pass
let via_marker_type = if path_ident_is_state(&via_path) { let via_marker_type = if path_ident_is_state(via_path) {
tr.via_marker_type() tr.via_marker_type()
} else { } else {
None None
@@ -868,11 +868,11 @@ fn impl_struct_by_extracting_all_at_once(
} }
fn impl_enum_by_extracting_all_at_once( fn impl_enum_by_extracting_all_at_once(
ident: syn::Ident, ident: &syn::Ident,
variants: Punctuated<syn::Variant, Token![,]>, variants: Punctuated<syn::Variant, Token![,]>,
path: syn::Path, path: &syn::Path,
rejection: Option<syn::Path>, rejection: Option<&syn::Path>,
state: State, state: &State,
tr: Trait, tr: Trait,
) -> syn::Result<TokenStream> { ) -> syn::Result<TokenStream> {
for variant in variants { for variant in variants {
+3 -3
View File
@@ -579,7 +579,7 @@ pub fn debug_handler(_attr: TokenStream, input: TokenStream) -> TokenStream {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
return expand_attr_with(_attr, input, |attrs, item_fn| { return expand_attr_with(_attr, input, |attrs, item_fn| {
debug_handler::expand(attrs, item_fn, FunctionKind::Handler) debug_handler::expand(attrs, &item_fn, FunctionKind::Handler)
}); });
} }
@@ -635,7 +635,7 @@ pub fn debug_middleware(_attr: TokenStream, input: TokenStream) -> TokenStream {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
return expand_attr_with(_attr, input, |attrs, item_fn| { return expand_attr_with(_attr, input, |attrs, item_fn| {
debug_handler::expand(attrs, item_fn, FunctionKind::Middleware) debug_handler::expand(attrs, &item_fn, FunctionKind::Middleware)
}); });
} }
@@ -662,7 +662,7 @@ pub fn __private_axum_test(_attr: TokenStream, input: TokenStream) -> TokenStrea
/// [`axum_extra::routing::TypedPath`]: https://docs.rs/axum-extra/latest/axum_extra/routing/trait.TypedPath.html /// [`axum_extra::routing::TypedPath`]: https://docs.rs/axum-extra/latest/axum_extra/routing/trait.TypedPath.html
#[proc_macro_derive(TypedPath, attributes(typed_path))] #[proc_macro_derive(TypedPath, attributes(typed_path))]
pub fn derive_typed_path(input: TokenStream) -> TokenStream { pub fn derive_typed_path(input: TokenStream) -> TokenStream {
expand_with(input, typed_path::expand) expand_with(input, |item_struct| typed_path::expand(&item_struct))
} }
/// Derive an implementation of [`FromRef`] for each field in a struct. /// Derive an implementation of [`FromRef`] for each field in a struct.
+23 -18
View File
@@ -4,14 +4,14 @@ use syn::{parse::Parse, ItemStruct, LitStr, Token};
use crate::attr_parsing::{combine_attribute, parse_parenthesized_attribute, second, Combine}; use crate::attr_parsing::{combine_attribute, parse_parenthesized_attribute, second, Combine};
pub(crate) fn expand(item_struct: ItemStruct) -> syn::Result<TokenStream> { pub(crate) fn expand(item_struct: &ItemStruct) -> syn::Result<TokenStream> {
let ItemStruct { let ItemStruct {
attrs, attrs,
ident, ident,
generics, generics,
fields, fields,
.. ..
} = &item_struct; } = item_struct;
if !generics.params.is_empty() || generics.where_clause.is_some() { if !generics.params.is_empty() || generics.where_clause.is_some() {
return Err(syn::Error::new_spanned( return Err(syn::Error::new_spanned(
@@ -34,13 +34,18 @@ pub(crate) fn expand(item_struct: ItemStruct) -> syn::Result<TokenStream> {
match fields { match fields {
syn::Fields::Named(_) => { syn::Fields::Named(_) => {
let segments = parse_path(&path)?; let segments = parse_path(&path)?;
Ok(expand_named_fields(ident, path, &segments, rejection)) Ok(expand_named_fields(
ident,
&path,
&segments,
rejection.as_ref(),
))
} }
syn::Fields::Unnamed(fields) => { syn::Fields::Unnamed(fields) => {
let segments = parse_path(&path)?; let segments = parse_path(&path)?;
expand_unnamed_fields(fields, ident, path, &segments, rejection) expand_unnamed_fields(fields, ident, &path, &segments, rejection.as_ref())
} }
syn::Fields::Unit => expand_unit_fields(ident, path, rejection), syn::Fields::Unit => expand_unit_fields(ident, &path, rejection.as_ref()),
} }
} }
@@ -95,9 +100,9 @@ impl Combine for Attrs {
fn expand_named_fields( fn expand_named_fields(
ident: &syn::Ident, ident: &syn::Ident,
path: LitStr, path: &LitStr,
segments: &[Segment], segments: &[Segment],
rejection: Option<syn::Path>, rejection: Option<&syn::Path>,
) -> TokenStream { ) -> TokenStream {
let format_str = format_str_from_path(segments); let format_str = format_str_from_path(segments);
let captures = captures_from_path(segments); let captures = captures_from_path(segments);
@@ -129,8 +134,8 @@ fn expand_named_fields(
} }
}; };
let rejection_assoc_type = rejection_assoc_type(&rejection); let rejection_assoc_type = rejection_assoc_type(rejection);
let map_err_rejection = map_err_rejection(&rejection); let map_err_rejection = map_err_rejection(rejection);
let from_request_impl = quote! { let from_request_impl = quote! {
#[automatically_derived] #[automatically_derived]
@@ -162,9 +167,9 @@ fn expand_named_fields(
fn expand_unnamed_fields( fn expand_unnamed_fields(
fields: &syn::FieldsUnnamed, fields: &syn::FieldsUnnamed,
ident: &syn::Ident, ident: &syn::Ident,
path: LitStr, path: &LitStr,
segments: &[Segment], segments: &[Segment],
rejection: Option<syn::Path>, rejection: Option<&syn::Path>,
) -> syn::Result<TokenStream> { ) -> syn::Result<TokenStream> {
let num_captures = segments let num_captures = segments
.iter() .iter()
@@ -233,8 +238,8 @@ fn expand_unnamed_fields(
} }
}; };
let rejection_assoc_type = rejection_assoc_type(&rejection); let rejection_assoc_type = rejection_assoc_type(rejection);
let map_err_rejection = map_err_rejection(&rejection); let map_err_rejection = map_err_rejection(rejection);
let from_request_impl = quote! { let from_request_impl = quote! {
#[automatically_derived] #[automatically_derived]
@@ -273,10 +278,10 @@ fn simple_pluralize(count: usize, word: &str) -> String {
fn expand_unit_fields( fn expand_unit_fields(
ident: &syn::Ident, ident: &syn::Ident,
path: LitStr, path: &LitStr,
rejection: Option<syn::Path>, rejection: Option<&syn::Path>,
) -> syn::Result<TokenStream> { ) -> syn::Result<TokenStream> {
for segment in parse_path(&path)? { for segment in parse_path(path)? {
match segment { match segment {
Segment::Capture(_, span) => { Segment::Capture(_, span) => {
return Err(syn::Error::new( return Err(syn::Error::new(
@@ -409,14 +414,14 @@ fn path_rejection() -> TokenStream {
} }
} }
fn rejection_assoc_type(rejection: &Option<syn::Path>) -> TokenStream { fn rejection_assoc_type(rejection: Option<&syn::Path>) -> TokenStream {
match rejection { match rejection {
Some(rejection) => quote! { #rejection }, Some(rejection) => quote! { #rejection },
None => path_rejection(), None => path_rejection(),
} }
} }
fn map_err_rejection(rejection: &Option<syn::Path>) -> TokenStream { fn map_err_rejection(rejection: Option<&syn::Path>) -> TokenStream {
rejection rejection
.as_ref() .as_ref()
.map(|rejection| { .map(|rejection| {
+7 -7
View File
@@ -423,11 +423,11 @@ where
return Err(MethodNotGet.into()); return Err(MethodNotGet.into());
} }
if !header_contains(&parts.headers, header::CONNECTION, "upgrade") { if !header_contains(&parts.headers, &header::CONNECTION, "upgrade") {
return Err(InvalidConnectionHeader.into()); return Err(InvalidConnectionHeader.into());
} }
if !header_eq(&parts.headers, header::UPGRADE, "websocket") { if !header_eq(&parts.headers, &header::UPGRADE, "websocket") {
return Err(InvalidUpgradeHeader.into()); return Err(InvalidUpgradeHeader.into());
} }
@@ -457,7 +457,7 @@ where
None None
}; };
if !header_eq(&parts.headers, header::SEC_WEBSOCKET_VERSION, "13") { if !header_eq(&parts.headers, &header::SEC_WEBSOCKET_VERSION, "13") {
return Err(InvalidWebSocketVersionHeader.into()); return Err(InvalidWebSocketVersionHeader.into());
} }
@@ -479,16 +479,16 @@ where
} }
} }
fn header_eq(headers: &HeaderMap, key: HeaderName, value: &'static str) -> bool { fn header_eq(headers: &HeaderMap, key: &HeaderName, value: &'static str) -> bool {
if let Some(header) = headers.get(&key) { if let Some(header) = headers.get(key) {
header.as_bytes().eq_ignore_ascii_case(value.as_bytes()) header.as_bytes().eq_ignore_ascii_case(value.as_bytes())
} else { } else {
false false
} }
} }
fn header_contains(headers: &HeaderMap, key: HeaderName, value: &'static str) -> bool { fn header_contains(headers: &HeaderMap, key: &HeaderName, value: &'static str) -> bool {
let Some(header) = headers.get(&key) else { let Some(header) = headers.get(key) else {
return false; return false;
}; };
+2 -2
View File
@@ -425,7 +425,7 @@ impl EventFlags {
const HAS_RETRY: Self = Self::from_bits(0b0100); const HAS_RETRY: Self = Self::from_bits(0b0100);
const HAS_ID: Self = Self::from_bits(0b1000); const HAS_ID: Self = Self::from_bits(0b1000);
const fn bits(&self) -> u8 { const fn bits(self) -> u8 {
self.0 self.0
} }
@@ -433,7 +433,7 @@ impl EventFlags {
Self(bits) Self(bits)
} }
const fn contains(&self, other: Self) -> bool { const fn contains(self, other: Self) -> bool {
self.bits() & other.bits() == other.bits() self.bits() & other.bits() == other.bits()
} }
+2 -2
View File
@@ -44,7 +44,7 @@ impl MethodFilter {
/// Match `TRACE` requests. /// Match `TRACE` requests.
pub const TRACE: Self = Self::from_bits(0b1_0000_0000); pub const TRACE: Self = Self::from_bits(0b1_0000_0000);
const fn bits(&self) -> u16 { const fn bits(self) -> u16 {
let bits = self; let bits = self;
bits.0 bits.0
} }
@@ -53,7 +53,7 @@ impl MethodFilter {
Self(bits) Self(bits)
} }
pub(crate) const fn contains(&self, other: Self) -> bool { pub(crate) const fn contains(self, other: Self) -> bool {
self.bits() & other.bits() == other.bits() self.bits() & other.bits() == other.bits()
} }
+12 -12
View File
@@ -635,7 +635,7 @@ where
{ {
self.on_endpoint( self.on_endpoint(
filter, filter,
MethodEndpoint::BoxedHandler(BoxedIntoRoute::from_handler(handler)), &MethodEndpoint::BoxedHandler(BoxedIntoRoute::from_handler(handler)),
) )
} }
@@ -815,11 +815,11 @@ where
T::Response: IntoResponse + 'static, T::Response: IntoResponse + 'static,
T::Future: Send + 'static, T::Future: Send + 'static,
{ {
self.on_endpoint(filter, MethodEndpoint::Route(Route::new(svc))) self.on_endpoint(filter, &MethodEndpoint::Route(Route::new(svc)))
} }
#[track_caller] #[track_caller]
fn on_endpoint(mut self, filter: MethodFilter, endpoint: MethodEndpoint<S, E>) -> Self { fn on_endpoint(mut self, filter: MethodFilter, endpoint: &MethodEndpoint<S, E>) -> Self {
// written as a separate function to generate less IR // written as a separate function to generate less IR
#[track_caller] #[track_caller]
fn set_endpoint<S, E>( fn set_endpoint<S, E>(
@@ -851,7 +851,7 @@ where
set_endpoint( set_endpoint(
"GET", "GET",
&mut self.get, &mut self.get,
&endpoint, endpoint,
filter, filter,
MethodFilter::GET, MethodFilter::GET,
&mut self.allow_header, &mut self.allow_header,
@@ -861,7 +861,7 @@ where
set_endpoint( set_endpoint(
"HEAD", "HEAD",
&mut self.head, &mut self.head,
&endpoint, endpoint,
filter, filter,
MethodFilter::HEAD, MethodFilter::HEAD,
&mut self.allow_header, &mut self.allow_header,
@@ -871,7 +871,7 @@ where
set_endpoint( set_endpoint(
"TRACE", "TRACE",
&mut self.trace, &mut self.trace,
&endpoint, endpoint,
filter, filter,
MethodFilter::TRACE, MethodFilter::TRACE,
&mut self.allow_header, &mut self.allow_header,
@@ -881,7 +881,7 @@ where
set_endpoint( set_endpoint(
"PUT", "PUT",
&mut self.put, &mut self.put,
&endpoint, endpoint,
filter, filter,
MethodFilter::PUT, MethodFilter::PUT,
&mut self.allow_header, &mut self.allow_header,
@@ -891,7 +891,7 @@ where
set_endpoint( set_endpoint(
"POST", "POST",
&mut self.post, &mut self.post,
&endpoint, endpoint,
filter, filter,
MethodFilter::POST, MethodFilter::POST,
&mut self.allow_header, &mut self.allow_header,
@@ -901,7 +901,7 @@ where
set_endpoint( set_endpoint(
"PATCH", "PATCH",
&mut self.patch, &mut self.patch,
&endpoint, endpoint,
filter, filter,
MethodFilter::PATCH, MethodFilter::PATCH,
&mut self.allow_header, &mut self.allow_header,
@@ -911,7 +911,7 @@ where
set_endpoint( set_endpoint(
"OPTIONS", "OPTIONS",
&mut self.options, &mut self.options,
&endpoint, endpoint,
filter, filter,
MethodFilter::OPTIONS, MethodFilter::OPTIONS,
&mut self.allow_header, &mut self.allow_header,
@@ -921,7 +921,7 @@ where
set_endpoint( set_endpoint(
"DELETE", "DELETE",
&mut self.delete, &mut self.delete,
&endpoint, endpoint,
filter, filter,
MethodFilter::DELETE, MethodFilter::DELETE,
&mut self.allow_header, &mut self.allow_header,
@@ -931,7 +931,7 @@ where
set_endpoint( set_endpoint(
"CONNECT", "CONNECT",
&mut self.options, &mut self.options,
&endpoint, endpoint,
filter, filter,
MethodFilter::CONNECT, MethodFilter::CONNECT,
&mut self.allow_header, &mut self.allow_header,
+3 -2
View File
@@ -347,6 +347,7 @@ where
} }
#[doc = include_str!("../docs/routing/method_not_allowed_fallback.md")] #[doc = include_str!("../docs/routing/method_not_allowed_fallback.md")]
#[allow(clippy::needless_pass_by_value)]
pub fn method_not_allowed_fallback<H, T>(self, handler: H) -> Self pub fn method_not_allowed_fallback<H, T>(self, handler: H) -> Self
where where
H: Handler<T, S>, H: Handler<T, S>,
@@ -354,7 +355,7 @@ where
{ {
tap_inner!(self, mut this => { tap_inner!(self, mut this => {
this.path_router this.path_router
.method_not_allowed_fallback(handler.clone()); .method_not_allowed_fallback(&handler);
}) })
} }
@@ -734,7 +735,7 @@ where
match self { match self {
Self::Default(route) | Self::Service(route) => route.oneshot_inner_owned(req), Self::Default(route) | Self::Service(route) => route.oneshot_inner_owned(req),
Self::BoxedHandler(handler) => { Self::BoxedHandler(handler) => {
let route = handler.clone().into_route(state); let route = handler.into_route(state);
route.oneshot_inner_owned(req) route.oneshot_inner_owned(req)
} }
} }
+2 -2
View File
@@ -97,7 +97,7 @@ where
Ok(()) Ok(())
} }
pub(super) fn method_not_allowed_fallback<H, T>(&mut self, handler: H) pub(super) fn method_not_allowed_fallback<H, T>(&mut self, handler: &H)
where where
H: Handler<T, S>, H: Handler<T, S>,
T: 'static, T: 'static,
@@ -362,7 +362,7 @@ where
&mut parts.extensions, &mut parts.extensions,
); );
url_params::insert_url_params(&mut parts.extensions, match_.params); url_params::insert_url_params(&mut parts.extensions, &match_.params);
let endpoint = self let endpoint = self
.routes .routes
+3 -3
View File
@@ -46,7 +46,7 @@ impl<E> Route<E> {
self.oneshot_inner_owned(req).not_top_level() self.oneshot_inner_owned(req).not_top_level()
} }
pub(crate) fn oneshot_inner(&mut self, req: Request) -> RouteFuture<E> { pub(crate) fn oneshot_inner(&self, req: Request) -> RouteFuture<E> {
let method = req.method().clone(); let method = req.method().clone();
RouteFuture::new(method, self.0.clone().oneshot(req)) RouteFuture::new(method, self.0.clone().oneshot(req))
} }
@@ -164,7 +164,7 @@ impl<E> Future for RouteFuture<E> {
set_allow_header(res.headers_mut(), this.allow_header); set_allow_header(res.headers_mut(), this.allow_header);
// make sure to set content-length before removing the body // make sure to set content-length before removing the body
set_content_length(res.size_hint(), res.headers_mut()); set_content_length(&res.size_hint(), res.headers_mut());
if *this.method == Method::HEAD { if *this.method == Method::HEAD {
*res.body_mut() = Body::empty(); *res.body_mut() = Body::empty();
@@ -187,7 +187,7 @@ fn set_allow_header(headers: &mut HeaderMap, allow_header: &mut Option<Bytes>) {
} }
} }
fn set_content_length(size_hint: http_body::SizeHint, headers: &mut HeaderMap) { fn set_content_length(size_hint: &http_body::SizeHint, headers: &mut HeaderMap) {
if headers.contains_key(CONTENT_LENGTH) { if headers.contains_key(CONTENT_LENGTH) {
return; return;
} }
+1 -1
View File
@@ -9,7 +9,7 @@ pub(crate) enum UrlParams {
InvalidUtf8InPathParam { key: Arc<str> }, InvalidUtf8InPathParam { key: Arc<str> },
} }
pub(super) fn insert_url_params(extensions: &mut Extensions, params: Params<'_, '_>) { pub(super) fn insert_url_params(extensions: &mut Extensions, params: &Params<'_, '_>) {
let current_params = extensions.get_mut(); let current_params = extensions.get_mut();
if let Some(UrlParams::InvalidUtf8InPathParam { .. }) = current_params { if let Some(UrlParams::InvalidUtf8InPathParam { .. }) = current_params {