diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7683bf8438..0d7ff37cfc 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -82,6 +82,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal + components: clippy toolchain: ${{ matrix.rust }} override: true @@ -91,6 +92,12 @@ jobs: command: test args: ${{ matrix.features }} + - name: Clippy + uses: actions-rs/cargo@v1 + with: + command: clippy + args: ${{ matrix.features }} --lib --examples --benches + - name: Test all benches if: matrix.benches uses: actions-rs/cargo@v1 diff --git a/benches/body.rs b/benches/body.rs index ea1a499bbf..86d8adbadf 100644 --- a/benches/body.rs +++ b/benches/body.rs @@ -1,3 +1,4 @@ +#![cfg(feature = "nightly")] #![feature(test)] #![deny(warnings)] diff --git a/benches/connect.rs b/benches/connect.rs index 34769cf930..6898dea1a1 100644 --- a/benches/connect.rs +++ b/benches/connect.rs @@ -1,8 +1,7 @@ +#![cfg(feature = "nightly")] #![feature(test)] #![deny(warnings)] -extern crate test; - // TODO: Reimplement http_connector bench using hyper::client::conn // (instead of removed HttpConnector). diff --git a/benches/end_to_end.rs b/benches/end_to_end.rs index 41dbde2ab0..076152e8c6 100644 --- a/benches/end_to_end.rs +++ b/benches/end_to_end.rs @@ -1,8 +1,7 @@ +#![cfg(feature = "nightly")] #![feature(test)] #![deny(warnings)] -extern crate test; - // TODO: Reimplement Opts::bench using hyper::server::conn and hyper::client::conn // (instead of Server and HttpClient). diff --git a/benches/pipeline.rs b/benches/pipeline.rs index a60100fa51..219ab755a3 100644 --- a/benches/pipeline.rs +++ b/benches/pipeline.rs @@ -1,3 +1,4 @@ +#![cfg(feature = "nightly")] #![feature(test)] #![deny(warnings)] diff --git a/benches/server.rs b/benches/server.rs index 17eefa0694..2b8e63e3c9 100644 --- a/benches/server.rs +++ b/benches/server.rs @@ -1,3 +1,4 @@ +#![cfg(feature = "nightly")] #![feature(test)] #![deny(warnings)] @@ -149,7 +150,7 @@ fn raw_tcp_throughput_small_payload(b: &mut test::Bencher) { let mut buf = [0u8; 8192]; while rx.try_recv().is_err() { - sock.read(&mut buf).unwrap(); + let _ = sock.read(&mut buf).unwrap(); sock.write_all( b"\ HTTP/1.1 200 OK\r\n\ @@ -196,7 +197,7 @@ fn raw_tcp_throughput_large_payload(b: &mut test::Bencher) { let mut buf = [0u8; 8192]; while rx.try_recv().is_err() { let r = sock.read(&mut buf).unwrap(); - extern crate test; + if r == 0 { break; } diff --git a/benches/support/tokiort.rs b/benches/support/tokiort.rs index 49558f0a2c..ac841d1d11 100644 --- a/benches/support/tokiort.rs +++ b/benches/support/tokiort.rs @@ -32,13 +32,13 @@ impl Timer for TokioTimer { fn sleep(&self, duration: Duration) -> Box { let s = tokio::time::sleep(duration); let hs = TokioSleep { inner: Box::pin(s) }; - return Box::new(hs); + Box::new(hs) } fn sleep_until(&self, deadline: Instant) -> Box { - return Box::new(TokioSleep { + Box::new(TokioSleep { inner: Box::pin(tokio::time::sleep_until(deadline.into())), - }); + }) } } diff --git a/examples/client.rs b/examples/client.rs index ffcc026719..dd5a004103 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -65,7 +65,7 @@ async fn fetch_url(url: hyper::Uri) -> Result<()> { while let Some(next) = res.frame().await { let frame = next?; if let Some(chunk) = frame.data_ref() { - io::stdout().write_all(&chunk).await?; + io::stdout().write_all(chunk).await?; } } diff --git a/examples/gateway.rs b/examples/gateway.rs index 2c8b8e17d5..0484d09317 100644 --- a/examples/gateway.rs +++ b/examples/gateway.rs @@ -11,8 +11,6 @@ async fn main() -> Result<(), Box> { let in_addr: SocketAddr = ([127, 0, 0, 1], 3001).into(); let out_addr: SocketAddr = ([127, 0, 0, 1], 3000).into(); - let out_addr_clone = out_addr.clone(); - let listener = TcpListener::bind(in_addr).await?; println!("Listening on http://{}", in_addr); @@ -27,7 +25,7 @@ async fn main() -> Result<(), Box> { let service = service_fn(move |mut req| { let uri_string = format!( "http://{}{}", - out_addr_clone, + out_addr, req.uri() .path_and_query() .map(|x| x.as_str()) diff --git a/examples/http_proxy.rs b/examples/http_proxy.rs index 792e1e470d..a5baebfc61 100644 --- a/examples/http_proxy.rs +++ b/examples/http_proxy.rs @@ -104,7 +104,7 @@ async fn proxy(req: Request) -> Result Option { - uri.authority().and_then(|auth| Some(auth.to_string())) + uri.authority().map(|auth| auth.to_string()) } fn empty() -> BoxBody { diff --git a/examples/upgrades.rs b/examples/upgrades.rs index e5494e7bbb..3be9f3fb17 100644 --- a/examples/upgrades.rs +++ b/examples/upgrades.rs @@ -160,7 +160,6 @@ async fn main() { res = &mut conn => { if let Err(err) = res { println!("Error serving connection: {:?}", err); - return; } } // Continue polling the connection after enabling graceful shutdown. @@ -178,7 +177,7 @@ async fn main() { }); // Client requests a HTTP connection upgrade. - let request = client_upgrade_request(addr.clone()); + let request = client_upgrade_request(addr); if let Err(e) = request.await { eprintln!("client error: {}", e); } diff --git a/examples/web_api.rs b/examples/web_api.rs index 47c30cd852..7d56d87e56 100644 --- a/examples/web_api.rs +++ b/examples/web_api.rs @@ -111,7 +111,7 @@ async fn main() -> Result<()> { let (stream, _) = listener.accept().await?; tokio::task::spawn(async move { - let service = service_fn(move |req| response_examples(req)); + let service = service_fn(response_examples); if let Err(err) = http1::Builder::new() .serve_connection(stream, service) diff --git a/src/body/body.rs b/src/body/body.rs index f93030f7c7..7822a86691 100644 --- a/src/body/body.rs +++ b/src/body/body.rs @@ -125,14 +125,12 @@ impl Recv { if !content_length.is_exact() && recv.is_end_stream() { content_length = DecodedLength::ZERO; } - let body = Recv::new(Kind::H2 { + Recv::new(Kind::H2 { data_done: false, ping, content_length, recv, - }); - - body + }) } #[cfg(feature = "ffi")] @@ -170,13 +168,9 @@ impl Body for Recv { want_tx.send(WANT_READY); if !data_rx.is_terminated() { - match ready!(Pin::new(data_rx).poll_next(cx)?) { - Some(chunk) => { - len.sub_if(chunk.len() as u64); - return Poll::Ready(Some(Ok(Frame::data(chunk)))); - } - // fall through to trailers - None => (), + if let Some(chunk) = ready!(Pin::new(data_rx).poll_next(cx)?) { + len.sub_if(chunk.len() as u64); + return Poll::Ready(Some(Ok(Frame::data(chunk)))); } } @@ -339,6 +333,7 @@ impl Sender { /// Aborts the body in an abnormal fashion. #[allow(unused)] + #[allow(clippy::redundant_clone)] pub(crate) fn abort(self) { let _ = self .data_tx diff --git a/src/client/conn/http1.rs b/src/client/conn/http1.rs index ad100f8819..ce99018aa8 100644 --- a/src/client/conn/http1.rs +++ b/src/client/conn/http1.rs @@ -33,6 +33,7 @@ pub struct SendRequest { /// This allows taking apart a `Connection` at a later time, in order to /// reclaim the IO object, and additional related pieces. #[derive(Debug)] +#[non_exhaustive] pub struct Parts { /// The original IO object used in the handshake. pub io: T, @@ -45,7 +46,6 @@ pub struct Parts { /// You will want to check for any existing bytes if you plan to continue /// communicating on the IO object. pub read_buf: Bytes, - _inner: (), } @@ -76,7 +76,6 @@ where Parts { io, read_buf, - _inner: (), } } @@ -546,3 +545,9 @@ impl Builder { } } } + +impl std::default::Default for Builder { + fn default() -> Self { + Self::new() + } +} diff --git a/src/client/conn/http2.rs b/src/client/conn/http2.rs index ee7325d385..63ee836efc 100644 --- a/src/client/conn/http2.rs +++ b/src/client/conn/http2.rs @@ -441,3 +441,9 @@ impl Builder { } } } + +impl std::default::Default for Builder { + fn default() -> Self { + Self::new() + } +} diff --git a/src/common/buf.rs b/src/common/buf.rs index 64e9333ead..342c0309ff 100644 --- a/src/common/buf.rs +++ b/src/common/buf.rs @@ -8,12 +8,14 @@ pub(crate) struct BufList { } impl BufList { + #[cfg(feature = "http1")] pub(crate) fn new() -> BufList { BufList { bufs: VecDeque::new(), } } + #[cfg(feature = "http1")] #[inline] pub(crate) fn push(&mut self, buf: T) { debug_assert!(buf.has_remaining()); diff --git a/src/error.rs b/src/error.rs index bc4414ab78..3d58592b65 100644 --- a/src/error.rs +++ b/src/error.rs @@ -67,6 +67,7 @@ pub(super) enum Parse { Header(Header), TooLarge, Status, + #[cfg(feature = "http1")] #[cfg_attr(debug_assertions, allow(unused))] Internal, } @@ -193,7 +194,7 @@ impl Error { pub(crate) fn find_source(&self) -> Option<&E> { let mut cause = self.source(); while let Some(err) = cause { - if let Some(ref typed) = err.downcast_ref() { + if let Some(typed) = err.downcast_ref() { return Some(typed); } cause = err.source(); @@ -351,6 +352,7 @@ impl Error { } Kind::Parse(Parse::TooLarge) => "message head is too large", Kind::Parse(Parse::Status) => "invalid HTTP status-code parsed", + #[cfg(feature = "http1")] Kind::Parse(Parse::Internal) => { "internal error inside Hyper and/or its dependencies, please report" } diff --git a/src/ext.rs b/src/ext.rs index 6c54821e9d..6c80e73144 100644 --- a/src/ext.rs +++ b/src/ext.rs @@ -104,7 +104,7 @@ impl HeaderCaseMap { &'a self, name: &HeaderName, ) -> impl Iterator + 'a> + 'a { - self.get_all_internal(name).into_iter() + self.get_all_internal(name) } /// Returns a view of all spellings associated with that header name, diff --git a/src/ext/h1_reason_phrase.rs b/src/ext/h1_reason_phrase.rs index 021b632b6d..faad76121d 100644 --- a/src/ext/h1_reason_phrase.rs +++ b/src/ext/h1_reason_phrase.rs @@ -52,6 +52,8 @@ impl ReasonPhrase { /// Converts a `Bytes` directly into a `ReasonPhrase` without validating. /// + /// # Safety + /// /// Use with care; invalid bytes in a reason phrase can cause serious security problems if /// emitted in a response. pub unsafe fn from_bytes_unchecked(reason: Bytes) -> Self { @@ -107,9 +109,9 @@ impl TryFrom for ReasonPhrase { } } -impl Into for ReasonPhrase { - fn into(self) -> Bytes { - self.0 +impl From for Bytes { + fn from(rp: ReasonPhrase) -> Self { + rp.0 } } @@ -144,12 +146,9 @@ const fn is_valid_byte(b: u8) -> bool { } // See https://httpwg.org/http-core/draft-ietf-httpbis-semantics-latest.html#fields.values - // - // The 0xFF comparison is technically redundant, but it matches the text of the spec more - // clearly and will be optimized away. #[allow(unused_comparisons)] const fn is_obs_text(b: u8) -> bool { - 0x80 <= b && b <= 0xFF + 0x80 <= b /* && b <= 0xFF */ } // See https://httpwg.org/http-core/draft-ietf-httpbis-messaging-latest.html#rfc.section.4.p.7 @@ -174,26 +173,26 @@ mod tests { #[test] fn basic_valid() { - const PHRASE: &'static [u8] = b"OK"; + const PHRASE: &[u8] = b"OK"; assert_eq!(ReasonPhrase::from_static(PHRASE).as_bytes(), PHRASE); assert_eq!(ReasonPhrase::try_from(PHRASE).unwrap().as_bytes(), PHRASE); } #[test] fn empty_valid() { - const PHRASE: &'static [u8] = b""; + const PHRASE: &[u8] = b""; assert_eq!(ReasonPhrase::from_static(PHRASE).as_bytes(), PHRASE); assert_eq!(ReasonPhrase::try_from(PHRASE).unwrap().as_bytes(), PHRASE); } #[test] fn obs_text_valid() { - const PHRASE: &'static [u8] = b"hyp\xe9r"; + const PHRASE: &[u8] = b"hyp\xe9r"; assert_eq!(ReasonPhrase::from_static(PHRASE).as_bytes(), PHRASE); assert_eq!(ReasonPhrase::try_from(PHRASE).unwrap().as_bytes(), PHRASE); } - const NEWLINE_PHRASE: &'static [u8] = b"hyp\ner"; + const NEWLINE_PHRASE: &[u8] = b"hyp\ner"; #[test] #[should_panic] @@ -206,7 +205,7 @@ mod tests { assert!(ReasonPhrase::try_from(NEWLINE_PHRASE).is_err()); } - const CR_PHRASE: &'static [u8] = b"hyp\rer"; + const CR_PHRASE: &[u8] = b"hyp\rer"; #[test] #[should_panic] diff --git a/src/headers.rs b/src/headers.rs index 8407be185f..7692e32918 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -61,7 +61,7 @@ pub(super) fn content_length_parse_all_values(values: ValueIter<'_, HeaderValue> } } - return content_length + content_length } fn from_digits(bytes: &[u8]) -> Option { @@ -93,10 +93,7 @@ fn from_digits(bytes: &[u8]) -> Option { #[cfg(all(feature = "http2", feature = "client"))] pub(super) fn method_has_defined_payload_semantics(method: &Method) -> bool { - match *method { - Method::GET | Method::HEAD | Method::DELETE | Method::CONNECT => false, - _ => true, - } + !matches!(*method, Method::GET | Method::HEAD | Method::DELETE | Method::CONNECT) } #[cfg(feature = "http2")] diff --git a/src/lib.rs b/src/lib.rs index 2bd4d759d3..d8c8f5a1a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![deny(missing_docs)] #![deny(missing_debug_implementations)] +#![allow(clippy::module_inception)] #![cfg_attr(test, deny(rust_2018_idioms))] #![cfg_attr(all(test, feature = "full"), deny(unreachable_pub))] #![cfg_attr(all(test, feature = "full"), deny(warnings))] diff --git a/src/proto/h1/conn.rs b/src/proto/h1/conn.rs index 3250b7f3dc..22dbcf5bf8 100644 --- a/src/proto/h1/conn.rs +++ b/src/proto/h1/conn.rs @@ -169,10 +169,7 @@ where } pub(crate) fn can_read_body(&self) -> bool { - match self.state.reading { - Reading::Body(..) | Reading::Continue(..) => true, - _ => false, - } + matches!(self.state.reading, Reading::Body(..) | Reading::Continue(..)) } fn should_error_on_eof(&self) -> bool { @@ -185,6 +182,7 @@ where read_buf.len() >= 24 && read_buf[..24] == *H2_PREFACE } + #[allow(clippy::type_complexity)] // The return type is complex due to task-semantics pub(super) fn poll_read_head( &mut self, cx: &mut task::Context<'_>, @@ -943,11 +941,7 @@ impl State { } fn wants_keep_alive(&self) -> bool { - if let KA::Disabled = self.keep_alive.status() { - false - } else { - true - } + !matches!(self.keep_alive.status(), KA::Disabled) } fn try_keep_alive(&mut self) { diff --git a/src/proto/h1/decode.rs b/src/proto/h1/decode.rs index 4077b22062..73c79fc522 100644 --- a/src/proto/h1/decode.rs +++ b/src/proto/h1/decode.rs @@ -451,7 +451,7 @@ mod tests { let mut v = vec![0; len]; let mut buf = ReadBuf::new(&mut v); ready!(Pin::new(self).poll_read(cx, &mut buf)?); - Poll::Ready(Ok(Bytes::copy_from_slice(&buf.filled()))) + Poll::Ready(Ok(Bytes::copy_from_slice(buf.filled()))) } } @@ -487,8 +487,7 @@ mod tests { let result = futures_util::future::poll_fn(|cx| state.step(cx, rdr, &mut size, &mut None)) .await; - let desc = format!("read_size failed for {:?}", s); - state = result.expect(desc.as_str()); + state = result.unwrap_or_else(|_| panic!("read_size failed for {:?}", s)); if state == ChunkedState::Body || state == ChunkedState::EndCr { break; } diff --git a/src/proto/h1/dispatch.rs b/src/proto/h1/dispatch.rs index a1c9341953..965176e021 100644 --- a/src/proto/h1/dispatch.rs +++ b/src/proto/h1/dispatch.rs @@ -19,6 +19,8 @@ pub(crate) struct Dispatcher { is_closing: bool, } +pub(crate) type DispatchResult = Poll>>; + pub(crate) trait Dispatch { type PollItem; type PollBody; @@ -27,7 +29,7 @@ pub(crate) trait Dispatch { fn poll_msg( self: Pin<&mut Self>, cx: &mut task::Context<'_>, - ) -> Poll>>; + ) -> DispatchResult; fn recv_msg(&mut self, msg: crate::Result<(Self::RecvItem, Recv)>) -> crate::Result<()>; fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll>; fn should_poll(&self) -> bool; @@ -307,7 +309,7 @@ where .size_hint() .exact() .map(BodyLength::Known) - .or_else(|| Some(BodyLength::Unknown)); + .or(Some(BodyLength::Unknown)); self.body_rx.set(Some(body)); btype }; diff --git a/src/proto/h1/io.rs b/src/proto/h1/io.rs index da4101b6fb..5542fff9ee 100644 --- a/src/proto/h1/io.rs +++ b/src/proto/h1/io.rs @@ -344,7 +344,7 @@ where } #[cfg(test)] - fn flush<'a>(&'a mut self) -> impl std::future::Future> + 'a { + fn flush(&mut self) -> impl std::future::Future> + '_ { futures_util::future::poll_fn(move |cx| self.poll_flush(cx)) } } diff --git a/src/proto/h1/role.rs b/src/proto/h1/role.rs index 37072384a2..80ab19004d 100644 --- a/src/proto/h1/role.rs +++ b/src/proto/h1/role.rs @@ -170,7 +170,7 @@ impl Http1Transaction for Server { Version::HTTP_10 }; - record_header_indices(bytes, &req.headers, &mut headers_indices)?; + record_header_indices(bytes, req.headers, &mut headers_indices)?; headers_len = req.headers.len(); } Ok(httparse::Status::Partial) => return Ok(None), @@ -453,9 +453,10 @@ impl Http1Transaction for Server { }; debug!("sending automatic response ({}) for parse error", status); - let mut msg = MessageHead::default(); - msg.subject = status; - Some(msg) + Some(MessageHead { + subject: status, + ..MessageHead::default() + }) } fn is_server() -> bool { @@ -474,16 +475,13 @@ impl Server { } fn can_chunked(method: &Option, status: StatusCode) -> bool { - if method == &Some(Method::HEAD) || method == &Some(Method::CONNECT) && status.is_success() + if method == &Some(Method::HEAD) + || method == &Some(Method::CONNECT) && status.is_success() + || status.is_informational() { false - } else if status.is_informational() { - false } else { - match status { - StatusCode::NO_CONTENT | StatusCode::NOT_MODIFIED => false, - _ => true, - } + !matches!(status, StatusCode::NO_CONTENT | StatusCode::NOT_MODIFIED) } } @@ -491,10 +489,7 @@ impl Server { if status.is_informational() || method == &Some(Method::CONNECT) && status.is_success() { false } else { - match status { - StatusCode::NO_CONTENT | StatusCode::NOT_MODIFIED => false, - _ => true, - } + !matches!(status, StatusCode::NO_CONTENT | StatusCode::NOT_MODIFIED) } } @@ -970,7 +965,7 @@ impl Http1Transaction for Client { } else { Version::HTTP_10 }; - record_header_indices(bytes, &res.headers, &mut headers_indices)?; + record_header_indices(bytes, res.headers, &mut headers_indices)?; let headers_len = res.headers.len(); (len, status, reason, version, headers_len) } @@ -1646,7 +1641,7 @@ mod tests { Server::parse(&mut raw, ctx).unwrap_err(); } - const H09_RESPONSE: &'static str = "Baguettes are super delicious, don't you agree?"; + const H09_RESPONSE: &str = "Baguettes are super delicious, don't you agree?"; #[test] fn test_parse_response_h09_allowed() { @@ -1697,7 +1692,7 @@ mod tests { assert_eq!(raw, H09_RESPONSE); } - const RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON: &'static str = + const RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON: &str = "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials : true\r\n\r\n"; #[test] diff --git a/src/proto/h2/client.rs b/src/proto/h2/client.rs index 92ab69cd56..fe3a9158bd 100644 --- a/src/proto/h2/client.rs +++ b/src/proto/h2/client.rs @@ -125,7 +125,7 @@ where } }); - let ping_config = new_ping_config(&config); + let ping_config = new_ping_config(config); let (conn, ping) = if ping_config.is_enabled() { let pp = conn.ping_pong().expect("conn.ping_pong"); @@ -248,17 +248,16 @@ where let eos = body.is_end_stream(); let ping = self.ping.clone(); - if is_connect { - if headers::content_length_parse_all(req.headers()) + if is_connect + && headers::content_length_parse_all(req.headers()) .map_or(false, |len| len != 0) - { - warn!("h2 connect request with non-zero body not supported"); - cb.send(Err(( - crate::Error::new_h2(h2::Reason::INTERNAL_ERROR.into()), - None, - ))); - continue; - } + { + warn!("h2 connect request with non-zero body not supported"); + cb.send(Err(( + crate::Error::new_h2(h2::Reason::INTERNAL_ERROR.into()), + None, + ))); + continue; } if let Some(protocol) = req.extensions_mut().remove::() { diff --git a/src/server/conn/http1.rs b/src/server/conn/http1.rs index 421ef9cd72..2fe9449255 100644 --- a/src/server/conn/http1.rs +++ b/src/server/conn/http1.rs @@ -51,6 +51,7 @@ pub struct Builder { /// This allows taking apart a `Connection` at a later time, in order to /// reclaim the IO object, and additional related pieces. #[derive(Debug)] +#[non_exhaustive] pub struct Parts { /// The original IO object used in the handshake. pub io: T, @@ -65,7 +66,6 @@ pub struct Parts { pub read_buf: Bytes, /// The `Service` used to serve this connection. pub service: S, - _inner: (), } // ===== impl Connection ===== @@ -116,7 +116,6 @@ where io, read_buf, service: dispatch.into_service(), - _inner: (), } } @@ -192,7 +191,7 @@ where pending.manual(); } }; - return Poll::Ready(Ok(())); + Poll::Ready(Ok(())) } Err(e) => Poll::Ready(Err(e)), } @@ -401,6 +400,12 @@ impl Builder { } } +impl std::default::Default for Builder { + fn default() -> Self { + Self::new() + } +} + mod upgrades { use crate::upgrade::Upgraded; diff --git a/src/server/conn/http2.rs b/src/server/conn/http2.rs index e39aaf80e9..b4d52abcaa 100644 --- a/src/server/conn/http2.rs +++ b/src/server/conn/http2.rs @@ -104,7 +104,7 @@ impl Builder { /// This starts with the default options, and an executor. pub fn new(exec: E) -> Self { Self { - exec: exec, + exec, timer: Time::Empty, h2_builder: Default::default(), } diff --git a/src/upgrade.rs b/src/upgrade.rs index 1c7b5b01cd..117ef512bc 100644 --- a/src/upgrade.rs +++ b/src/upgrade.rs @@ -78,6 +78,7 @@ pub struct OnUpgrade { /// Includes the original IO type, and a read buffer of bytes that the /// HTTP state machine may have already read before completing an upgrade. #[derive(Debug)] +#[non_exhaustive] pub struct Parts { /// The original IO object used before the upgrade. pub io: T, @@ -90,7 +91,6 @@ pub struct Parts { /// You will want to check for any existing bytes if you plan to continue /// communicating on the IO object. pub read_buf: Bytes, - _inner: (), } /// Gets a pending HTTP upgrade from this message. @@ -139,7 +139,6 @@ impl Upgraded { Ok(t) => Ok(Parts { io: *t, read_buf: buf, - _inner: (), }), Err(io) => Err(Upgraded { io: Rewind::new_buffered(io, buf), diff --git a/tests/client.rs b/tests/client.rs index 508995046b..a6838f02b2 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -997,7 +997,7 @@ test! { \r\n\ ", reply: { - let long_header = std::iter::repeat("A").take(500_000).collect::(); + let long_header = "A".repeat(500_000); format!("\ HTTP/1.1 200 OK\r\n\ {}: {}\r\n\ diff --git a/tests/server.rs b/tests/server.rs index 6b798ef3e4..56fa27d9c3 100644 --- a/tests/server.rs +++ b/tests/server.rs @@ -1607,7 +1607,7 @@ async fn upgrades_new() { let response = s(&buf); assert!(response.starts_with("HTTP/1.1 101 Switching Protocols\r\n")); - assert!(!has_header(&response, "content-length")); + assert!(!has_header(response, "content-length")); let _ = read_101_tx.send(()); let n = tcp.read(&mut buf).expect("read 2"); diff --git a/tests/support/mod.rs b/tests/support/mod.rs index dced9a2e3b..8e0a875d7e 100644 --- a/tests/support/mod.rs +++ b/tests/support/mod.rs @@ -367,7 +367,7 @@ async fn async_test(cfg: __TestConfig) { assert_eq!(req.method(), &sreq.method, "client method"); assert_eq!(req.version(), version, "client version"); for func in &sreq.headers { - func(&req.headers()); + func(req.headers()); } let sbody = sreq.body; req.collect().map_ok(move |collected| { @@ -456,7 +456,7 @@ async fn async_test(cfg: __TestConfig) { assert_eq!(res.status(), cstatus, "server status"); assert_eq!(res.version(), version, "server version"); for func in &cheaders { - func(&res.headers()); + func(res.headers()); } let body = res.collect().await.unwrap().to_bytes();