From f6ed23607bda1e7b00f4679ea3b8d6e4bc3e3c4b Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Fri, 15 May 2026 14:42:03 +0200 Subject: [PATCH] storage: use Bytes instead of Vec to prevent some cloning --- .../bin/docs_rs_web/src/handlers/rustdoc.rs | 6 ++-- crates/lib/docs_rs_storage/src/blob.rs | 8 ++--- .../docs_rs_storage/src/storage/blocking.rs | 5 +-- .../src/storage/non_blocking.rs | 36 +++++++++---------- crates/lib/docs_rs_test_fakes/src/legacy.rs | 4 +-- 5 files changed, 29 insertions(+), 30 deletions(-) diff --git a/crates/bin/docs_rs_web/src/handlers/rustdoc.rs b/crates/bin/docs_rs_web/src/handlers/rustdoc.rs index 34a221fe8..c51e1bc5f 100644 --- a/crates/bin/docs_rs_web/src/handlers/rustdoc.rs +++ b/crates/bin/docs_rs_web/src/handlers/rustdoc.rs @@ -3254,7 +3254,7 @@ mod test { storage .store_one( format!("{RUSTDOC_STATIC_STORAGE_PREFIX}{path}"), - b"static content", + "static content", ) .await?; @@ -3298,8 +3298,8 @@ mod test { const ROOT_ASSET: &str = "normalize-20200403-1.44.0-nightly-74bd074ee.css"; let storage = env.storage()?; - storage.store_one(ROOT_ASSET, *b"content").await?; - storage.store_one(path, *b"more_content").await?; + storage.store_one(ROOT_ASSET, "content").await?; + storage.store_one(path, "more_content").await?; let web = env.web_app().await; diff --git a/crates/lib/docs_rs_storage/src/blob.rs b/crates/lib/docs_rs_storage/src/blob.rs index f6364ff41..91fc7ffab 100644 --- a/crates/lib/docs_rs_storage/src/blob.rs +++ b/crates/lib/docs_rs_storage/src/blob.rs @@ -33,7 +33,7 @@ impl From for StreamUpload { Self { path: value.path, mime: value.mime, - source: StreamUploadSource::Bytes(value.content.into()), + source: StreamUploadSource::Bytes(value.content), compression: value.compression, } } @@ -44,7 +44,7 @@ impl From for StreamUpload { pub struct BlobUpload { pub path: String, pub mime: Mime, - pub content: Vec, + pub content: Bytes, pub compression: Option, } @@ -53,7 +53,7 @@ impl From for BlobUpload { Self { path: value.path, mime: value.mime, - content: value.content, + content: value.content.into(), compression: value.compression, } } @@ -76,7 +76,7 @@ impl From for Blob { mime: value.mime, date_updated: Utc::now(), etag: compute_etag(&value.content).into(), - content: value.content, + content: value.content.into(), compression: value.compression, } } diff --git a/crates/lib/docs_rs_storage/src/storage/blocking.rs b/crates/lib/docs_rs_storage/src/storage/blocking.rs index 59c28caaa..44fd307d7 100644 --- a/crates/lib/docs_rs_storage/src/storage/blocking.rs +++ b/crates/lib/docs_rs_storage/src/storage/blocking.rs @@ -3,6 +3,7 @@ use anyhow::Result; use docs_rs_types::{BuildId, CompressionAlgorithm, KrateName, Version}; use std::{fmt, path::Path, sync::Arc}; use tokio::runtime; +use tokio_util::bytes::Bytes; /// Sync wrapper around `AsyncStorage` for parts of the codebase that are not async. pub struct Storage { @@ -112,7 +113,7 @@ impl Storage { pub fn store_one_uncompressed( &self, path: impl Into + std::fmt::Debug, - content: impl Into>, + content: impl Into, ) -> Result<()> { self.runtime .block_on(self.inner.store_one_uncompressed(path, content)) @@ -123,7 +124,7 @@ impl Storage { pub fn store_one( &self, path: impl Into + std::fmt::Debug, - content: impl Into>, + content: impl Into, ) -> Result { self.runtime.block_on(self.inner.store_one(path, content)) } diff --git a/crates/lib/docs_rs_storage/src/storage/non_blocking.rs b/crates/lib/docs_rs_storage/src/storage/non_blocking.rs index 206793304..843e137ac 100644 --- a/crates/lib/docs_rs_storage/src/storage/non_blocking.rs +++ b/crates/lib/docs_rs_storage/src/storage/non_blocking.rs @@ -29,6 +29,7 @@ use std::{ sync::Arc, }; use tokio::{fs, io, io::AsyncWriteExt as _}; +use tokio_util::bytes::Bytes; use tracing::{info_span, instrument, trace, warn}; /// buffer size when writing zip files. @@ -491,7 +492,7 @@ impl AsyncStorage { pub async fn store_one_uncompressed( &self, path: impl Into + fmt::Debug, - content: impl Into>, + content: impl Into, ) -> Result<()> { let path = path.into(); let content = content.into(); @@ -501,7 +502,7 @@ impl AsyncStorage { .upload_stream(StreamUpload { path, mime, - source: StreamUploadSource::Bytes(content.into()), + source: StreamUploadSource::Bytes(content), compression: None, }) .await?; @@ -515,11 +516,11 @@ impl AsyncStorage { pub async fn store_one( &self, path: impl Into + fmt::Debug, - content: impl Into>, + content: impl Into, ) -> Result { let path = path.into(); let alg = CompressionAlgorithm::default(); - let content = compress(Cursor::new(content.into()), alg)?; + let content = compress(Cursor::new(content.into().as_ref()), alg)?; let mime = detect_mime(&path).to_owned(); self.backend @@ -615,7 +616,7 @@ mod backend_tests { path: path.into(), mime: mime::TEXT_PLAIN, compression: None, - content: b"test content\n".to_vec(), + content: "test content\n".into(), }; storage.store_blobs(vec![blob.clone()]).await?; @@ -646,7 +647,7 @@ mod backend_tests { path: "foo/bar.txt".into(), mime: mime::TEXT_PLAIN, compression: None, - content: b"test content\n".to_vec(), + content: "test content\n".into(), }; let full_etag = compute_etag(&blob.content); @@ -697,7 +698,7 @@ mod backend_tests { path: filename.into(), mime: mime::TEXT_PLAIN, compression: None, - content: b"test content\n".to_vec(), + content: "test content\n".into(), }) .collect(), ) @@ -746,13 +747,13 @@ mod backend_tests { let small_blob = BlobUpload { path: "small-blob.bin".into(), mime: mime::TEXT_PLAIN, - content: vec![0; MAX_SIZE], + content: [0; MAX_SIZE].as_ref().into(), compression: None, }; let big_blob = BlobUpload { path: "big-blob.bin".into(), mime: mime::TEXT_PLAIN, - content: vec![0; MAX_SIZE * 2], + content: [0; MAX_SIZE * 2].as_ref().into(), compression: None, }; @@ -792,7 +793,7 @@ mod backend_tests { path: path.into(), mime: mime::TEXT_PLAIN, compression: None, - content: b"Hello world!\n".to_vec(), + content: "Hello world!\n".into(), }) .collect::>(); @@ -975,14 +976,11 @@ mod backend_tests { async fn test_batched_uploads(storage: &AsyncStorage) -> Result<()> { let uploads: Vec<_> = (0..=100) - .map(|i| { - let content = format!("const IDX: usize = {i};").as_bytes().to_vec(); - BlobUpload { - mime: mimes::TEXT_RUST.clone(), - content, - path: format!("{i}.rs"), - compression: None, - } + .map(|i| BlobUpload { + mime: mimes::TEXT_RUST.clone(), + content: format!("const IDX: usize = {i};").into(), + path: format!("{i}.rs"), + compression: None, }) .collect(); @@ -1043,7 +1041,7 @@ mod backend_tests { .iter() .map(|path| BlobUpload { path: (*path).to_string(), - content: b"foo\n".to_vec(), + content: "foo\n".into(), compression: None, mime: mime::TEXT_PLAIN, }) diff --git a/crates/lib/docs_rs_test_fakes/src/legacy.rs b/crates/lib/docs_rs_test_fakes/src/legacy.rs index 33ebe89e3..015e71c8b 100644 --- a/crates/lib/docs_rs_test_fakes/src/legacy.rs +++ b/crates/lib/docs_rs_test_fakes/src/legacy.rs @@ -733,7 +733,7 @@ impl FakeBuild { let prefix = format!("build-logs/{build_id}/"); - if let Some(s3_build_log) = self.s3_build_log.as_deref() { + if let Some(s3_build_log) = self.s3_build_log.clone() { let path = format!("{prefix}{default_target}.txt"); storage.store_one(path, s3_build_log).await?; } @@ -743,7 +743,7 @@ impl FakeBuild { bail!("build log for default target has to be set via `s3_build_log`"); } let path = format!("{prefix}{target}.txt"); - storage.store_one(path, log.as_str()).await?; + storage.store_one(path, log.clone()).await?; } Ok(())