From 7f1f131d44a9571f30727cd2cfdaf71ffb269d8b Mon Sep 17 00:00:00 2001 From: David McGillicuddy Date: Thu, 6 Jan 2022 19:11:40 +0000 Subject: [PATCH] replace use of str::split_once, str::rsplit_once, and concat! inside doc comments, to enable 1.51 compat --- actix-http/src/header/shared/quality_item.rs | 11 +++++++++-- src/error/internal.rs | 11 ++++++++++- src/guard.rs | 17 ++++++++++++++--- src/http/header/range.rs | 12 ++++++++++-- src/web.rs | 20 ++++++++++++++++---- 5 files changed, 59 insertions(+), 12 deletions(-) diff --git a/actix-http/src/header/shared/quality_item.rs b/actix-http/src/header/shared/quality_item.rs index 71a3bdd53..f35dd864d 100644 --- a/actix-http/src/header/shared/quality_item.rs +++ b/actix-http/src/header/shared/quality_item.rs @@ -99,8 +99,7 @@ impl str::FromStr for QualityItem { let mut raw_item = q_item_str; let mut quality = Quality::MAX; - let parts = q_item_str - .rsplit_once(';') + let parts = str_rsplit_once(q_item_str, ';') .map(|(item, q_attr)| (item.trim(), q_attr.trim())); if let Some((val, q_attr)) = parts { @@ -141,6 +140,14 @@ impl str::FromStr for QualityItem { } } +// `str::rsplit_once` is stabilized in 1.52.0 +fn str_rsplit_once(s: &str, delimiter: char) -> Option<(&str, &str)> { + let mut rsplit = s.rsplitn(2, delimiter); + let suffix = rsplit.next()?; + let prefix = rsplit.next()?; + Some((prefix, suffix)) +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/error/internal.rs b/src/error/internal.rs index 1c6e343e3..7ff52567e 100644 --- a/src/error/internal.rs +++ b/src/error/internal.rs @@ -117,8 +117,17 @@ where } macro_rules! error_helper { + // Workaround for 1.52.0 compat. It's not great but any use of `concat!` must be done prior + // to insertion in a doc comment. ($name:ident, $status:ident) => { - #[doc = concat!("Helper function that wraps any error and generates a `", stringify!($status), "` response.")] + error_helper!( + $name, + $status, + concat!("Helper function that wraps any error and generates a `", stringify!($status), "` response.") + ); + }; + ($name:ident, $status:ident, $doc:expr) => { + #[doc = $doc] #[allow(non_snake_case)] pub fn $name(err: T) -> Error where diff --git a/src/guard.rs b/src/guard.rs index f4200a382..d4117bfab 100644 --- a/src/guard.rs +++ b/src/guard.rs @@ -289,16 +289,27 @@ impl Guard for MethodGuard { } macro_rules! method_guard { + // Workaround for 1.52.0 compat. It's not great but any use of `concat!` must be done prior + // to insertion in a doc comment. ($method_fn:ident, $method_const:ident) => { - #[doc = concat!("Creates a guard that matches the `", stringify!($method_const), "` request method.")] + method_guard!( + $method_fn, + $method_const, + concat!("Creates a guard that matches the `", stringify!($method_const), "` request method."), + concat!("The route in this example will only respond to `", stringify!($method_const), "` requests."), + concat!(" .guard(guard::", stringify!($method_fn), "())") + ); + }; + ($method_fn:ident, $method_const:ident, $doc1:expr, $doc2:expr, $doc3:expr) => { + #[doc = $doc1] /// /// # Examples - #[doc = concat!("The route in this example will only respond to `", stringify!($method_const), "` requests.")] + #[doc = $doc2] /// ``` /// use actix_web::{guard, web, HttpResponse}; /// /// web::route() - #[doc = concat!(" .guard(guard::", stringify!($method_fn), "())")] + #[doc = $doc3] /// .to(|| HttpResponse::Ok()); /// ``` #[allow(non_snake_case)] diff --git a/src/http/header/range.rs b/src/http/header/range.rs index 68028f53a..5c249abec 100644 --- a/src/http/header/range.rs +++ b/src/http/header/range.rs @@ -217,7 +217,7 @@ impl FromStr for Range { type Err = ParseError; fn from_str(s: &str) -> Result { - let (unit, val) = s.split_once('=').ok_or(ParseError::Header)?; + let (unit, val) = str_split_once(s, '=').ok_or(ParseError::Header)?; match (unit, val) { ("bytes", ranges) => { @@ -242,7 +242,7 @@ impl FromStr for ByteRangeSpec { type Err = ParseError; fn from_str(s: &str) -> Result { - let (start, end) = s.split_once('-').ok_or(ParseError::Header)?; + let (start, end) = str_split_once(s, '-').ok_or(ParseError::Header)?; match (start, end) { ("", end) => end @@ -295,6 +295,14 @@ fn from_comma_delimited(s: &str) -> Vec { .collect() } +// `str::split_once` is stabilized in 1.52.0 +fn str_split_once(str: &str, delimiter: char) -> Option<(&str, &str)> { + let mut splitn = str.splitn(2, delimiter); + let prefix = splitn.next()?; + let suffix = splitn.next()?; + Some((prefix, suffix)) +} + #[cfg(test)] mod tests { use actix_http::{test::TestRequest, Request}; diff --git a/src/web.rs b/src/web.rs index 4858600af..b61a4a599 100644 --- a/src/web.rs +++ b/src/web.rs @@ -83,25 +83,37 @@ pub fn route() -> Route { Route::new() } + macro_rules! method_route { + // Workaround for 1.52.0 compat. It's not great but any use of `concat!` must be done prior + // to insertion in a doc comment. ($method_fn:ident, $method_const:ident) => { - #[doc = concat!(" Creates a new route with `", stringify!($method_const), "` method guard.")] + method_route!( + $method_fn, + $method_const, + concat!(" Creates a new route with `", stringify!($method_const), "` method guard."), + concat!(" In this example, one `", stringify!($method_const), " /{project_id}` route is set up:"), + concat!(" .route(web::", stringify!($method_fn), "().to(|| HttpResponse::Ok()))") + ); + }; + ($method_fn:ident, $method_const:ident, $doc1:expr, $doc2:expr, $doc3:expr) => { + #[doc = $doc1] /// /// # Examples - #[doc = concat!(" In this example, one `", stringify!($method_const), " /{project_id}` route is set up:")] + #[doc = $doc2] /// ``` /// use actix_web::{web, App, HttpResponse}; /// /// let app = App::new().service( /// web::resource("/{project_id}") - #[doc = concat!(" .route(web::", stringify!($method_fn), "().to(|| HttpResponse::Ok()))")] + #[doc = $doc3] /// /// ); /// ``` pub fn $method_fn() -> Route { method(Method::$method_const) } - }; + } } method_route!(get, GET);