From 4570487c76882c0669cd25f3daf05d7df03b879a Mon Sep 17 00:00:00 2001 From: Kriskras99 Date: Wed, 2 Jul 2025 18:31:11 +0200 Subject: [PATCH 1/2] feat: Raise MSRV to 1.63 --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 97205378..38e8aa45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,9 +19,9 @@ A set of types for representing HTTP requests and responses. """ keywords = ["http"] categories = ["web-programming"] -edition = "2018" +edition = "2021" # When updating this value, don't forget to also adjust the GitHub Actions config. -rust-version = "1.49.0" +rust-version = "1.63.0" [workspace] members = [ From 51167ce7159c1ee12316f66626fcb1b01370167b Mon Sep 17 00:00:00 2001 From: Kriskras99 Date: Wed, 2 Jul 2025 19:14:06 +0200 Subject: [PATCH 2/2] chore: Fix Clippy lints up to 1.88 (compatible with 1.63) --- src/byte_str.rs | 3 +-- src/header/map.rs | 25 ++++++++++++------------- src/header/name.rs | 7 +++---- src/header/value.rs | 18 +++++++++--------- src/method.rs | 4 ++-- src/request.rs | 4 +--- src/response.rs | 4 +--- src/uri/authority.rs | 12 ++++++------ src/uri/builder.rs | 8 ++++---- src/uri/mod.rs | 15 ++++++--------- src/uri/path.rs | 14 +++++++------- src/uri/scheme.rs | 2 +- tests/header_map.rs | 8 +++----- tests/header_map_fuzz.rs | 13 ++++++------- 14 files changed, 62 insertions(+), 75 deletions(-) diff --git a/src/byte_str.rs b/src/byte_str.rs index e69bf0a8..21c89929 100644 --- a/src/byte_str.rs +++ b/src/byte_str.rs @@ -37,8 +37,7 @@ impl ByteStr { match str::from_utf8(&bytes) { Ok(_) => (), Err(err) => panic!( - "ByteStr::from_utf8_unchecked() with invalid bytes; error = {}, bytes = {:?}", - err, bytes + "ByteStr::from_utf8_unchecked() with invalid bytes; error = {err}, bytes = {bytes:?}" ), } } diff --git a/src/header/map.rs b/src/header/map.rs index 4fa7b85a..b79d1506 100644 --- a/src/header/map.rs +++ b/src/header/map.rs @@ -1460,7 +1460,7 @@ impl HeaderMap { #[inline] fn find(&self, key: &K) -> Option<(usize, usize)> where - K: Hash + Into + ?Sized, + K: Hash + Into, HeaderName: PartialEq, { if self.entries.is_empty() { @@ -3588,10 +3588,9 @@ fn usable_capacity(cap: usize) -> usize { fn to_raw_capacity(n: usize) -> usize { match n.checked_add(n / 3) { Some(n) => n, - None => panic!( - "requested capacity {} too large: overflow while converting to raw capacity", - n - ), + None => { + panic!("requested capacity {n} too large: overflow while converting to raw capacity") + } } } @@ -3690,7 +3689,7 @@ mod into_header_name { impl IntoHeaderName for HeaderName {} - impl<'a> Sealed for &'a HeaderName { + impl Sealed for &HeaderName { #[inline] fn try_insert( self, @@ -3710,7 +3709,7 @@ mod into_header_name { } } - impl<'a> IntoHeaderName for &'a HeaderName {} + impl IntoHeaderName for &HeaderName {} impl Sealed for &'static str { #[inline] @@ -3800,7 +3799,7 @@ mod as_header_name { impl AsHeaderName for HeaderName {} - impl<'a> Sealed for &'a HeaderName { + impl Sealed for &HeaderName { #[inline] fn try_entry(self, map: &mut HeaderMap) -> Result, TryEntryError> { Ok(map.try_entry2(self)?) @@ -3816,9 +3815,9 @@ mod as_header_name { } } - impl<'a> AsHeaderName for &'a HeaderName {} + impl AsHeaderName for &HeaderName {} - impl<'a> Sealed for &'a str { + impl Sealed for &str { #[inline] fn try_entry(self, map: &mut HeaderMap) -> Result, TryEntryError> { Ok(HdrName::from_bytes(self.as_bytes(), move |hdr| { @@ -3836,7 +3835,7 @@ mod as_header_name { } } - impl<'a> AsHeaderName for &'a str {} + impl AsHeaderName for &str {} impl Sealed for String { #[inline] @@ -3856,7 +3855,7 @@ mod as_header_name { impl AsHeaderName for String {} - impl<'a> Sealed for &'a String { + impl Sealed for &String { #[inline] fn try_entry(self, map: &mut HeaderMap) -> Result, TryEntryError> { self.as_str().try_entry(map) @@ -3872,7 +3871,7 @@ mod as_header_name { } } - impl<'a> AsHeaderName for &'a String {} + impl AsHeaderName for &String {} } #[test] diff --git a/src/header/name.rs b/src/header/name.rs index 122b96f9..3021190b 100644 --- a/src/header/name.rs +++ b/src/header/name.rs @@ -1439,7 +1439,7 @@ impl<'a> PartialEq<&'a HeaderName> for HeaderName { } } -impl<'a> PartialEq for &'a HeaderName { +impl PartialEq for &HeaderName { #[inline] fn eq(&self, other: &HeaderName) -> bool { *other == *self @@ -1493,7 +1493,7 @@ impl<'a> PartialEq<&'a str> for HeaderName { } } -impl<'a> PartialEq for &'a str { +impl PartialEq for &str { /// Performs a case-insensitive comparison of the string against the header /// name #[inline] @@ -1688,8 +1688,7 @@ mod tests { let hdr = vec![1u8; i]; assert!( HeaderName::from_bytes(&hdr).is_err(), - "{} invalid header chars did not fail", - i + "{i} invalid header chars did not fail" ); } } diff --git a/src/header/value.rs b/src/header/value.rs index 99d1e155..dc60c35a 100644 --- a/src/header/value.rs +++ b/src/header/value.rs @@ -398,7 +398,7 @@ impl fmt::Debug for HeaderValue { if b == b'"' { f.write_str("\\\"")?; } else { - write!(f, "\\x{:x}", b)?; + write!(f, "\\x{b:x}")?; } from = i + 1; } @@ -439,7 +439,7 @@ macro_rules! from_integers { let val = HeaderValue::from(n); assert_eq!(val, &n.to_string()); - let n = ::std::$t::MAX; + let n = $t::MAX; let val = HeaderValue::from(n); assert_eq!(val, &n.to_string()); } @@ -571,7 +571,7 @@ mod try_from_header_name_tests { #[test] fn it_converts_using_try_from() { assert_eq!( - HeaderValue::try_from(name::UPGRADE).unwrap(), + HeaderValue::from(name::UPGRADE), HeaderValue::from_bytes(b"upgrade").unwrap() ); } @@ -725,14 +725,14 @@ impl PartialOrd for String { } } -impl<'a> PartialEq for &'a HeaderValue { +impl PartialEq for &HeaderValue { #[inline] fn eq(&self, other: &HeaderValue) -> bool { **self == *other } } -impl<'a> PartialOrd for &'a HeaderValue { +impl PartialOrd for &HeaderValue { #[inline] fn partial_cmp(&self, other: &HeaderValue) -> Option { (**self).partial_cmp(other) @@ -759,14 +759,14 @@ where } } -impl<'a> PartialEq for &'a str { +impl PartialEq for &str { #[inline] fn eq(&self, other: &HeaderValue) -> bool { *other == *self } } -impl<'a> PartialOrd for &'a str { +impl PartialOrd for &str { #[inline] fn partial_cmp(&self, other: &HeaderValue) -> Option { self.as_bytes().partial_cmp(other.as_bytes()) @@ -788,11 +788,11 @@ fn test_debug() { for &(value, expected) in cases { let val = HeaderValue::from_bytes(value.as_bytes()).unwrap(); - let actual = format!("{:?}", val); + let actual = format!("{val:?}"); assert_eq!(expected, actual); } let mut sensitive = HeaderValue::from_static("password"); sensitive.set_sensitive(true); - assert_eq!("Sensitive", format!("{:?}", sensitive)); + assert_eq!("Sensitive", format!("{sensitive:?}")); } diff --git a/src/method.rs b/src/method.rs index 7b4584ab..2567b739 100644 --- a/src/method.rs +++ b/src/method.rs @@ -194,7 +194,7 @@ impl<'a> PartialEq<&'a Method> for Method { } } -impl<'a> PartialEq for &'a Method { +impl PartialEq for &Method { #[inline] fn eq(&self, other: &Method) -> bool { *self == other @@ -222,7 +222,7 @@ impl<'a> PartialEq<&'a str> for Method { } } -impl<'a> PartialEq for &'a str { +impl PartialEq for &str { #[inline] fn eq(&self, other: &Method) -> bool { *self == other.as_ref() diff --git a/src/request.rs b/src/request.rs index 324b676c..b5029301 100644 --- a/src/request.rs +++ b/src/request.rs @@ -165,6 +165,7 @@ pub struct Request { /// The HTTP request head consists of a method, uri, version, and a set of /// header fields. #[derive(Clone)] +#[non_exhaustive] pub struct Parts { /// The request's method pub method: Method, @@ -180,8 +181,6 @@ pub struct Parts { /// The request's extensions pub extensions: Extensions, - - _priv: (), } /// An HTTP request builder @@ -715,7 +714,6 @@ impl Parts { version: Version::default(), headers: HeaderMap::default(), extensions: Extensions::default(), - _priv: (), } } } diff --git a/src/response.rs b/src/response.rs index ab9e49bc..765d8dfc 100644 --- a/src/response.rs +++ b/src/response.rs @@ -187,6 +187,7 @@ pub struct Response { /// The HTTP response head consists of a status, version, and a set of /// header fields. #[derive(Clone)] +#[non_exhaustive] pub struct Parts { /// The response's status pub status: StatusCode, @@ -199,8 +200,6 @@ pub struct Parts { /// The response's extensions pub extensions: Extensions, - - _priv: (), } /// An HTTP response builder @@ -507,7 +506,6 @@ impl Parts { version: Version::default(), headers: HeaderMap::default(), extensions: Extensions::default(), - _priv: (), } } } diff --git a/src/uri/authority.rs b/src/uri/authority.rs index 07aa6795..f70bc66f 100644 --- a/src/uri/authority.rs +++ b/src/uri/authority.rs @@ -302,7 +302,7 @@ impl PartialEq for str { } } -impl<'a> PartialEq for &'a str { +impl PartialEq for &str { fn eq(&self, other: &Authority) -> bool { self.eq_ignore_ascii_case(other.as_str()) } @@ -360,7 +360,7 @@ impl PartialOrd for str { } } -impl<'a> PartialOrd for &'a str { +impl PartialOrd for &str { fn partial_cmp(&self, other: &Authority) -> Option { let left = self.as_bytes().iter().map(|b| b.to_ascii_lowercase()); let right = other.data.as_bytes().iter().map(|b| b.to_ascii_lowercase()); @@ -619,10 +619,10 @@ mod tests { #[test] fn compares_with_a_string() { let authority: Authority = "def.com".parse().unwrap(); - assert!(authority < "ghi.com".to_string()); - assert!("ghi.com".to_string() > authority); - assert!(authority > "abc.com".to_string()); - assert!("abc.com".to_string() < authority); + assert!(authority < "ghi.com"); + assert!("ghi.com" > authority); + assert!(authority > "abc.com"); + assert!("abc.com" < authority); } #[test] diff --git a/src/uri/builder.rs b/src/uri/builder.rs index d5f7f49b..9aaf330e 100644 --- a/src/uri/builder.rs +++ b/src/uri/builder.rs @@ -182,10 +182,10 @@ mod tests { fn build_from_string() { for i in 1..10 { let uri = Builder::new() - .path_and_query(format!("/foo?a={}", i)) + .path_and_query(format!("/foo?a={i}")) .build() .unwrap(); - let expected_query = format!("a={}", i); + let expected_query = format!("a={i}"); assert_eq!(uri.path(), "/foo"); assert_eq!(uri.query(), Some(expected_query.as_str())); } @@ -194,9 +194,9 @@ mod tests { #[test] fn build_from_string_ref() { for i in 1..10 { - let p_a_q = format!("/foo?a={}", i); + let p_a_q = format!("/foo?a={i}"); let uri = Builder::new().path_and_query(&p_a_q).build().unwrap(); - let expected_query = format!("a={}", i); + let expected_query = format!("a={i}"); assert_eq!(uri.path(), "/foo"); assert_eq!(uri.query(), Some(expected_query.as_str())); } diff --git a/src/uri/mod.rs b/src/uri/mod.rs index 767f0743..58b89e60 100644 --- a/src/uri/mod.rs +++ b/src/uri/mod.rs @@ -103,6 +103,7 @@ pub struct Uri { /// /// This struct is used to provide to and retrieve from a URI. #[derive(Debug, Default)] +#[non_exhaustive] pub struct Parts { /// The scheme component of a URI pub scheme: Option, @@ -112,9 +113,6 @@ pub struct Parts { /// The origin-form component of a URI pub path_and_query: Option, - - /// Allow extending in the future - _priv: (), } /// An error resulting from a failed attempt to construct a URI. @@ -361,7 +359,7 @@ impl Uri { let s = Bytes::from_static(src.as_bytes()); match Uri::from_shared(s) { Ok(uri) => uri, - Err(e) => panic!("static str is not valid URI: {}", e), + Err(e) => panic!("static str is not valid URI: {e}"), } } @@ -814,7 +812,6 @@ impl From for Parts { scheme, authority, path_and_query, - _priv: (), } } } @@ -1001,7 +998,7 @@ impl<'a> PartialEq<&'a str> for Uri { } } -impl<'a> PartialEq for &'a str { +impl PartialEq for &str { fn eq(&self, uri: &Uri) -> bool { uri == *self } @@ -1024,17 +1021,17 @@ impl Default for Uri { impl fmt::Display for Uri { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(scheme) = self.scheme() { - write!(f, "{}://", scheme)?; + write!(f, "{scheme}://")?; } if let Some(authority) = self.authority() { - write!(f, "{}", authority)?; + write!(f, "{authority}")?; } write!(f, "{}", self.path())?; if let Some(query) = self.query() { - write!(f, "?{}", query)?; + write!(f, "?{query}")?; } Ok(()) diff --git a/src/uri/path.rs b/src/uri/path.rs index 42db1f92..b37d04cb 100644 --- a/src/uri/path.rs +++ b/src/uri/path.rs @@ -383,7 +383,7 @@ impl PartialEq for PathAndQuery { } } -impl<'a> PartialEq for &'a str { +impl PartialEq for &str { #[inline] fn eq(&self, other: &PathAndQuery) -> bool { self == &other.as_str() @@ -446,7 +446,7 @@ impl<'a> PartialOrd<&'a str> for PathAndQuery { } } -impl<'a> PartialOrd for &'a str { +impl PartialOrd for &str { #[inline] fn partial_cmp(&self, other: &PathAndQuery) -> Option { self.partial_cmp(&other.as_str()) @@ -548,10 +548,10 @@ mod tests { #[test] fn compares_with_a_string() { let path_and_query: PathAndQuery = "/b/world&foo=bar".parse().unwrap(); - assert!(path_and_query < "/c/world&foo=bar".to_string()); - assert!("/c/world&foo=bar".to_string() > path_and_query); - assert!(path_and_query > "/a/world&foo=bar".to_string()); - assert!("/a/world&foo=bar".to_string() < path_and_query); + assert!(path_and_query < "/c/world&foo=bar"); + assert!("/c/world&foo=bar" > path_and_query); + assert!(path_and_query > "/a/world&foo=bar"); + assert!("/a/world&foo=bar" < path_and_query); } #[test] @@ -599,6 +599,6 @@ mod tests { } fn pq(s: &str) -> PathAndQuery { - s.parse().expect(&format!("parsing {}", s)) + s.parse().unwrap_or_else(|_| panic!("parsing {s}")) } } diff --git a/src/uri/scheme.rs b/src/uri/scheme.rs index dbcc8c3f..47a8bb1c 100644 --- a/src/uri/scheme.rs +++ b/src/uri/scheme.rs @@ -356,6 +356,6 @@ mod test { } fn scheme(s: &str) -> Scheme { - s.parse().expect(&format!("Invalid scheme: {}", s)) + s.parse().unwrap_or_else(|_| panic!("Invalid scheme: {s}")) } } diff --git a/tests/header_map.rs b/tests/header_map.rs index 9a9d7e12..b81b3213 100644 --- a/tests/header_map.rs +++ b/tests/header_map.rs @@ -60,7 +60,7 @@ fn with_capacity_overflow() { fn reserve_overflow() { // See https://github.com/hyperium/http/issues/352 let mut headers = HeaderMap::::with_capacity(0); - headers.reserve(std::usize::MAX); // next_power_of_two overflows + headers.reserve(usize::MAX); // next_power_of_two overflows } #[test] @@ -74,9 +74,7 @@ fn reserve() { let reserved_cap = headers.capacity(); assert!( reserved_cap >= requested_cap, - "requested {} capacity, but it reserved only {} entries", - requested_cap, - reserved_cap, + "requested {requested_cap} capacity, but it reserved only {reserved_cap} entries", ); for i in 0..requested_cap { @@ -351,7 +349,7 @@ fn custom_std(n: usize) -> Vec { .collect() } -const STD: &'static [HeaderName] = &[ +const STD: &[HeaderName] = &[ ACCEPT, ACCEPT_CHARSET, ACCEPT_ENCODING, diff --git a/tests/header_map_fuzz.rs b/tests/header_map_fuzz.rs index e6a43e8d..6cd9ea2a 100644 --- a/tests/header_map_fuzz.rs +++ b/tests/header_map_fuzz.rs @@ -170,7 +170,7 @@ impl AltMap { let name = self.gen_name(-5, rng); let val = gen_header_value(rng); - let vals = self.map.entry(name.clone()).or_insert(vec![]); + let vals = self.map.entry(name.clone()).or_default(); let ret = !vals.is_empty(); vals.push(val.clone()); @@ -180,7 +180,7 @@ impl AltMap { /// Negative numbers weigh finding an existing header higher fn gen_name(&self, weight: i32, rng: &mut StdRng) -> HeaderName { - let mut existing = rng.random_ratio(1, weight.abs() as u32); + let mut existing = rng.random_ratio(1, weight.unsigned_abs()); if weight < 0 { existing = !existing; @@ -203,7 +203,7 @@ impl AltMap { None } else { let n = rng.random_range(0..self.map.len()); - self.map.keys().nth(n).map(Clone::clone) + self.map.keys().nth(n).cloned() } } @@ -221,7 +221,7 @@ impl AltMap { for (key, val) in &self.map { // Test get - assert_eq!(other.get(key), val.get(0)); + assert_eq!(other.get(key), val.first()); // Test get_all let vals = other.get_all(key); @@ -253,7 +253,7 @@ impl Action { } fn gen_header_name(g: &mut StdRng) -> HeaderName { - const STANDARD_HEADERS: &'static [HeaderName] = &[ + const STANDARD_HEADERS: &[HeaderName] = &[ header::ACCEPT, header::ACCEPT_CHARSET, header::ACCEPT_ENCODING, @@ -354,10 +354,9 @@ fn gen_string(g: &mut StdRng, min: usize, max: usize) -> String { let bytes: Vec<_> = (min..max) .map(|_| { // Chars to pick from - b"ABCDEFGHIJKLMNOPQRSTUVabcdefghilpqrstuvwxyz----" + *b"ABCDEFGHIJKLMNOPQRSTUVabcdefghilpqrstuvwxyz----" .choose(g) .unwrap() - .clone() }) .collect();