From 2bb118fce16f2d5a1a85fce96d228acc23df827e Mon Sep 17 00:00:00 2001 From: Sam Scott Date: Sun, 7 Apr 2024 15:23:28 -0500 Subject: [PATCH] Fix MSRV (#99) * Remove `then_some` to stay compatible with earlier versions of Rust * Fix CI builds to build on old versions of Rust * Trying 1.61 --- .github/workflows/ci.yml | 22 ++++++++++++++-------- Cargo.toml | 4 ++-- src/actix.rs | 17 +++++------------ src/ser.rs | 15 +++++---------- tests/test_actix.rs | 6 +++--- tests/test_deserialize.rs | 2 +- tests/test_warp.rs | 6 +++--- 7 files changed, 33 insertions(+), 39 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 373269f..9034936 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,15 +10,13 @@ jobs: matrix: rust: - stable - - 1.36.0 + - 1.61.0 steps: - uses: actions/checkout@v2 - name: Install Rust stable toolchain - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: stable - override: true components: rustfmt, clippy - name: Check Rust formatting uses: actions-rs/cargo@v1 @@ -38,13 +36,22 @@ jobs: matrix: rust: - stable - - 1.36.0 + - 1.61.0 feature: - "" - actix4 - actix3 - warp - axum + exclude: + - rust: 1.61.0 + feature: actix4 + - rust: 1.61.0 + feature: actix3 + - rust: 1.61.0 + feature: warp + - rust: 1.61.0 + feature: axum steps: - uses: actions/checkout@v2 - uses: actions/cache@v2 @@ -55,10 +62,9 @@ jobs: target key: ${{ runner.os }}-cargo-test-${{ hashFiles('Cargo.toml') }} - name: Install Rust stable toolchain - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@master with: - profile: minimal - toolchain: stable + toolchain: ${{ matrix.rust }} - name: Run test ${{ matrix.feature }} run: | cargo test --all-targets --features "${{ matrix.feature }}" diff --git a/Cargo.toml b/Cargo.toml index 8293f82..1e388aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ name = "serde_qs" repository = "https://github.com/samscott89/serde_qs" readme = "README.md" version = "0.13.0" -rust-version = "1.36" +rust-version = "1.61" [dependencies] actix-web4 = { version = "4.0", optional = true, package = "actix-web", default-features = false } @@ -25,7 +25,7 @@ axum-framework = { package = "axum", version = "0.7", default-features = false, [dev-dependencies] chrono = { version = "0.4", features = ["serde"] } -csv = "1.1" +csv = "1.3" rand = "0.8" serde_derive = "1.0" serde_urlencoded = "0.7" diff --git a/src/actix.rs b/src/actix.rs index 176ce7d..02e9ae8 100644 --- a/src/actix.rs +++ b/src/actix.rs @@ -134,6 +134,8 @@ where } } +type ActixErrorHandler = Option ActixError + Send + Sync>>; + /// Query extractor configuration /// /// ```rust @@ -173,9 +175,9 @@ where /// ); /// } /// ``` -#[derive(Clone)] +#[derive(Clone, Default)] pub struct QsQueryConfig { - ehandler: Option ActixError + Send + Sync>>, + ehandler: ActixErrorHandler, qs_config: QsConfig, } @@ -201,15 +203,6 @@ impl QsQueryConfig { } } -impl Default for QsQueryConfig { - fn default() -> Self { - QsQueryConfig { - ehandler: None, - qs_config: QsConfig::default(), - } - } -} - #[derive(PartialEq, Eq, PartialOrd, Ord)] /// Extract typed information from from the request's form data. /// @@ -230,7 +223,7 @@ impl Default for QsQueryConfig { /// } /// /// // Use `QsForm` extractor for Form information. -/// // Content-Type: application/x-www-form-urlencoded +/// // Content-Type: application/x-www-form-urlencoded /// // The correct request payload for this handler would be `id[]=1124&id[]=88` /// async fn filter_users(info: QsForm) -> HttpResponse { /// HttpResponse::Ok().body( diff --git a/src/ser.rs b/src/ser.rs index 607fa0d..5198d71 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -279,7 +279,7 @@ impl<'a, W: 'a + Write> QsSerializer<'a, W> { write!( self.writer, "{}{}={}", - amp.then_some("&").unwrap_or_default(), + if amp { "&" } else { "" }, key, percent_encode(value, QS_ENCODE_SET) .map(replace_space) @@ -294,16 +294,11 @@ impl<'a, W: 'a + Write> QsSerializer<'a, W> { fn write_unit(&mut self) -> Result<()> { let amp = !self.first.swap(false, Ordering::Relaxed); if let Some(ref key) = self.key { - write!( - self.writer, - "{}{}=", - amp.then_some("&").unwrap_or_default(), - key, - ) - .map_err(Error::from) + write!(self.writer, "{}{}=", if amp { "&" } else { "" }, key,).map_err(Error::from) + } else if amp { + write!(self.writer, "&").map_err(Error::from) } else { - // For top level unit types - write!(self.writer, "{}", amp.then_some("&").unwrap_or_default(),).map_err(Error::from) + Ok(()) } } diff --git a/tests/test_actix.rs b/tests/test_actix.rs index 48ad27f..dcc5980 100644 --- a/tests/test_actix.rs +++ b/tests/test_actix.rs @@ -26,7 +26,7 @@ where S: std::str::FromStr, { let s = <&str as serde::Deserialize>::deserialize(deserializer)?; - S::from_str(&s).map_err(|_| D::Error::custom("could not parse string")) + S::from_str(s).map_err(|_| D::Error::custom("could not parse string")) } #[derive(Deserialize, Serialize, Debug, PartialEq)] @@ -103,7 +103,7 @@ fn test_composite_querystring_extractor() { assert_eq!(s.bars, vec![0, 1]); assert_eq!(s.common.limit, 100); assert_eq!(s.common.offset, 50); - assert_eq!(s.common.remaining, true); + assert!(s.common.remaining); }) } @@ -140,7 +140,7 @@ fn test_custom_qs_config() { assert_eq!(s.bars, vec![3]); assert_eq!(s.common.limit, 100); assert_eq!(s.common.offset, 50); - assert_eq!(s.common.remaining, true); + assert!(s.common.remaining); }) } diff --git a/tests/test_deserialize.rs b/tests/test_deserialize.rs index cbe2019..7d424cc 100644 --- a/tests/test_deserialize.rs +++ b/tests/test_deserialize.rs @@ -81,7 +81,7 @@ fn deserialize_struct() { user_ids: vec![1, 2, 3, 4], }; - for config in vec![qs::Config::new(5, true), qs::Config::new(5, false)] { + for config in [qs::Config::new(5, true), qs::Config::new(5, false)] { // standard parameters let rec_params: QueryParams = config .deserialize_str( diff --git a/tests/test_warp.rs b/tests/test_warp.rs index 76bfd80..ca56ded 100644 --- a/tests/test_warp.rs +++ b/tests/test_warp.rs @@ -17,7 +17,7 @@ where S: std::str::FromStr, { let s = <&str as serde::Deserialize>::deserialize(deserializer)?; - S::from_str(&s).map_err(|_| D::Error::custom("could not parse string")) + S::from_str(s).map_err(|_| D::Error::custom("could not parse string")) } #[derive(Deserialize, Serialize, Debug, PartialEq)] @@ -65,7 +65,7 @@ fn test_composite_querystring_extractor() { assert_eq!(s.bars, vec![0, 1]); assert_eq!(s.common.limit, 100); assert_eq!(s.common.offset, 50); - assert_eq!(s.common.remaining, true); + assert!(s.common.remaining); }) } @@ -99,6 +99,6 @@ fn test_custom_qs_config() { assert_eq!(s.bars, vec![3]); assert_eq!(s.common.limit, 100); assert_eq!(s.common.offset, 50); - assert_eq!(s.common.remaining, true); + assert!(s.common.remaining); }) }