From 7c8a67d3c8fb64b35bd77c0d5f2f47bdce5d5734 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Tue, 23 Dec 2025 09:28:07 +0100 Subject: [PATCH] Remove bincode, add postcard for etag calculation --- Cargo.lock | 117 ++++++++++++------ Cargo.toml | 5 +- crates/lib/docs_rs_cargo_metadata/Cargo.toml | 1 - .../docs_rs_cargo_metadata/src/metadata.rs | 41 ++---- .../src/release_dependency.rs | 2 +- .../lib/docs_rs_headers/src/canonical_url.rs | 12 +- crates/lib/docs_rs_registry_api/Cargo.toml | 1 - crates/lib/docs_rs_registry_api/src/models.rs | 12 +- crates/lib/docs_rs_types/Cargo.toml | 5 +- crates/lib/docs_rs_types/src/krate_name.rs | 12 +- crates/lib/docs_rs_types/src/req_version.rs | 26 +--- crates/lib/docs_rs_types/src/version.rs | 21 ---- crates/lib/docs_rs_uri/Cargo.toml | 2 +- crates/lib/docs_rs_uri/src/escaped_uri.rs | 20 +-- src/build_queue.rs | 3 +- src/docbuilder/limits.rs | 3 +- src/docbuilder/rustwide_builder.rs | 4 +- src/test/fakes.rs | 10 +- src/web/build_details.rs | 2 +- src/web/crate_details.rs | 10 +- src/web/extractors/rustdoc.rs | 8 +- src/web/features.rs | 16 +-- src/web/licenses.rs | 3 +- src/web/mod.rs | 2 +- src/web/releases.rs | 6 +- src/web/rustdoc.rs | 46 ++----- 26 files changed, 143 insertions(+), 247 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e2b5214ad..27cb7275d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -422,6 +422,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -986,26 +995,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bincode" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" -dependencies = [ - "bincode_derive", - "serde", - "unty", -] - -[[package]] -name = "bincode_derive" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" -dependencies = [ - "virtue", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -1244,6 +1233,15 @@ dependencies = [ "cc", ] +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.17", +] + [[package]] name = "codemap" version = "0.1.3" @@ -1490,6 +1488,12 @@ dependencies = [ "itertools 0.13.0", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crossbeam-channel" version = "0.5.15" @@ -1908,7 +1912,6 @@ dependencies = [ "axum", "axum-extra", "base64", - "bincode 2.0.1", "chrono", "clap", "comrak", @@ -1953,6 +1956,7 @@ dependencies = [ "opentelemetry_sdk", "phf 0.13.1", "phf_codegen 0.13.1", + "postcard", "pretty_assertions", "rand 0.9.2", "rayon", @@ -1987,7 +1991,6 @@ name = "docs_rs_cargo_metadata" version = "0.1.0" dependencies = [ "anyhow", - "bincode 2.0.1", "derive_more 2.1.0", "docs_rs_types", "serde", @@ -2106,7 +2109,6 @@ name = "docs_rs_registry_api" version = "0.1.0" dependencies = [ "anyhow", - "bincode 2.0.1", "chrono", "docs_rs_env_vars", "docs_rs_types", @@ -2188,7 +2190,6 @@ name = "docs_rs_types" version = "0.1.0" dependencies = [ "anyhow", - "bincode 2.0.1", "crates_io_validation", "derive_more 2.1.0", "semver", @@ -2206,9 +2207,9 @@ version = "0.1.0" dependencies = [ "anyhow", "askama", - "bincode 2.0.1", "http 1.4.0", "percent-encoding", + "serde_with", "test-case", "url", ] @@ -2308,6 +2309,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "encoding_rs" version = "0.8.35" @@ -2367,7 +2380,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7223ae2d2f179b803433d9c830478527e92b8117eab39460edae7f1614d9fb73" dependencies = [ - "heapless", + "heapless 0.8.0", "serde", ] @@ -4163,6 +4176,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hash32" version = "0.3.1" @@ -4243,13 +4265,27 @@ dependencies = [ "http 1.4.0", ] +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version", + "serde", + "spin", + "stable_deref_trait", +] + [[package]] name = "heapless" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "hash32", + "hash32 0.3.1", "stable_deref_trait", ] @@ -6057,6 +6093,19 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "heapless 0.7.17", + "serde", +] + [[package]] name = "potential_utf" version = "0.1.4" @@ -7589,7 +7638,7 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "656b45c05d95a5704399aeef6bd0ddec7b2b3531b7c9e900abbf7c4d2190c925" dependencies = [ - "bincode 1.3.3", + "bincode", "flate2", "fnv", "once_cell", @@ -8270,12 +8319,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "unty" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" - [[package]] name = "ureq" version = "3.1.4" @@ -8370,12 +8413,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "virtue" -version = "0.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" - [[package]] name = "vsimd" version = "0.8.0" diff --git a/Cargo.toml b/Cargo.toml index b4dd4f9b0..6bfff65e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,6 @@ anyhow = { version = "1.0.42", features = ["backtrace"]} askama = "0.14.0" async-stream = "0.3.5" axum-extra = { version = "0.12.0", features = ["typed-header", "routing", "middleware"] } -bincode = "~2" # bincode is unmaintained, and 3.0 is just a breaking notification chrono = { version = "0.4.11", default-features = false, features = ["clock", "serde"] } derive_more = { version = "2.0.0", features = ["display", "deref", "from", "into", "from_str"] } futures-util = "0.3.5" @@ -37,12 +36,14 @@ opentelemetry = "0.31.0" opentelemetry-otlp = { version = "0.31.0", features = ["grpc-tonic", "metrics"] } opentelemetry-resource-detectors = "0.10.0" opentelemetry_sdk = { version = "0.31.0", features = ["rt-tokio"] } +postcard = { version = "1.1.3", features = ["use-std"] } rand = "0.9" regex = "1" reqwest = { version = "0.12", features = ["json", "gzip"] } sentry = { version = "0.46.0", features = ["panic", "tracing", "tower-http", "anyhow", "backtrace"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +serde_with = "3.4.0" sqlx = { version = "0.8", features = [ "runtime-tokio", "postgres", "sqlite", "chrono" ] } strum = { version = "0.27.0", features = ["derive"] } tempfile = "3.1.0" @@ -112,7 +113,7 @@ http = { workspace = true } # Data serialization and deserialization serde = { workspace = true } serde_json = { workspace = true } -bincode = { workspace = true } +postcard = { workspace = true } # axum dependencies axum = { version = "0.8.1", features = ["macros"] } diff --git a/crates/lib/docs_rs_cargo_metadata/Cargo.toml b/crates/lib/docs_rs_cargo_metadata/Cargo.toml index 6db8beb92..d326461f9 100644 --- a/crates/lib/docs_rs_cargo_metadata/Cargo.toml +++ b/crates/lib/docs_rs_cargo_metadata/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] anyhow = { workspace = true } -bincode = { workspace = true } derive_more = { workspace = true } docs_rs_types = { path = "../docs_rs_types" } serde = { workspace = true } diff --git a/crates/lib/docs_rs_cargo_metadata/src/metadata.rs b/crates/lib/docs_rs_cargo_metadata/src/metadata.rs index 2c18cf93b..347f3dd05 100644 --- a/crates/lib/docs_rs_cargo_metadata/src/metadata.rs +++ b/crates/lib/docs_rs_cargo_metadata/src/metadata.rs @@ -1,7 +1,7 @@ use anyhow::{Context, Result}; use docs_rs_types::{Version, VersionReq}; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; +use std::collections::BTreeMap; pub struct CargoMetadata { root: Package, @@ -39,7 +39,7 @@ impl CargoMetadata { } } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize)] pub struct Package { pub id: String, pub name: String, @@ -53,7 +53,7 @@ pub struct Package { pub targets: Vec, pub readme: Option, pub keywords: Vec, - pub features: HashMap>, + pub features: BTreeMap>, } impl Package { @@ -86,7 +86,7 @@ impl Package { } } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize)] pub struct Target { pub name: String, #[cfg(not(feature = "testing"))] @@ -107,7 +107,7 @@ impl Target { } } -#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct Dependency { pub name: String, pub req: VersionReq, @@ -116,29 +116,6 @@ pub struct Dependency { pub optional: bool, } -impl bincode::Encode for Dependency { - fn encode( - &self, - encoder: &mut E, - ) -> Result<(), bincode::error::EncodeError> { - let Self { - name, - req, - kind, - rename, - optional, - } = self; - name.encode(encoder)?; - // FIXME: VersionReq does not implement Encode, so we serialize it to string - // Could be fixable by wrapping VersionReq in a newtype - req.to_string().encode(encoder)?; - kind.encode(encoder)?; - rename.encode(encoder)?; - optional.encode(encoder)?; - Ok(()) - } -} - impl Dependency { #[cfg(feature = "testing")] pub fn new(name: String, req: VersionReq) -> Dependency { @@ -158,25 +135,25 @@ impl Dependency { } } -#[derive(Deserialize, Serialize)] +#[derive(Deserialize)] struct DeserializedMetadata { packages: Vec, resolve: DeserializedResolve, } -#[derive(Deserialize, Serialize)] +#[derive(Deserialize)] struct DeserializedResolve { root: String, nodes: Vec, } -#[derive(Deserialize, Serialize)] +#[derive(Deserialize)] struct DeserializedResolveNode { id: String, deps: Vec, } -#[derive(Deserialize, Serialize)] +#[derive(Deserialize)] struct DeserializedResolveDep { pkg: String, } diff --git a/crates/lib/docs_rs_cargo_metadata/src/release_dependency.rs b/crates/lib/docs_rs_cargo_metadata/src/release_dependency.rs index ce83080bd..2fb69357f 100644 --- a/crates/lib/docs_rs_cargo_metadata/src/release_dependency.rs +++ b/crates/lib/docs_rs_cargo_metadata/src/release_dependency.rs @@ -16,7 +16,7 @@ impl<'de> Deserialize<'de> for ReleaseDependency { { /// The three possible representations of a dependency in our internal JSON format /// in the `releases.dependencies` column. - #[derive(Serialize, Deserialize)] + #[derive(Deserialize)] #[serde(untagged)] enum Repr { /// just [name, version]`` diff --git a/crates/lib/docs_rs_headers/src/canonical_url.rs b/crates/lib/docs_rs_headers/src/canonical_url.rs index ff8bf5dd3..3350e432e 100644 --- a/crates/lib/docs_rs_headers/src/canonical_url.rs +++ b/crates/lib/docs_rs_headers/src/canonical_url.rs @@ -9,7 +9,8 @@ use std::{fmt, ops::Deref}; /// simplified typed header for a `Link rel=canonical` header in the response. /// /// When given only a path, it builds a full docs.rs URL. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] +#[serde(transparent)] pub struct CanonicalUrl(EscapedURI); impl CanonicalUrl { @@ -62,15 +63,6 @@ impl fmt::Display for CanonicalUrl { } } -impl Serialize for CanonicalUrl { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(&self.0.to_string()) - } -} - impl From for CanonicalUrl { fn from(value: Uri) -> Self { Self(EscapedURI::from_uri(value)) diff --git a/crates/lib/docs_rs_registry_api/Cargo.toml b/crates/lib/docs_rs_registry_api/Cargo.toml index 694cd55be..fe117ac2e 100644 --- a/crates/lib/docs_rs_registry_api/Cargo.toml +++ b/crates/lib/docs_rs_registry_api/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] anyhow = { workspace = true } -bincode = { workspace = true } chrono = { workspace = true } docs_rs_env_vars = { path = "../docs_rs_env_vars" } docs_rs_types = { path = "../docs_rs_types" } diff --git a/crates/lib/docs_rs_registry_api/src/models.rs b/crates/lib/docs_rs_registry_api/src/models.rs index 46f20893c..89cfc4e8e 100644 --- a/crates/lib/docs_rs_registry_api/src/models.rs +++ b/crates/lib/docs_rs_registry_api/src/models.rs @@ -32,17 +32,7 @@ pub struct CrateOwner { } #[derive( - Debug, - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Serialize, - Deserialize, - sqlx::Type, - bincode::Encode, + Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, sqlx::Type, )] #[sqlx(type_name = "owner_kind", rename_all = "lowercase")] #[serde(rename_all = "lowercase")] diff --git a/crates/lib/docs_rs_types/Cargo.toml b/crates/lib/docs_rs_types/Cargo.toml index 2192ba605..411401011 100644 --- a/crates/lib/docs_rs_types/Cargo.toml +++ b/crates/lib/docs_rs_types/Cargo.toml @@ -5,12 +5,11 @@ edition = "2024" [dependencies] anyhow = { workspace = true } -bincode = { workspace = true } crates_io_validation = { path = "../crates_io_validation" } derive_more = { workspace = true } semver = { version = "1.0.4", features = ["serde"] } serde = { workspace = true } -serde_with = "3.4.0" +serde_with = { workspace = true } sqlx = { workspace = true } [dev-dependencies] @@ -19,6 +18,6 @@ test-case = { workspace = true } tokio = { workspace = true } [features] -# NOTE: we could make serde & sqlx & bincode optional features, some +# NOTE: we could make serde & sqlx optional features, some # of the subcrates don't need one or both of them. testing = [] diff --git a/crates/lib/docs_rs_types/src/krate_name.rs b/crates/lib/docs_rs_types/src/krate_name.rs index f3e426612..0eed00fa1 100644 --- a/crates/lib/docs_rs_types/src/krate_name.rs +++ b/crates/lib/docs_rs_types/src/krate_name.rs @@ -19,17 +19,7 @@ use std::{borrow::Cow, io::Write, str::FromStr}; /// FIXME: this should actually come from some shared crate between the rust projects, /// so the amount of duplication is less. #[derive( - Debug, - Clone, - PartialEq, - Eq, - Hash, - Deref, - Into, - Display, - DeserializeFromStr, - SerializeDisplay, - bincode::Encode, + Debug, Clone, PartialEq, Eq, Hash, Deref, Into, Display, DeserializeFromStr, SerializeDisplay, )] pub struct KrateName(Cow<'static, str>); diff --git a/crates/lib/docs_rs_types/src/req_version.rs b/crates/lib/docs_rs_types/src/req_version.rs index 4ecbb6056..3fe0856b6 100644 --- a/crates/lib/docs_rs_types/src/req_version.rs +++ b/crates/lib/docs_rs_types/src/req_version.rs @@ -8,7 +8,7 @@ use std::{ /// Represents a version identifier in a request in the original state. /// Can be an exact version, a semver requirement, or the string "latest". -#[derive(Debug, Default, Clone, PartialEq, Eq, SerializeDisplay, DeserializeFromStr)] +#[derive(Debug, Default, Clone, PartialEq, Eq, DeserializeFromStr, SerializeDisplay)] pub enum ReqVersion { Exact(Version), Semver(VersionReq), @@ -22,30 +22,6 @@ impl ReqVersion { } } -impl bincode::Encode for ReqVersion { - fn encode( - &self, - encoder: &mut E, - ) -> Result<(), bincode::error::EncodeError> { - // manual implementation since VersionReq doesn't implement Encode, - // and I don't want to NewType it right now. - match self { - ReqVersion::Exact(v) => { - 0u8.encode(encoder)?; - v.encode(encoder) - } - ReqVersion::Semver(req) => { - 1u8.encode(encoder)?; - req.to_string().encode(encoder) - } - ReqVersion::Latest => { - 2u8.encode(encoder)?; - Ok(()) - } - } - } -} - impl Display for ReqVersion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/crates/lib/docs_rs_types/src/version.rs b/crates/lib/docs_rs_types/src/version.rs index 9a9b9ef23..088e31a09 100644 --- a/crates/lib/docs_rs_types/src/version.rs +++ b/crates/lib/docs_rs_types/src/version.rs @@ -42,27 +42,6 @@ mod version_impl { } } - impl bincode::Encode for Version { - fn encode( - &self, - encoder: &mut E, - ) -> Result<(), bincode::error::EncodeError> { - let Self(semver::Version { - major, - minor, - patch, - pre: _, - build: _, - }) = self; - major.encode(encoder)?; - minor.encode(encoder)?; - patch.encode(encoder)?; - bincode::Encode::encode(self.0.pre.as_str(), encoder)?; - bincode::Encode::encode(self.0.build.as_str(), encoder)?; - Ok(()) - } - } - impl Type for Version { fn type_info() -> PgTypeInfo { >::type_info() diff --git a/crates/lib/docs_rs_uri/Cargo.toml b/crates/lib/docs_rs_uri/Cargo.toml index 93ea3d9c5..b169c2144 100644 --- a/crates/lib/docs_rs_uri/Cargo.toml +++ b/crates/lib/docs_rs_uri/Cargo.toml @@ -6,9 +6,9 @@ edition = "2024" [dependencies] anyhow = { workspace = true } askama = { workspace = true } -bincode = { workspace = true } http = { workspace = true } percent-encoding = "2.2.0" +serde_with = { workspace = true } url = { workspace = true } [dev-dependencies] diff --git a/crates/lib/docs_rs_uri/src/escaped_uri.rs b/crates/lib/docs_rs_uri/src/escaped_uri.rs index b6bc97344..dc6260a99 100644 --- a/crates/lib/docs_rs_uri/src/escaped_uri.rs +++ b/crates/lib/docs_rs_uri/src/escaped_uri.rs @@ -1,6 +1,7 @@ use crate::encode::{encode_url_path, url_decode}; use askama::filters::HtmlSafe; use http::{Uri, uri::PathAndQuery}; +use serde_with::{DeserializeFromStr, SerializeDisplay}; use std::{borrow::Borrow, fmt::Display, iter, str::FromStr}; use url::form_urlencoded; @@ -13,29 +14,12 @@ use url::form_urlencoded; /// /// Also we support fragments, with http::Uri doesn't support yet. /// See https://github.com/hyperium/http/issues/775 -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, SerializeDisplay, DeserializeFromStr)] pub struct EscapedURI { uri: Uri, fragment: Option, } -impl bincode::Encode for EscapedURI { - fn encode( - &self, - encoder: &mut E, - ) -> Result<(), bincode::error::EncodeError> { - // encode as separate parts so we don't have to clone - self.uri.scheme_str().encode(encoder)?; - self.uri.authority().map(|a| a.as_str()).encode(encoder)?; - self.uri - .path_and_query() - .map(|pq| pq.as_str()) - .encode(encoder)?; - self.fragment.encode(encoder)?; - Ok(()) - } -} - impl EscapedURI { pub fn from_uri(uri: Uri) -> Self { if uri.path_and_query().is_some() { diff --git a/src/build_queue.rs b/src/build_queue.rs index 104bd7674..f42999779 100644 --- a/src/build_queue.rs +++ b/src/build_queue.rs @@ -57,9 +57,8 @@ pub(crate) const PRIORITY_CONSISTENCY_CHECK: i32 = 15; /// The static priority for background rebuilds, used when queueing rebuilds, and when rendering them collapsed in the UI. pub(crate) const PRIORITY_CONTINUOUS: i32 = 20; -#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize)] +#[derive(Debug, Clone, Eq, PartialEq)] pub(crate) struct QueuedCrate { - #[serde(skip)] id: i32, pub(crate) name: String, pub(crate) version: Version, diff --git a/src/docbuilder/limits.rs b/src/docbuilder/limits.rs index f1e21a27c..b9571c991 100644 --- a/src/docbuilder/limits.rs +++ b/src/docbuilder/limits.rs @@ -1,10 +1,9 @@ use crate::{Config, db::Overrides, error::Result}; -use serde::Serialize; use std::time::Duration; const GB: usize = 1024 * 1024 * 1024; -#[derive(Debug, Clone, PartialEq, Eq, Serialize)] +#[derive(Debug, Clone, PartialEq, Eq)] pub(crate) struct Limits { pub memory: usize, pub targets: usize, diff --git a/src/docbuilder/rustwide_builder.rs b/src/docbuilder/rustwide_builder.rs index 2df87de03..e6ff16cd7 100644 --- a/src/docbuilder/rustwide_builder.rs +++ b/src/docbuilder/rustwide_builder.rs @@ -1453,7 +1453,7 @@ mod tests { use docs_rs_storage::{CompressionAlgorithm, compression}; use docs_rs_types::{BuildStatus, Feature, ReleaseId, Version}; use pretty_assertions::assert_eq; - use std::{io, iter}; + use std::{collections::BTreeMap, io, iter}; use test_case::test_case; fn get_features( @@ -1832,7 +1832,7 @@ mod tests { targets: vec![], readme: None, keywords: vec![], - features: HashMap::new(), + features: BTreeMap::new(), }, Path::new("/unknown/"), "x86_64-unknown-linux-gnu", diff --git a/src/test/fakes.rs b/src/test/fakes.rs index 5133647af..350cd08ef 100644 --- a/src/test/fakes.rs +++ b/src/test/fakes.rs @@ -15,7 +15,11 @@ use docs_rs_storage::{ rustdoc_archive_path, rustdoc_json_path, source_archive_path, }; use docs_rs_types::{BuildId, BuildStatus, ReleaseId, Version, VersionReq}; -use std::{collections::HashMap, fmt, iter, sync::Arc}; +use std::{ + collections::{BTreeMap, HashMap}, + fmt, iter, + sync::Arc, +}; use tracing::debug; /// Create a fake release in the database that failed before the build. @@ -121,7 +125,7 @@ impl<'a> FakeRelease<'a> { ] .iter() .cloned() - .collect::>>(), + .collect::>>(), }, builds: None, source_files: Vec::new(), @@ -309,7 +313,7 @@ impl<'a> FakeRelease<'a> { } } - pub(crate) fn features(mut self, features: HashMap>) -> Self { + pub(crate) fn features(mut self, features: BTreeMap>) -> Self { self.package.features = features; self } diff --git a/src/web/build_details.rs b/src/web/build_details.rs index 64685a5aa..5db88c11b 100644 --- a/src/web/build_details.rs +++ b/src/web/build_details.rs @@ -51,7 +51,7 @@ impl BuildDetailsPage { } } -#[derive(Clone, Deserialize, Debug)] +#[derive(Clone, Debug, Deserialize)] pub(crate) struct BuildDetailsParams { pub(crate) id: String, pub(crate) filename: Option, diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs index c35ce78cc..04bb7db88 100644 --- a/src/web/crate_details.rs +++ b/src/web/crate_details.rs @@ -733,7 +733,7 @@ mod tests { use http::StatusCode; use kuchikiki::traits::TendrilSink; use pretty_assertions::assert_eq; - use std::collections::HashMap; + use std::collections::BTreeMap; use std::str::FromStr as _; use test_case::test_case; @@ -1579,7 +1579,7 @@ mod tests { .await .name("library") .version("0.1.0") - .features(HashMap::new()) + .features(BTreeMap::new()) .create() .await?; @@ -1602,7 +1602,7 @@ mod tests { let features = [("_private".into(), Vec::new())] .iter() .cloned() - .collect::>>(); + .collect::>>(); env.fake_release() .await .name("library") @@ -1630,7 +1630,7 @@ mod tests { let features = [("feature1".into(), Vec::new())] .iter() .cloned() - .collect::>>(); + .collect::>>(); env.fake_release() .await .name("library") @@ -1666,7 +1666,7 @@ mod tests { ] .iter() .cloned() - .collect::>>(); + .collect::>>(); env.fake_release() .await .name("library") diff --git a/src/web/extractors/rustdoc.rs b/src/web/extractors/rustdoc.rs index c34f58007..bc645d307 100644 --- a/src/web/extractors/rustdoc.rs +++ b/src/web/extractors/rustdoc.rs @@ -11,7 +11,7 @@ use docs_rs_storage::CompressionAlgorithm; use docs_rs_types::{BuildId, KrateName, ReqVersion}; use docs_rs_uri::{EscapedURI, url_decode}; use itertools::Itertools as _; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; const INDEX_HTML: &str = "index.html"; const FOLDER_AND_INDEX_HTML: &str = "/index.html"; @@ -23,7 +23,7 @@ pub(crate) const ROOT_RUSTDOC_HTML_FILES: &[&str] = &[ "scrape-examples-help.html", ]; -#[derive(Clone, Debug, PartialEq, bincode::Encode)] +#[derive(Clone, Debug, PartialEq, Serialize)] pub(crate) enum PageKind { Rustdoc, Source, @@ -39,7 +39,7 @@ pub(crate) enum PageKind { /// All of these have more or less detail depending on how much metadata we have here. /// Maintains some additional fields containing "fixed" things, whos quality /// gets better the more metadata we provide. -#[derive(Clone, PartialEq, bincode::Encode)] +#[derive(Clone, PartialEq, Serialize)] pub(crate) struct RustdocParams { // optional behaviour marker page_kind: Option, @@ -102,7 +102,7 @@ impl std::fmt::Debug for RustdocParams { /// All except the crate name are optional or have a default, /// so this extractor can be used in many handlers with a variety of /// specificity of the route. -#[derive(Deserialize, Debug)] +#[derive(Debug, Deserialize)] pub(crate) struct UrlParams { pub name: KrateName, #[serde(default)] diff --git a/src/web/features.rs b/src/web/features.rs index cde0e2e75..7f6252081 100644 --- a/src/web/features.rs +++ b/src/web/features.rs @@ -238,7 +238,7 @@ fn get_dependency_versions(raw_dependencies: Option) -> HashMap) -> (Vec, HashSet) { - let mut all_features: HashMap<_, _> = raw_features + let mut all_features: BTreeMap<_, _> = raw_features .into_iter() .filter(|feature| !feature.is_private()) .map(|feature| (feature.name.clone(), Feature::from(feature))) @@ -408,7 +408,7 @@ mod tests { .await .name("foo") .version("0.2.1") - .features(HashMap::new()) + .features(BTreeMap::new()) .create() .await?; @@ -431,7 +431,7 @@ mod tests { .await .name("foo") .version("0.2.0") - .features(HashMap::new()) + .features(BTreeMap::new()) .create() .await?; @@ -455,7 +455,7 @@ mod tests { .await .name("foo") .version("0.1.0") - .features(HashMap::new()) + .features(BTreeMap::new()) .create() .await?; @@ -463,7 +463,7 @@ mod tests { .await .name("foo") .version("0.2.0") - .features(HashMap::new()) + .features(BTreeMap::new()) .create() .await?; @@ -489,7 +489,7 @@ mod tests { .await .name("foo") .version("0.1.0") - .features(HashMap::new()) + .features(BTreeMap::new()) .create() .await?; @@ -507,7 +507,7 @@ mod tests { .await .name("foo") .version("0.1.0") - .features(HashMap::new()) + .features(BTreeMap::new()) .create() .await?; @@ -539,7 +539,7 @@ mod tests { .await .name("foo") .version("0.1.0") - .features(features.into_iter().collect::>()) + .features(features.into_iter().collect::>()) .create() .await?; diff --git a/src/web/licenses.rs b/src/web/licenses.rs index c3bd537ac..f40dc27de 100644 --- a/src/web/licenses.rs +++ b/src/web/licenses.rs @@ -1,4 +1,5 @@ use regex::Regex; +use serde::Serialize; use std::collections::HashSet; use std::sync::LazyLock; @@ -8,7 +9,7 @@ static LICENSE_ID_REGEX: LazyLock = LazyLock::new(|| Regex::new("[A-Za-z0-9.-]+").expect("Known regex must compile")); /// A segment of an SPDX license string -#[derive(Clone, PartialEq, Eq, Debug, bincode::Encode)] +#[derive(Clone, PartialEq, Eq, Debug, Serialize)] pub enum LicenseSegment { /// This is a set of glue tokens like OR, AND, `/`, `(`, `)`, etc. /// diff --git a/src/web/mod.rs b/src/web/mod.rs index 312cdf48d..3213cee98 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -525,7 +525,7 @@ where } /// MetaData used in header -#[derive(Debug, Clone, PartialEq, Eq, Serialize, bincode::Encode)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub(crate) struct MetaData { pub(crate) name: KrateName, /// The exact version of the release being shown. diff --git a/src/web/releases.rs b/src/web/releases.rs index ec7b4bed4..71357a6c4 100644 --- a/src/web/releases.rs +++ b/src/web/releases.rs @@ -29,7 +29,7 @@ use docs_rs_types::{KrateName, ReqVersion, Version}; use docs_rs_uri::encode_url_path; use futures_util::stream::TryStreamExt; use itertools::Itertools; -use serde::{Deserialize, Serialize}; +use serde::Deserialize; use sqlx::Row; use std::{ collections::{BTreeMap, HashMap}, @@ -46,7 +46,7 @@ const RELEASES_IN_RELEASES: i64 = 30; /// Releases in recent releases feed const RELEASES_IN_FEED: i64 = 150; -#[derive(Debug, Clone, PartialEq, Eq, Serialize)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Release { pub(crate) name: KrateName, pub(crate) version: Version, @@ -711,7 +711,7 @@ pub(crate) async fn activity_handler(mut conn: DbConnection) -> AxumResult, diff --git a/src/web/rustdoc.rs b/src/web/rustdoc.rs index 47fc2a725..bad0c1b8b 100644 --- a/src/web/rustdoc.rs +++ b/src/web/rustdoc.rs @@ -43,7 +43,7 @@ use docs_rs_storage::{ use docs_rs_types::{KrateName, ReqVersion}; use docs_rs_uri::EscapedURI; use http::{HeaderMap, HeaderValue, Uri, header::CONTENT_DISPOSITION, uri::Authority}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, iter, @@ -380,6 +380,7 @@ pub(crate) async fn rustdoc_redirector_handler( /// small wrapper around CrateDetails to limit serialized fields we hand /// to the template. /// Mostly to know what we have to serialize into the etag. +#[derive(Serialize)] pub struct LimitedCrateDetails { parsed_license: Option>, homepage_url: Option, @@ -418,35 +419,7 @@ impl From for LimitedCrateDetails { } } -impl bincode::Encode for LimitedCrateDetails { - fn encode( - &self, - encoder: &mut E, - ) -> Result<(), bincode::error::EncodeError> { - let LimitedCrateDetails { - parsed_license, - homepage_url, - documentation_url, - repository_url, - owners, - dependencies, - total_items, - documented_items, - } = self; - - parsed_license.encode(encoder)?; - homepage_url.encode(encoder)?; - documentation_url.encode(encoder)?; - repository_url.encode(encoder)?; - owners.encode(encoder)?; - dependencies.encode(encoder)?; - total_items.encode(encoder)?; - documented_items.encode(encoder)?; - Ok(()) - } -} - -#[derive(Template, bincode::Encode)] +#[derive(Template, Serialize)] #[template(path = "rustdoc/topbar.html")] pub struct RustdocPage { pub latest_path: EscapedURI, @@ -494,14 +467,11 @@ impl RustdocPage { // we assume that all the info we put into the `RustdocPage` struct might change the // page content. So we have to pipe all of it into the ETag. - // I chose to add the additional bincode dependency because I was worried about the + // I chose to add the additional postcard dependency because I was worried about the // added processing time when handling these responses, since this is our // most accessed handler on the origin. - let config = bincode::config::standard() - .with_big_endian() - .with_variable_int_encoding(); - bincode::encode_into_std_write(self, &mut etag, config) - .expect("bincode::Encode impl in RustdocPage can't fail"); + postcard::to_io(self, &mut etag) + .expect("postcard::to_io can only when the underlying write fails, which it can't"); etag.finalize() } @@ -852,7 +822,7 @@ pub(crate) async fn target_redirect_handler( )?) } -#[derive(Deserialize, Debug)] +#[derive(Debug, Deserialize)] pub(crate) struct BadgeQueryParams { version: Option, } @@ -875,7 +845,7 @@ pub(crate) async fn badge_handler( )) } -#[derive(Clone, Deserialize, Debug)] +#[derive(Clone, Debug, Deserialize)] pub(crate) struct JsonDownloadParams { pub(crate) format_version: Option, }