From 3f43767be67326db3971b22685278093aa4b5f8b Mon Sep 17 00:00:00 2001 From: Rene Leonhardt <65483435+reneleonhardt@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:11:21 +0200 Subject: [PATCH 1/6] chore: update dependencies --- .github/actions/compliance/action.yml | 5 +- .github/dependabot.yml | 12 +++ .github/workflows/CI.yml | 101 +++++++------------------- examples/Cargo.toml | 4 +- examples/client.rs | 20 +++-- h3-datagram/src/datagram.rs | 2 +- h3-quinn/src/datagram.rs | 8 +- h3-quinn/src/lib.rs | 10 +-- h3-webtransport/src/server.rs | 6 +- h3/Cargo.toml | 6 +- h3/src/buf.rs | 2 +- h3/src/qpack/dynamic.rs | 4 +- h3/src/qpack/prefix_string/decode.rs | 4 +- h3/src/shared_state.rs | 2 +- h3/src/stream.rs | 7 +- h3/src/tests/mod.rs | 2 +- 16 files changed, 76 insertions(+), 119 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/actions/compliance/action.yml b/.github/actions/compliance/action.yml index 7e41d341..19497796 100644 --- a/.github/actions/compliance/action.yml +++ b/.github/actions/compliance/action.yml @@ -14,10 +14,9 @@ runs: using: "composite" steps: - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable - override: true - name: Cache builds uses: camshaft/rust-cache@v1 @@ -67,7 +66,7 @@ runs: # publish report only when pushing to master - name: Push to gh-pages if: github.ref == 'refs/heads/master' - uses: ad-m/github-push-action@master + uses: ad-m/github-push-action@v1 with: github_token: ${{ github.token }} branch: gh-pages diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..aad874af --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: cargo + directories: + - / + - fuzz + schedule: + interval: weekly + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 26fad965..72da4421 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -8,7 +8,7 @@ on: env: RUST_BACKTRACE: 1 toolchain_style: stable - toolchain_msrv: 1.70.0 + toolchain_msrv: 1.74.1 toolchain_h3_quinn_msrv: 1.74.1 toolchain_doc: nightly-2025-04-02 toolchain_lint: stable @@ -35,76 +35,49 @@ jobs: name: Check Style runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Install Rust ${{ env.toolchain_style }} - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: ${{ env.toolchain_style }} - override: true components: rustfmt - - uses: Swatinem/rust-cache@v2 - - name: cargo fmt --all -- --check - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + - run: cargo fmt --all -- --check lint: name: Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Install Rust ${{ env.toolchain_lint }} - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: ${{ env.toolchain_lint }} - override: true components: clippy - - uses: Swatinem/rust-cache@v2 - - name: cargo clippy - uses: actions-rs/cargo@v1 - with: - command: clippy + - run: cargo clippy msrv: name: Check MSRV needs: [style] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Install Rust ${{ env.toolchain_msrv }} - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: ${{ env.toolchain_msrv }} - override: true - - uses: Swatinem/rust-cache@v2 - - name: cargo check -p h3 - uses: actions-rs/cargo@v1 - with: - command: check - args: -p h3 + - run: cargo check -p h3 msrv_h3_quinn: name: Check MSRV of `h3-quinn` needs: [style] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Install Rust ${{ env.toolchain_h3_quinn_msrv }} - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: ${{ env.toolchain_h3_quinn_msrv }} - override: true - - uses: Swatinem/rust-cache@v2 - - name: cargo check -p h3-quinn - uses: actions-rs/cargo@v1 - with: - command: check - args: -p h3-quinn + - run: cargo check -p h3-quinn test: name: Test ${{ matrix.toolchain }} ${{ matrix.os }} ${{ matrix.target }} @@ -123,7 +96,7 @@ jobs: target: i686-unknown-linux-gnu runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 # Add this step for 32-bit build support - name: Install 32-bit development libraries if: matrix.target == 'i686-unknown-linux-gnu' @@ -132,18 +105,11 @@ jobs: sudo apt-get update sudo apt-get install -y gcc-multilib libc6-dev-i386 - name: Install Rust ${{ matrix.toolchain }} - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: ${{ matrix.toolchain }} target: ${{ matrix.target }} - override: true - - uses: Swatinem/rust-cache@v2 - - name: cargo test - uses: actions-rs/cargo@v1 - with: - command: test - args: --features ${{ matrix.features }} --target ${{ matrix.target }} + - run: cargo test --features ${{ matrix.features }} --target ${{ matrix.target }} - name: h3Spec run: ./ci/h3spec.sh if: matrix.toolchain == 'stable' @@ -153,49 +119,35 @@ jobs: needs: [test] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Install Rust ${{ env.toolchain_doc }} - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: ${{ env.toolchain_doc }} - override: true - - uses: Swatinem/rust-cache@v2 - - name: cargo rustdoc -p h3 -- -D intra-doc-link-resolution-failure - uses: actions-rs/cargo@v1 - with: - command: rustdoc - args: -p h3 -- -D intra-doc-link-resolution-failure + - run: cargo rustdoc -p h3 -- -D intra-doc-link-resolution-failure fuzz: name: Fuzz test needs: [test] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Install Rust ${{ env.toolchain_fuzz }} - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: ${{ env.toolchain_fuzz }} - override: true - - uses: Swatinem/rust-cache@v2 - name: Install cargo-fuzz uses: camshaft/install@v1 with: crate: cargo-fuzz - - name: cargo fuzz run fuzz_varint -- -runs=1 - uses: actions-rs/cargo@v1 - with: - command: fuzz - args: run fuzz_varint -- -runs=1 + - run: cargo fuzz run fuzz_varint -- -runs=1 compliance: name: Compliance report needs: [test] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 with: persist-credentials: false fetch-depth: 0 @@ -209,13 +161,10 @@ jobs: needs: [test] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Install Rust stable - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - name: Run server and client examples test run: ./ci/example_test.sh diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 2b34bcca..16446daa 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -19,13 +19,13 @@ quinn = { version = "0.11", default-features = false, features = [ "rustls", "ring", ] } -rcgen = { version = "0.13" } +rcgen = { version = "0.14" } rustls = { version = "0.23", default-features = false, features = [ "logging", "ring", "std", ] } -rustls-native-certs = "0.7" +rustls-native-certs = "0.8" structopt = "0.3" tokio = { version = "1.27", features = ["full"] } tracing = "0.1.37" diff --git a/examples/client.rs b/examples/client.rs index 4ac7e7c9..f91a340f 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -3,6 +3,7 @@ use std::{path::PathBuf, sync::Arc}; use futures::future; use h3::error::{ConnectionError, StreamError}; use rustls::pki_types::CertificateDer; +use rustls_native_certs::CertificateResult; use structopt::StructOpt; use tokio::io::AsyncWriteExt; use tracing::{error, info}; @@ -63,18 +64,15 @@ async fn main() -> Result<(), Box> { // load CA certificates stored in the system let mut roots = rustls::RootCertStore::empty(); - match rustls_native_certs::load_native_certs() { - Ok(certs) => { - for cert in certs { - if let Err(e) = roots.add(cert) { - error!("failed to parse trust anchor: {}", e); - } - } + let CertificateResult { certs, errors, .. } = rustls_native_certs::load_native_certs(); + for cert in certs { + if let Err(e) = roots.add(cert) { + error!("failed to parse trust anchor: {}", e); } - Err(e) => { - error!("couldn't load any default trust roots: {}", e); - } - }; + } + for e in errors { + error!("couldn't load default trust roots: {}", e); + } // load certificate of CA who issues the server certificate // NOTE that this should be used for dev only diff --git a/h3-datagram/src/datagram.rs b/h3-datagram/src/datagram.rs index 79d0853d..15f2ecd9 100644 --- a/h3-datagram/src/datagram.rs +++ b/h3-datagram/src/datagram.rs @@ -106,7 +106,7 @@ where fn chunk(&self) -> &[u8] { if self.len - self.pos > 0 { - return &self.stream_id[self.pos..self.len]; + &self.stream_id[self.pos..self.len] } else { self.payload.chunk() } diff --git a/h3-quinn/src/datagram.rs b/h3-quinn/src/datagram.rs index e073f077..497d02b5 100644 --- a/h3-quinn/src/datagram.rs +++ b/h3-quinn/src/datagram.rs @@ -31,7 +31,7 @@ impl SendDatagram for SendDatagramHandler { let mut buf: EncodedDatagram = data.into(); self.conn .send_datagram(buf.copy_to_bytes(buf.remaining())) - .map_err(|err| convert_send_datagram_error(err)) + .map_err(convert_send_datagram_error) } } @@ -49,7 +49,7 @@ impl RecvDatagram for RecvDatagramHandler { Poll::Ready( ready!(self.datagrams.poll_next_unpin(cx)) .expect("self. datagrams never returns None") - .map_err(|e| convert_connection_error(e)), + .map_err(convert_connection_error), ) } } @@ -90,9 +90,7 @@ fn convert_h3_error_to_datagram_error( ) -> h3_datagram::ConnectionErrorIncoming { match error { ConnectionErrorIncoming::ApplicationClose { error_code } => { - h3_datagram::ConnectionErrorIncoming::ApplicationClose { - error_code: error_code, - } + h3_datagram::ConnectionErrorIncoming::ApplicationClose { error_code } } ConnectionErrorIncoming::Timeout => h3_datagram::ConnectionErrorIncoming::Timeout, ConnectionErrorIncoming::InternalError(err) => { diff --git a/h3-quinn/src/lib.rs b/h3-quinn/src/lib.rs index 009f030c..29de7eb5 100644 --- a/h3-quinn/src/lib.rs +++ b/h3-quinn/src/lib.rs @@ -79,7 +79,7 @@ where ) -> Poll> { let (send, recv) = ready!(self.incoming_bi.poll_next_unpin(cx)) .expect("self.incoming_bi BoxStream never returns None") - .map_err(|e| convert_connection_error(e))?; + .map_err(convert_connection_error)?; Poll::Ready(Ok(Self::BidiStream { send: Self::SendStream::new(send), recv: Self::RecvStream::new(recv), @@ -93,7 +93,7 @@ where ) -> Poll> { let recv = ready!(self.incoming_uni.poll_next_unpin(cx)) .expect("self.incoming_uni BoxStream never returns None") - .map_err(|e| convert_connection_error(e))?; + .map_err(convert_connection_error)?; Poll::Ready(Ok(Self::RecvStream::new(recv))) } @@ -383,7 +383,7 @@ impl quic::RecvStream for RecvStream { let (stream, chunk) = ready!(self.read_chunk_fut.poll(cx)); self.stream = Some(stream); Poll::Ready(Ok(chunk - .map_err(|e| convert_read_error_to_stream_error(e))? + .map_err(convert_read_error_to_stream_error)? .map(|c| c.bytes))) } @@ -450,7 +450,7 @@ where { fn new(stream: quinn::SendStream) -> SendStream { Self { - stream: stream, + stream, writing: None, } } @@ -466,7 +466,7 @@ where while data.has_remaining() { let stream = Pin::new(&mut self.stream); let written = ready!(stream.poll_write(cx, data.chunk())) - .map_err(|err| convert_write_error_to_stream_error(err))?; + .map_err(convert_write_error_to_stream_error)?; data.advance(written); } } diff --git a/h3-webtransport/src/server.rs b/h3-webtransport/src/server.rs index 147b8181..b45e3ad7 100644 --- a/h3-webtransport/src/server.rs +++ b/h3-webtransport/src/server.rs @@ -171,7 +171,7 @@ where } /// Accept an incoming unidirectional stream from the client, it reads the stream until EOF. - pub fn accept_uni(&self) -> AcceptUni { + pub fn accept_uni(&self) -> AcceptUni<'_, C, B> { AcceptUni { conn: &self.server_conn, } @@ -219,7 +219,7 @@ where } /// Open a new bidirectional stream - pub fn open_bi(&self, session_id: SessionId) -> OpenBi { + pub fn open_bi(&self, session_id: SessionId) -> OpenBi<'_, C, B> { OpenBi { opener: &self.opener, stream: None, @@ -231,7 +231,7 @@ where } /// Open a new unidirectional stream - pub fn open_uni(&self, session_id: SessionId) -> OpenUni { + pub fn open_uni(&self, session_id: SessionId) -> OpenUni<'_, C, B> { OpenUni { opener: &self.opener, stream: None, diff --git a/h3/Cargo.toml b/h3/Cargo.toml index 6684e7e6..c6767a41 100644 --- a/h3/Cargo.toml +++ b/h3/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "h3" version = "0.0.8" -rust-version = "1.70" +rust-version = "1.74" authors = [ "Sean McArthur ", "Jean-Christophe BEGUE ", @@ -42,7 +42,7 @@ quinn = { version = "0.11", default-features = false, features = [ "ring", ] } quinn-proto = { version = "0.11", default-features = false } -rcgen = "0.13" +rcgen = "0.14" rustls = { version = "0.23", default-features = false, features = ["logging", "ring", "std"] } tokio = { version = "1", features = ["rt", "macros", "io-util", "io-std"] } tracing-subscriber = { version = "0.3", default-features = false, features = [ @@ -54,4 +54,4 @@ tracing-subscriber = { version = "0.3", default-features = false, features = [ ] } futures = { version = "0.3.28" } tokio-util = { version = "0.7.9" } -h3-datagram = {path = "../h3-datagram" } \ No newline at end of file +h3-datagram = {path = "../h3-datagram" } diff --git a/h3/src/buf.rs b/h3/src/buf.rs index c6c5617e..5196f815 100644 --- a/h3/src/buf.rs +++ b/h3/src/buf.rs @@ -22,7 +22,7 @@ impl BufList { self.bufs.push_back(buf); } - pub fn cursor(&self) -> Cursor { + pub fn cursor(&self) -> Cursor<'_, T> { Cursor { buf: self, pos_total: 0, diff --git a/h3/src/qpack/dynamic.rs b/h3/src/qpack/dynamic.rs index 542e0ccf..08e6d17e 100644 --- a/h3/src/qpack/dynamic.rs +++ b/h3/src/qpack/dynamic.rs @@ -258,11 +258,11 @@ impl DynamicTable { DynamicTable::default() } - pub fn decoder(&self, base: usize) -> DynamicTableDecoder { + pub fn decoder(&self, base: usize) -> DynamicTableDecoder<'_> { DynamicTableDecoder { table: self, base } } - pub fn encoder(&mut self, stream_id: u64) -> DynamicTableEncoder { + pub fn encoder(&mut self, stream_id: u64) -> DynamicTableEncoder<'_> { for (idx, field) in self.fields.iter().enumerate() { self.name_map .insert(field.name.clone(), self.vas.index(idx).unwrap()); diff --git a/h3/src/qpack/prefix_string/decode.rs b/h3/src/qpack/prefix_string/decode.rs index 4ee5d322..1ccddc96 100644 --- a/h3/src/qpack/prefix_string/decode.rs +++ b/h3/src/qpack/prefix_string/decode.rs @@ -312,11 +312,11 @@ impl<'a> Iterator for DecodeIter<'a> { } pub trait HpackStringDecode { - fn hpack_decode(&self) -> DecodeIter; + fn hpack_decode(&self) -> DecodeIter<'_>; } impl HpackStringDecode for Vec { - fn hpack_decode(&self) -> DecodeIter { + fn hpack_decode(&self) -> DecodeIter<'_> { DecodeIter { bit_pos: BitWindow::new(), content: self, diff --git a/h3/src/shared_state.rs b/h3/src/shared_state.rs index 98c149fb..00ad7f4b 100644 --- a/h3/src/shared_state.rs +++ b/h3/src/shared_state.rs @@ -67,7 +67,7 @@ pub trait ConnectionState { } /// Get the settings - fn settings(&self) -> Cow { + fn settings(&self) -> Cow<'_, Settings> { //= https://www.rfc-editor.org/rfc/rfc9114#section-7.2.4.2 //# Each endpoint SHOULD use //# these initial values to send messages before the peer's SETTINGS diff --git a/h3/src/stream.rs b/h3/src/stream.rs index fc9cea58..fd76322a 100644 --- a/h3/src/stream.rs +++ b/h3/src/stream.rs @@ -14,7 +14,7 @@ use crate::{ error::{internal_error::InternalConnectionError, Code}, frame::FrameStream, proto::{ - coding::{Decode as _, Encode}, + coding::Encode, frame::{Frame, Settings}, stream::StreamType, varint::VarInt, @@ -324,9 +324,9 @@ where Err(StreamErrorIncoming::StreamTerminated { error_code }) => { Some(StreamEnd::Reset(error_code)) } - Err(StreamErrorIncoming::Unknown(err)) => { + Err(StreamErrorIncoming::Unknown(_err)) => { #[cfg(feature = "tracing")] - tracing::error!("Unknown error when reading stream {}", err); + tracing::error!("Unknown error when reading stream {}", _err); Some(StreamEnd::Other) } @@ -383,6 +383,7 @@ where enum StreamEnd { EndOfStream, + #[allow(dead_code)] Reset(u64), // if the quic layer returns an unknown error Other, diff --git a/h3/src/tests/mod.rs b/h3/src/tests/mod.rs index 31d360c9..f9c742df 100644 --- a/h3/src/tests/mod.rs +++ b/h3/src/tests/mod.rs @@ -155,6 +155,6 @@ pub fn build_certs() -> (CertificateDer<'static>, PrivateKeyDer<'static>) { let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap(); ( cert.cert.into(), - PrivateKeyDer::Pkcs8(cert.key_pair.serialize_der().into()), + PrivateKeyDer::Pkcs8(cert.signing_key.serialize_der().into()), ) } From 8ede8167e50e73cf9818650a37c424343b5a5bcd Mon Sep 17 00:00:00 2001 From: Rene Leonhardt <65483435+reneleonhardt@users.noreply.github.com> Date: Sun, 28 Sep 2025 15:55:19 +0200 Subject: [PATCH 2/6] fix warnings --- h3/src/client/connection.rs | 1 - h3/src/client/stream.rs | 6 ++---- h3/src/connection.rs | 20 ++++++++------------ h3/src/error/connection_error_creators.rs | 7 +++---- h3/src/error/mod.rs | 1 + h3/src/qpack/vas.rs | 2 +- h3/src/server/connection.rs | 1 - h3/src/server/request.rs | 2 +- h3/src/shared_state.rs | 2 +- h3/src/stream.rs | 18 +++++++----------- 10 files changed, 24 insertions(+), 36 deletions(-) diff --git a/h3/src/client/connection.rs b/h3/src/client/connection.rs index 4090d021..82b800e3 100644 --- a/h3/src/client/connection.rs +++ b/h3/src/client/connection.rs @@ -419,7 +419,6 @@ where Ok(Frame::Settings(_)) => { #[cfg(feature = "tracing")] trace!("Got settings"); - () } Ok(Frame::Goaway(id)) => { diff --git a/h3/src/client/stream.rs b/h3/src/client/stream.rs index ef64de77..bba0e2b5 100644 --- a/h3/src/client/stream.rs +++ b/h3/src/client/stream.rs @@ -212,10 +212,8 @@ where cx: &mut Context<'_>, ) -> Poll, StreamError>> { let res = self.inner.poll_recv_trailers(cx); - if let Poll::Ready(Err(e)) = &res { - if let StreamError::HeaderTooBig { .. } = e { - self.inner.stream.stop_sending(Code::H3_REQUEST_CANCELLED); - } + if let Poll::Ready(Err(StreamError::HeaderTooBig { .. })) = &res { + self.inner.stream.stop_sending(Code::H3_REQUEST_CANCELLED); } res } diff --git a/h3/src/connection.rs b/h3/src/connection.rs index 275e4c98..25ab6b03 100644 --- a/h3/src/connection.rs +++ b/h3/src/connection.rs @@ -304,7 +304,7 @@ where let mut conn_inner = Self { shared, conn, - control_send: control_send, + control_send, control_recv: None, qpack_streams, handled_connection_error: None, @@ -399,17 +399,13 @@ where let _ = self.poll_connection_error(cx)?; // Get all currently pending streams - loop { - match self - .conn - .poll_accept_recv(cx) - .map_err(|e| self.handle_connection_error(e))? - { - Poll::Ready(stream) => self - .pending_recv_streams - .push(Some(AcceptRecvStream::new(stream))), - Poll::Pending => break, - } + while let Poll::Ready(stream) = self + .conn + .poll_accept_recv(cx) + .map_err(|e| self.handle_connection_error(e))? + { + self.pending_recv_streams + .push(Some(AcceptRecvStream::new(stream))) } for stream in self.pending_recv_streams.iter_mut().filter(|s| s.is_some()) { diff --git a/h3/src/error/connection_error_creators.rs b/h3/src/error/connection_error_creators.rs index 0d729ef5..93193e20 100644 --- a/h3/src/error/connection_error_creators.rs +++ b/h3/src/error/connection_error_creators.rs @@ -85,7 +85,7 @@ where } /// Close the connection - pub fn close_connection(&mut self, code: Code, reason: String) -> () { + pub fn close_connection(&mut self, code: Code, reason: String) { self.conn.close(code, reason.as_bytes()) } } @@ -151,8 +151,7 @@ pub(crate) trait CloseRawQuicConnection: quic::Connection { reason: reason.to_string(), }; self.close(Code::H3_INTERNAL_ERROR, reason.as_bytes()); - let conn_error = ConnectionError::Local { error: local_error }; - conn_error + ConnectionError::Local { error: local_error } } _ => ConnectionError::Remote(error), } @@ -196,7 +195,7 @@ where match error { FrameStreamError::Quic(error) => self.handle_quic_stream_error(error), FrameStreamError::Proto(frame_error) => self.handle_connection_error_on_stream( - InternalConnectionError::got_frame_error(frame_error).into(), + InternalConnectionError::got_frame_error(frame_error), ), FrameStreamError::UnexpectedEnd => { self.handle_connection_error_on_stream(InternalConnectionError::new( diff --git a/h3/src/error/mod.rs b/h3/src/error/mod.rs index f26cf0be..11e391ea 100644 --- a/h3/src/error/mod.rs +++ b/h3/src/error/mod.rs @@ -12,6 +12,7 @@ pub mod internal_error; #[cfg(not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))] pub(crate) mod internal_error; +#[allow(clippy::module_inception)] mod error; pub use codes::Code; diff --git a/h3/src/qpack/vas.rs b/h3/src/qpack/vas.rs index 5fccbfef..8bfe8234 100644 --- a/h3/src/qpack/vas.rs +++ b/h3/src/qpack/vas.rs @@ -1,4 +1,4 @@ -/** +/* * https://www.rfc-editor.org/rfc/rfc9204.html#name-absolute-indexing * https://www.rfc-editor.org/rfc/rfc9204.html#name-relative-indexing * https://www.rfc-editor.org/rfc/rfc9204.html#name-post-base-indexing diff --git a/h3/src/server/connection.rs b/h3/src/server/connection.rs index ef374a20..3e52e9d2 100644 --- a/h3/src/server/connection.rs +++ b/h3/src/server/connection.rs @@ -237,7 +237,6 @@ where Frame::Settings(_setting) => { #[cfg(feature = "tracing")] trace!("Got settings > {:?}", _setting); - () } &Frame::Goaway(id) => self.inner.process_goaway(&mut self.recv_closing, id)?, _frame @ Frame::MaxPushId(_) | _frame @ Frame::CancelPush(_) => { diff --git a/h3/src/server/request.rs b/h3/src/server/request.rs index ecc20868..6f241c52 100644 --- a/h3/src/server/request.rs +++ b/h3/src/server/request.rs @@ -71,7 +71,7 @@ where ) -> Result<(Request<()>, RequestStream), StreamError> { let frame = std::future::poll_fn(|cx| self.frame_stream.poll_next(cx)).await; let req = self.accept_with_frame(frame)?; - Ok(req.resolve().await?) + req.resolve().await } /// Accepts a http request where the first frame has already been read and decoded. diff --git a/h3/src/shared_state.rs b/h3/src/shared_state.rs index 00ad7f4b..2b8f08cd 100644 --- a/h3/src/shared_state.rs +++ b/h3/src/shared_state.rs @@ -76,7 +76,7 @@ pub trait ConnectionState { self.shared_state() .settings .get() - .map(|s| Cow::Borrowed(s)) + .map(Cow::Borrowed) .unwrap_or_default() } /// Set the connection to closing diff --git a/h3/src/stream.rs b/h3/src/stream.rs index fd76322a..ff6fdd52 100644 --- a/h3/src/stream.rs +++ b/h3/src/stream.rs @@ -604,7 +604,7 @@ where // If there is data available *do not* poll for more data, as that may suspend indefinitely // if no more data is sent, causing data loss. if !p.has_remaining() { - let eos = ready!(p.poll_read(cx).map_err(|err| convert_to_std_io_error(err)))?; + let eos = ready!(p.poll_read(cx).map_err(convert_to_std_io_error))?; if eos { return Poll::Ready(Ok(0)); } @@ -639,7 +639,7 @@ where // If there is data available *do not* poll for more data, as that may suspend indefinitely // if no more data is sent, causing data loss. if !p.has_remaining() { - let eos = ready!(p.poll_read(cx).map_err(|err| convert_to_std_io_error(err)))?; + let eos = ready!(p.poll_read(cx).map_err(convert_to_std_io_error))?; if eos { return Poll::Ready(Ok(())); } @@ -668,8 +668,7 @@ where mut buf: &[u8], ) -> Poll> { let p = &mut *self; - p.poll_send(cx, &mut buf) - .map_err(|err| convert_to_std_io_error(err)) + p.poll_send(cx, &mut buf).map_err(convert_to_std_io_error) } fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { @@ -678,8 +677,7 @@ where fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let p = &mut *self; - p.poll_finish(cx) - .map_err(|err| convert_to_std_io_error(err)) + p.poll_finish(cx).map_err(convert_to_std_io_error) } } @@ -694,8 +692,7 @@ where mut buf: &[u8], ) -> Poll> { let p = &mut *self; - p.poll_send(cx, &mut buf) - .map_err(|err| convert_to_std_io_error(err)) + p.poll_send(cx, &mut buf).map_err(convert_to_std_io_error) } fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { @@ -704,13 +701,12 @@ where fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let p = &mut *self; - p.poll_finish(cx) - .map_err(|err| convert_to_std_io_error(err)) + p.poll_finish(cx).map_err(convert_to_std_io_error) } } fn convert_to_std_io_error(error: StreamErrorIncoming) -> std::io::Error { - std::io::Error::new(std::io::ErrorKind::Other, error) + std::io::Error::other(error) } #[cfg(test)] From f05262e4cd61b5bc0dc73a21fd046d70759ceec9 Mon Sep 17 00:00:00 2001 From: Rene Leonhardt <65483435+reneleonhardt@users.noreply.github.com> Date: Sun, 28 Sep 2025 17:57:45 +0200 Subject: [PATCH 3/6] remove bits_decode casting --- h3/src/qpack/prefix_string/decode.rs | 88 ++++++++++++++-------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/h3/src/qpack/prefix_string/decode.rs b/h3/src/qpack/prefix_string/decode.rs index 1ccddc96..c05887a3 100644 --- a/h3/src/qpack/prefix_string/decode.rs +++ b/h3/src/qpack/prefix_string/decode.rs @@ -108,7 +108,7 @@ macro_rules! bits_decode { HuffmanDecoder { lookup: $count, table: &[ - $( DecodeValue::Sym($sym as u8), )* + $( DecodeValue::Sym($sym), )* $( DecodeValue::Partial(&$sub), )* ] } @@ -118,8 +118,8 @@ macro_rules! bits_decode { HuffmanDecoder { lookup: 1, table: &[ - DecodeValue::Sym($first as u8), - DecodeValue::Sym($second as u8), + DecodeValue::Sym($first), + DecodeValue::Sym($second), ] } }; @@ -128,10 +128,10 @@ macro_rules! bits_decode { HuffmanDecoder { lookup: 2, table: &[ - DecodeValue::Sym($first as u8), - DecodeValue::Sym($second as u8), - DecodeValue::Sym($third as u8), - DecodeValue::Sym($fourth as u8), + DecodeValue::Sym($first), + DecodeValue::Sym($second), + DecodeValue::Sym($third), + DecodeValue::Sym($fourth), ] } }; @@ -140,7 +140,7 @@ macro_rules! bits_decode { HuffmanDecoder { lookup: 1, table: &[ - DecodeValue::Sym($first as u8), + DecodeValue::Sym($first), DecodeValue::Partial(&$second), ] } @@ -176,7 +176,7 @@ macro_rules! bits_decode { #[rustfmt::skip] bits_decode![ HPACK_STRING => ( - lookup: 5, [ '0', '1', '2', 'a', 'c', 'e', 'i', 'o', 's', 't', + lookup: 5, [ b'0', b'1', b'2', b'a', b'c', b'e', b'i', b'o', b's', b't', => END0_01010, => END0_01011, => END0_01100, => END0_01101, => END0_01110, => END0_01111, => END0_10000, => END0_10001, => END0_10010, => END0_10011, => END0_10100, => END0_10101, @@ -184,46 +184,46 @@ bits_decode![ => END0_11010, => END0_11011, => END0_11100, => END0_11101, => END0_11110, => END0_11111, ]), - END0_01010 => ( 32, '%'), - END0_01011 => ('-', '.'), - END0_01100 => ('/', '3'), - END0_01101 => ('4', '5'), - END0_01110 => ('6', '7'), - END0_01111 => ('8', '9'), - END0_10000 => ('=', 'A'), - END0_10001 => ('_', 'b'), - END0_10010 => ('d', 'f'), - END0_10011 => ('g', 'h'), - END0_10100 => ('l', 'm'), - END0_10101 => ('n', 'p'), - END0_10110 => ('r', 'u'), - END0_10111 => (':', 'B', 'C', 'D'), - END0_11000 => ('E', 'F', 'G', 'H'), - END0_11001 => ('I', 'J', 'K', 'L'), - END0_11010 => ('M', 'N', 'O', 'P'), - END0_11011 => ('Q', 'R', 'S', 'T'), - END0_11100 => ('U', 'V', 'W', 'Y'), - END0_11101 => ('j', 'k', 'q', 'v'), - END0_11110 => ('w', 'x', 'y', 'z'), + END0_01010 => ( 32 , b'%'), + END0_01011 => (b'-' , b'.'), + END0_01100 => (b'/' , b'3'), + END0_01101 => (b'4' , b'5'), + END0_01110 => (b'6' , b'7'), + END0_01111 => (b'8' , b'9'), + END0_10000 => (b'=' , b'A'), + END0_10001 => (b'_' , b'b'), + END0_10010 => (b'd' , b'f'), + END0_10011 => (b'g' , b'h'), + END0_10100 => (b'l' , b'm'), + END0_10101 => (b'n' , b'p'), + END0_10110 => (b'r' , b'u'), + END0_10111 => (b':', b'B', b'C', b'D'), + END0_11000 => (b'E', b'F', b'G', b'H'), + END0_11001 => (b'I', b'J', b'K', b'L'), + END0_11010 => (b'M', b'N', b'O', b'P'), + END0_11011 => (b'Q', b'R', b'S', b'T'), + END0_11100 => (b'U', b'V', b'W', b'Y'), + END0_11101 => (b'j', b'k', b'q', b'v'), + END0_11110 => (b'w', b'x', b'y', b'z'), END0_11111 => (=> END5_00, => END5_01, => END5_10, => END5_11), - END5_00 => ('&', '*'), - END5_01 => (',', 59), - END5_10 => ('X', 'Z'), + END5_00 => (b'&' , b'*'), + END5_01 => (b',', 59), + END5_10 => (b'X' , b'Z'), END5_11 => (=> END7_0, => END7_1), - END7_0 => ('!', '"', '(', ')'), + END7_0 => (b'!', b'"', b'(', b')'), END7_1 => (=> END8_0, => END8_1), - END8_0 => ('?', => END9A_1), - END9A_1 => ('\'', '+'), - END8_1 => (lookup: 2, ['|', => END9B_01, => END9B_10, => END9B_11,]), - END9B_01 => ('#', '>'), - END9B_10 => (0, '$', '@', '['), - END9B_11 => (lookup: 2, [']', '~', => END13_10, => END13_11,]), - END13_10 => ('^', '}'), + END8_0 => (b'?', => END9A_1), + END9A_1 => (b'\'' , b'+'), + END8_1 => (lookup: 2, [b'|', => END9B_01, => END9B_10, => END9B_11,]), + END9B_01 => (b'#' , b'>'), + END9B_10 => (0, b'$', b'@', b'['), + END9B_11 => (lookup: 2, [b']', b'~', => END13_10, => END13_11,]), + END13_10 => (b'^', b'}'), END13_11 => (=> END14_0, => END14_1), - END14_0 => ('<', '`'), - END14_1 => ('{', => END15_1), + END14_0 => (b'<', b'`'), + END14_1 => (b'{', => END15_1), END15_1 => - (lookup: 4, [ '\\', 195, 208, => END19_0011, + (lookup: 4, [ b'\\', 195, 208, => END19_0011, => END19_0100, => END19_0101, => END19_0110, => END19_0111, => END19_1000, => END19_1001, => END19_1010, => END19_1011, => END19_1100, => END19_1101, => END19_1110, => END19_1111, From 720cffb1862352d58a322359e2ccd059a1d87bfc Mon Sep 17 00:00:00 2001 From: Rene Leonhardt <65483435+reneleonhardt@users.noreply.github.com> Date: Sun, 28 Sep 2025 18:28:08 +0200 Subject: [PATCH 4/6] suppress manual_is_multiple_of --- h3-datagram/src/datagram.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/h3-datagram/src/datagram.rs b/h3-datagram/src/datagram.rs index 15f2ecd9..6516df58 100644 --- a/h3-datagram/src/datagram.rs +++ b/h3-datagram/src/datagram.rs @@ -20,6 +20,8 @@ where B: Buf, { /// Creates a new datagram frame + // TODO: remove for MSRV >= 1.87 https://github.com/rust-lang/rust/issues/128101 + #[allow(unknown_lints, clippy::manual_is_multiple_of)] pub fn new(stream_id: StreamId, payload: B) -> Self { assert!( stream_id.into_inner() % 4 == 0, From ef66a148c0501742f278ba099e6979c03710c3c0 Mon Sep 17 00:00:00 2001 From: Rene Leonhardt <65483435+reneleonhardt@users.noreply.github.com> Date: Sun, 28 Sep 2025 19:12:49 +0200 Subject: [PATCH 5/6] suppress more warnings --- .github/workflows/CI.yml | 2 ++ h3-webtransport/src/server.rs | 1 + h3/src/proto/coding.rs | 4 ++++ h3/src/proto/varint.rs | 2 ++ h3/src/server/request.rs | 2 ++ 5 files changed, 11 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 72da4421..1167b0ba 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -110,6 +110,8 @@ jobs: toolchain: ${{ matrix.toolchain }} target: ${{ matrix.target }} - run: cargo test --features ${{ matrix.features }} --target ${{ matrix.target }} + env: #[cfg(feature = "datagram")] unexpected `cfg` condition value: `datagram` + RUSTFLAGS: "-A unexpected_cfgs" - name: h3Spec run: ./ci/h3spec.sh if: matrix.toolchain == 'stable' diff --git a/h3-webtransport/src/server.rs b/h3-webtransport/src/server.rs index b45e3ad7..fa28f1e1 100644 --- a/h3-webtransport/src/server.rs +++ b/h3-webtransport/src/server.rs @@ -368,6 +368,7 @@ where /// An accepted incoming bidirectional stream. /// /// Since +#[allow(clippy::large_enum_variant)] pub enum AcceptedBi, B: Buf> { /// An incoming bidirectional stream BidiStream(SessionId, BidiStream), diff --git a/h3/src/proto/coding.rs b/h3/src/proto/coding.rs index 5ddd4d88..7bdcd428 100644 --- a/h3/src/proto/coding.rs +++ b/h3/src/proto/coding.rs @@ -36,7 +36,9 @@ impl Decode for u8 { } pub trait BufExt { + #[allow(dead_code)] fn get(&mut self) -> Result; + #[allow(dead_code)] fn get_var(&mut self) -> Result; } @@ -51,7 +53,9 @@ impl BufExt for T { } pub trait BufMutExt { + #[allow(dead_code)] fn write(&mut self, x: T); + #[allow(dead_code)] fn write_var(&mut self, x: u64); } diff --git a/h3/src/proto/varint.rs b/h3/src/proto/varint.rs index 60cdacf5..7afa981e 100644 --- a/h3/src/proto/varint.rs +++ b/h3/src/proto/varint.rs @@ -180,6 +180,7 @@ impl fmt::Display for VarInt { } pub trait BufExt { + #[allow(dead_code)] fn get_var(&mut self) -> Result; } @@ -190,6 +191,7 @@ impl BufExt for T { } pub trait BufMutExt { + #[allow(dead_code)] fn write_var(&mut self, x: u64); } diff --git a/h3/src/server/request.rs b/h3/src/server/request.rs index 6f241c52..0b3588aa 100644 --- a/h3/src/server/request.rs +++ b/h3/src/server/request.rs @@ -66,6 +66,7 @@ where { /// Returns a future to await the request headers and return a `Request` object #[cfg_attr(feature = "tracing", instrument(skip_all, level = "trace"))] + #[allow(clippy::type_complexity)] pub async fn resolve_request( mut self, ) -> Result<(Request<()>, RequestStream), StreamError> { @@ -192,6 +193,7 @@ where /// Finishes the resolution of the request #[cfg_attr(feature = "tracing", instrument(skip_all, level = "trace"))] + #[allow(clippy::type_complexity)] pub async fn resolve( mut self, ) -> Result<(Request<()>, RequestStream), StreamError> { From 373a99c15dd20651bab4ad4f969022c5cd798926 Mon Sep 17 00:00:00 2001 From: Rene Leonhardt <65483435+reneleonhardt@users.noreply.github.com> Date: Tue, 7 Oct 2025 17:29:29 +0200 Subject: [PATCH 6/6] review: add todos --- h3-webtransport/src/server.rs | 1 + h3/src/error/mod.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/h3-webtransport/src/server.rs b/h3-webtransport/src/server.rs index fa28f1e1..8d472267 100644 --- a/h3-webtransport/src/server.rs +++ b/h3-webtransport/src/server.rs @@ -368,6 +368,7 @@ where /// An accepted incoming bidirectional stream. /// /// Since +// Todo #[allow(clippy::large_enum_variant)] pub enum AcceptedBi, B: Buf> { /// An incoming bidirectional stream diff --git a/h3/src/error/mod.rs b/h3/src/error/mod.rs index 11e391ea..e6e90840 100644 --- a/h3/src/error/mod.rs +++ b/h3/src/error/mod.rs @@ -12,6 +12,7 @@ pub mod internal_error; #[cfg(not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))] pub(crate) mod internal_error; +// Todo better module names #[allow(clippy::module_inception)] mod error;