Skip to content

perf!: reduce allocations in upload, send, and Jid paths - #471

Merged
jlucaso1 merged 1 commit into
mainfrom
perf/reduce-allocations-upload-send
Mar 31, 2026
Merged

perf!: reduce allocations in upload, send, and Jid paths#471
jlucaso1 merged 1 commit into
mainfrom
perf/reduce-allocations-upload-send

Conversation

@jlucaso1

@jlucaso1 jlucaso1 commented Mar 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • UploadResponse / MediaUploadInfo: media_key, file_sha256, file_enc_sha256 changed from Vec<u8> to [u8; 32] — eliminates heap allocations on construction and makes Clone a 96-byte memcpy instead of 3 heap allocs
  • UploadOptions::media_key: Option<Vec<u8>>Option<[u8; 32]> — removes the try_from validation dance since the type is now statically correct
  • Status::send_image / send_video: take UploadResponse by value — moves Strings instead of cloning them
  • DM send path: move message_for_encryption into DeviceSentMessage instead of cloning (1 full protobuf Message clone eliminated per DM)
  • Group send path: compute phash eagerly from the distribution list, avoiding a Vec<Jid> clone
  • Jid::new: user: &struser: impl Into<String> — callers with owned Strings skip reallocation

Breaking changes & migration

UploadResponse fields changed from Vec<u8> to [u8; 32]

// Before:
upload.media_key.clone()      // Vec<u8> clone (heap alloc)
upload.file_sha256.clone()    // Vec<u8> clone (heap alloc)

// After — for protobuf fields that need Vec<u8>:
upload.media_key.to_vec()
upload.file_sha256.to_vec()

// After — for passing as &[u8] (zero-cost):
&upload.media_key
&upload.file_sha256

UploadOptions::with_media_key takes [u8; 32] instead of Vec<u8>

// Before:
UploadOptions::new().with_media_key(vec_key)

// After:
UploadOptions::new().with_media_key(array_key)  // [u8; 32]

MediaUploadInfo::new takes [u8; 32] instead of Vec<u8>

// Before:
MediaUploadInfo::new(path, vec![0u8; 32], vec![1u8; 32], vec![2u8; 32], len, ts)

// After:
MediaUploadInfo::new(path, [0u8; 32], [1u8; 32], [2u8; 32], len, ts)

Status::send_image / send_video take UploadResponse by value

// Before:
client.status().send_image(&upload, thumb, caption, &recipients, opts).await?;
// upload is still usable here

// After:
client.status().send_image(upload, thumb, caption, &recipients, opts).await?;
// upload is consumed — clone before if needed elsewhere

Jid::new accepts impl Into<String> (non-breaking for most callers)

Existing Jid::new("user", "server") calls continue to work. Callers with owned Strings now avoid a reallocation:

let owned: String = get_user();
Jid::new(owned, "s.whatsapp.net")  // no extra allocation

Test plan

  • cargo clippy --all --tests — clean
  • cargo test --all --lib — all unit tests pass
  • E2E tests (requires mock server)

Summary by CodeRabbit

  • Performance

    • Improved media upload handling to reduce memory use and make image/video sending more efficient.
  • Bug Fixes

    • Added validation for sticker pack uploads to catch mismatched media keys and fail early.
  • Refactor

    • Internal message construction updated to avoid unnecessary cloning and streamline stanza preparation.

@coderabbitai

coderabbitai Bot commented Mar 31, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 524c39c7-ca38-4acb-9629-3bf6ee22bc8c

📥 Commits

Reviewing files that changed from the base of the PR and between a4ff6d7 and 6d51c9c.

📒 Files selected for processing (7)
  • src/features/status.rs
  • src/upload.rs
  • tests/e2e/tests/media.rs
  • tests/e2e/tests/newsletter.rs
  • wacore/binary/src/jid.rs
  • wacore/src/send.rs
  • wacore/src/sticker_pack.rs

📝 Walkthrough

Walkthrough

Refactors media crypto fields from Vec<u8> to fixed-size [u8; 32], adds vec-conversion helpers, changes UploadOptions and UploadResponse types, makes Status::send_image/send_video take UploadResponse by value, adjusts usages and tests, and tweaks Jid::new plus stanza/message ownership handling.

Changes

Cohort / File(s) Summary
Upload & options
src/upload.rs
Converted UploadResponse crypto fields (media_key, file_enc_sha256, file_sha256) to [u8; 32]; UploadOptions.media_keyOption<[u8;32]>. Added helper methods to return Vec<u8>. Updated builder/usage sites and with_media_key signature.
Status media send
src/features/status.rs
Changed send_image and send_video to take upload: UploadResponse (by value). Moved URL/direct_path strings and converted fixed-size arrays to Vec<u8> via .to_vec() when building proto messages.
Sticker pack & media info
wacore/src/sticker_pack.rs
MediaUploadInfo fields switched to [u8;32]. build_sticker_pack_message now returns Result<wa::Message> and validates matching media keys between zip/thumb. Proto construction converts arrays to Vec<u8>.
Send flow & JID
wacore/src/send.rs, wacore/binary/src/jid.rs
prepare_dm_stanza moves message into DeviceSentMessage (no clone). prepare_group_stanza precomputes/stores phash string. Jid::new now accepts impl Into<String> for user.
Tests
tests/e2e/tests/media.rs, tests/e2e/tests/newsletter.rs
Updated tests to use .to_vec() for crypto fields when building messages (reflecting fixed-size array storage).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I hopped through bytes both small and neat,
Swapped vectors for arrays — tidy and sweet.
Keys stacked in rows, no heap to roam,
Messages move, no clones to own.
A carrot for tests, a thump for review.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically identifies the main objective of the PR: reducing allocations across upload, send, and Jid paths, matching the substantive changes throughout the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/reduce-allocations-upload-send

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Mar 31, 2026

Copy link
Copy Markdown

🐰 Bencher Report

Branchperf/reduce-allocations-upload-send
Testbedubuntu-latest

🚨 1 Alert

BenchmarkMeasure
Units
ViewBenchmark Result
(Result Δ%)
Upper Boundary
(Limit %)
libsignal_benchmark::session_optimization_group::bench_decrypt_with_previous_session previous_session:setup_with_archived_sessions()Instructions
instructions x 1e3
📈 plot
🚷 threshold
🚨 alert (🔔)
47.13 x 1e3
(+8.92%)Baseline: 43.27 x 1e3
45.43 x 1e3
(103.74%)

Click to view all benchmark results
BenchmarkInstructionsBenchmark Result
instructions
(Result Δ%)
Upper Boundary
instructions
(Limit %)
binary_benchmark::attr_parser_group::bench_attr_parser attr_lookup:setup_attr_marshaled()📈 view plot
🚷 view threshold
6,197.00
(-4.72%)Baseline: 6,504.29
6,829.50
(90.74%)
binary_benchmark::child_iteration_group::bench_get_children_by_tag📈 view plot
🚷 view threshold
524,304.00
(-26.46%)Baseline: 712,911.92
748,557.51
(70.04%)
binary_benchmark::jid_optimization_group::bench_jid_to_owned_access jid_access:setup_jid_heavy_marshaled()📈 view plot
🚷 view threshold
20,868.00
(-5.50%)Baseline: 22,082.04
23,186.14
(90.00%)
binary_benchmark::marshal_group::bench_marshal_allocating📈 view plot
🚷 view threshold
98,202.00
(-15.54%)Baseline: 116,270.61
122,084.14
(80.44%)
binary_benchmark::marshal_group::bench_marshal_auto_allocating📈 view plot
🚷 view threshold
98,230.00
(-9.77%)Baseline: 108,868.07
114,311.47
(85.93%)
binary_benchmark::marshal_group::bench_marshal_auto_huge_bytes_allocating📈 view plot
🚷 view threshold
532,948.00
(-0.10%)Baseline: 533,502.20
560,177.31
(95.14%)
binary_benchmark::marshal_group::bench_marshal_auto_long_string📈 view plot
🚷 view threshold
15,870.00
(-4.54%)Baseline: 16,624.94
17,456.18
(90.91%)
binary_benchmark::marshal_group::bench_marshal_auto_many_children_allocating📈 view plot
🚷 view threshold
14,715,201.00
(-7.71%)Baseline: 15,944,268.86
16,741,482.31
(87.90%)
binary_benchmark::marshal_group::bench_marshal_exact_allocating📈 view plot
🚷 view threshold
118,358.00
(-19.96%)Baseline: 147,878.76
155,272.69
(76.23%)
binary_benchmark::marshal_group::bench_marshal_exact_huge_bytes_allocating📈 view plot
🚷 view threshold
534,378.00
(-0.10%)Baseline: 534,923.42
561,669.59
(95.14%)
binary_benchmark::marshal_group::bench_marshal_exact_long_string📈 view plot
🚷 view threshold
17,919.00
(-4.05%)Baseline: 18,676.15
19,609.96
(91.38%)
binary_benchmark::marshal_group::bench_marshal_exact_many_children_allocating📈 view plot
🚷 view threshold
28,066,347.00
(-20.97%)Baseline: 35,511,431.57
37,287,003.15
(75.27%)
binary_benchmark::marshal_group::bench_marshal_huge_bytes_allocating📈 view plot
🚷 view threshold
533,387.00
(-0.10%)Baseline: 533,941.20
560,638.26
(95.14%)
binary_benchmark::marshal_group::bench_marshal_long_string📈 view plot
🚷 view threshold
15,843.00
(-7.16%)Baseline: 17,064.38
17,917.60
(88.42%)
binary_benchmark::marshal_group::bench_marshal_many_children_allocating📈 view plot
🚷 view threshold
14,716,627.00
(-7.71%)Baseline: 15,945,401.66
16,742,671.75
(87.90%)
binary_benchmark::marshal_group::bench_marshal_reusing_buffer📈 view plot
🚷 view threshold
107,945.00
(-12.30%)Baseline: 123,085.12
129,239.38
(83.52%)
binary_benchmark::marshal_group::bench_marshal_reusing_buffer_vec_writer📈 view plot
🚷 view threshold
98,302.00
(-9.77%)Baseline: 108,940.07
114,387.07
(85.94%)
binary_benchmark::roundtrip_group::bench_roundtrip large:setup_large_marshaled()📈 view plot
🚷 view threshold
90,974.00
(-5.21%)Baseline: 95,975.90
100,774.69
(90.27%)
binary_benchmark::roundtrip_group::bench_roundtrip small:setup_small_marshaled()📈 view plot
🚷 view threshold
7,378.00
(-3.35%)Baseline: 7,634.00
8,015.70
(92.04%)
binary_benchmark::roundtrip_group::bench_roundtrip_auto large:setup_large_marshaled()📈 view plot
🚷 view threshold
91,005.00
(-1.72%)Baseline: 92,602.06
97,232.16
(93.60%)
binary_benchmark::roundtrip_group::bench_roundtrip_auto small:setup_small_marshaled()📈 view plot
🚷 view threshold
7,401.00
(+0.35%)Baseline: 7,375.35
7,744.11
(95.57%)
binary_benchmark::roundtrip_group::bench_roundtrip_exact large:setup_large_marshaled()📈 view plot
🚷 view threshold
106,790.00
(-1.47%)Baseline: 108,387.06
113,806.41
(93.83%)
binary_benchmark::roundtrip_group::bench_roundtrip_exact small:setup_small_marshaled()📈 view plot
🚷 view threshold
8,913.00
(+0.29%)Baseline: 8,887.35
9,331.71
(95.51%)
binary_benchmark::unmarshal_group::bench_unmarshal large:setup_large_marshaled()📈 view plot
🚷 view threshold
41,989.00
(-7.59%)Baseline: 45,436.39
47,708.21
(88.01%)
binary_benchmark::unmarshal_group::bench_unmarshal small:setup_small_marshaled()📈 view plot
🚷 view threshold
2,717.00
(-2.87%)Baseline: 2,797.39
2,937.26
(92.50%)
binary_benchmark::unpack_group::bench_unpack_compressed📈 view plot
🚷 view threshold
556,092.00
(+1.82%)Baseline: 546,129.21
573,435.67
(96.98%)
binary_benchmark::unpack_group::bench_unpack_uncompressed📈 view plot
🚷 view threshold
771.00
(-0.27%)Baseline: 773.10
811.76
(94.98%)
libsignal_benchmark::conversation_group::bench_full_dm_conversation full:setup_conversation_data()📈 view plot
🚷 view threshold
27,696,368.00
(-0.01%)Baseline: 27,698,741.33
29,083,678.39
(95.23%)
libsignal_benchmark::dm_group::bench_dm_decrypt_first_message decrypt_prekey:setup_dm_with_first_message()📈 view plot
🚷 view threshold
5,544,828.00
(-0.05%)Baseline: 5,547,811.80
5,825,202.39
(95.19%)
libsignal_benchmark::dm_group::bench_dm_encrypt_first_message first_msg:setup_dm_session()📈 view plot
🚷 view threshold
175,061.00
(-1.32%)Baseline: 177,396.48
186,266.30
(93.98%)
libsignal_benchmark::dm_group::bench_dm_encrypt_subsequent_message subsequent:setup_established_dm_session()📈 view plot
🚷 view threshold
175,710.00
(-1.38%)Baseline: 178,171.30
187,079.87
(93.92%)
libsignal_benchmark::dm_group::bench_dm_session_establishment setup:setup_dm_users()📈 view plot
🚷 view threshold
17,158,702.00
(-0.71%)Baseline: 17,280,631.08
18,144,662.63
(94.57%)
libsignal_benchmark::group_messaging_group::bench_group_create_distribution_message create:setup_group_sender()📈 view plot
🚷 view threshold
298,417.00
(+0.55%)Baseline: 296,791.33
311,630.89
(95.76%)
libsignal_benchmark::group_messaging_group::bench_group_decrypt_message decrypt:setup_group_with_encrypted_message()📈 view plot
🚷 view threshold
12,591,698.00
(-0.03%)Baseline: 12,595,523.80
13,225,299.99
(95.21%)
libsignal_benchmark::group_messaging_group::bench_group_encrypt_message encrypt:setup_group_with_distribution()📈 view plot
🚷 view threshold
719,597.00
(+0.38%)Baseline: 716,900.06
752,745.06
(95.60%)
libsignal_benchmark::session_optimization_group::bench_decrypt_with_previous_session previous_session:setup_with_archived_sessions()📈 view plot
🚷 view threshold
🚨 view alert (🔔)
47,129.00
(+8.92%)Baseline: 43,268.08
45,431.49
(103.74%)

libsignal_benchmark::session_optimization_group::bench_message_key_eviction eviction:setup_message_key_eviction()📈 view plot
🚷 view threshold
15,561,842.00
(+0.00%)Baseline: 15,561,765.46
16,339,853.73
(95.24%)
libsignal_benchmark::session_optimization_group::bench_out_of_order_decryption out_of_order:setup_out_of_order_messages()📈 view plot
🚷 view threshold
5,378,778.00
(-1.81%)Baseline: 5,477,669.90
5,751,553.40
(93.52%)
libsignal_benchmark::session_optimization_group::bench_promote_matching_session promote:setup_promote_matching_session()📈 view plot
🚷 view threshold
312,188.00
(-61.16%)Baseline: 803,718.41
843,904.33
(36.99%)
libsignal_benchmark::signature_group::bench_key_generation keygen📈 view plot
🚷 view threshold
2,830,547.00
(+0.18%)Baseline: 2,825,540.05
2,966,817.05
(95.41%)
libsignal_benchmark::signature_group::bench_signature_creation sign:setup_keypair_with_message()📈 view plot
🚷 view threshold
3,452,844.00
(-0.52%)Baseline: 3,470,936.84
3,644,483.69
(94.74%)
libsignal_benchmark::signature_group::bench_signature_verification verify:setup_keypair_with_message()📈 view plot
🚷 view threshold
126,163,068.00
(+0.65%)Baseline: 125,350,429.48
131,617,950.95
(95.86%)
reporting_token_benchmark::content_extraction_group::bench_content_extraction extended:setup_extended_message()📈 view plot
🚷 view threshold
12,002.00
(+1.50%)Baseline: 11,824.23
12,415.44
(96.67%)
reporting_token_benchmark::content_extraction_group::bench_content_extraction simple:setup_simple_message()📈 view plot
🚷 view threshold
3,930.00
(+2.44%)Baseline: 3,836.40
4,028.22
(97.56%)
reporting_token_benchmark::full_generation_group::bench_full_token_generation extended:setup_full_gen_extended()📈 view plot
🚷 view threshold
87,073.00
(-0.78%)Baseline: 87,759.42
92,147.39
(94.49%)
reporting_token_benchmark::full_generation_group::bench_full_token_generation simple:setup_full_gen_simple()📈 view plot
🚷 view threshold
79,022.00
(-0.97%)Baseline: 79,793.82
83,783.51
(94.32%)
reporting_token_benchmark::key_derivation_group::bench_key_derivation📈 view plot
🚷 view threshold
50,375.00
(-1.05%)Baseline: 50,911.82
53,457.41
(94.23%)
reporting_token_benchmark::message_encoding_group::bench_message_encoding extended:setup_extended_message()📈 view plot
🚷 view threshold
5,956.00
(+3.12%)Baseline: 5,776.04
6,064.85
(98.21%)
reporting_token_benchmark::message_encoding_group::bench_message_encoding simple:setup_simple_message()📈 view plot
🚷 view threshold
2,227.00
(+4.44%)Baseline: 2,132.36
2,238.98
(99.46%)
reporting_token_benchmark::token_calculation_group::bench_token_calculation📈 view plot
🚷 view threshold
21,920.00
(+0.00%)Baseline: 21,919.58
23,015.56
(95.24%)
🐰 View full continuous benchmarking report in Bencher

@jlucaso1

Copy link
Copy Markdown
Collaborator Author

@claude review

@claude

claude Bot commented Mar 31, 2026

Copy link
Copy Markdown

Claude finished @jlucaso1's task in 1m 25s —— View job


Code Review: perf!: reduce allocations in upload, send, and Jid paths

  • Read changed files and gather context
  • Review each change area
  • Post findings

Verdict: LGTM — clean, correct, well-scoped allocation reductions. A few minor observations below.


UploadResponse / MediaUploadInfo: Vec<u8>[u8; 32]

Good change. Media keys, SHA-256 file hashes, and encrypted hashes are always exactly 32 bytes — the type now encodes that invariant statically. This eliminates 3 heap allocations per UploadResponse construction and makes Clone a stack memcpy.

The From<UploadResponse> for MediaUploadInfo impl (src/upload.rs:244-254) now does a direct field copy instead of moving heap buffers — nice.

Unused _vec() helpers

media_key_vec(), file_sha256_vec(), and file_enc_sha256_vec() (src/upload.rs:257-267) are defined but never called anywhere in the codebase. Every call site already uses .to_vec() or .media_key.to_vec() directly. Consider removing these dead methods — they add public API surface without providing value. If the intent is to offer them for downstream consumers, that's fine, but worth a brief doc comment explaining that.

Status::send_image / send_video — by-value UploadResponse

Correct. The String fields (url, direct_path) are now moved instead of cloned, and the [u8; 32] fields use .to_vec() only where protobuf needs Vec<u8>. Good tradeoff.

DM send path — move instead of clone (wacore/src/send.rs:707-712)

message_for_encryption is borrowed by encode_to_vec() (takes &self) on line 707, then moved into DeviceSentMessage on line 712. Correct — eliminates one full protobuf Message clone per DM.

Group send path — eager phash (wacore/src/send.rs:1107-1113)

Computing participant_list_hash eagerly before passing distribution_list to encrypt_for_devices avoids cloning the Vec<Jid>. The semantics are preserved — phash is still derived from the full distribution list at send time. Clean refactor.

Jid::new: &strimpl Into<String> (wacore/binary/src/jid.rs:316)

Non-breaking for existing &str callers. Callers with owned Strings now avoid a reallocation. Standard Rust API pattern.

UploadOptions::with_media_key: Vec<u8>[u8; 32]

Removes the runtime try_from validation in Client::upload (src/upload.rs:312), since the type is now statically correct. The old error path ("media_key must be exactly 32 bytes") is gone — the compiler enforces it. Good.

Benchmark alert

The single Bencher alert (bench_decrypt_with_previous_session, +8.92%) is in libsignal_benchmark — completely unrelated to the changes in this PR. Likely CI noise.


Overall this is a well-targeted PR — each change removes unnecessary allocations with no semantic changes. The breaking changes are clearly documented in the PR description with migration examples.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/upload.rs (1)

232-242: ⚠️ Potential issue | 🟠 Major

Redact UploadResponse before these fields hit logs.

With media_key on this public type, the existing derived Debug will dump secret key material verbatim. Because the same struct also carries the retrieval paths, a stray {:?} log is enough to expose uploaded media metadata outside the process.

Suggested redacted Debug impl
-#[derive(Debug, Clone)]
+#[derive(Clone)]
 pub struct UploadResponse {
     pub url: String,
     pub direct_path: String,
     pub media_key: [u8; 32],
     pub file_enc_sha256: [u8; 32],
     pub file_sha256: [u8; 32],
     pub file_length: u64,
     /// Unix timestamp (seconds) when the media key was generated.
     pub media_key_timestamp: i64,
 }
+
+impl std::fmt::Debug for UploadResponse {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("UploadResponse")
+            .field("url", &self.url)
+            .field("direct_path", &self.direct_path)
+            .field("media_key", &"<redacted>")
+            .field("file_enc_sha256", &"<redacted>")
+            .field("file_sha256", &"<redacted>")
+            .field("file_length", &self.file_length)
+            .field("media_key_timestamp", &self.media_key_timestamp)
+            .finish()
+    }
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/upload.rs` around lines 232 - 242, The UploadResponse struct currently
derives Debug and will print secret key material; replace the derived Debug with
a custom impl for UploadResponse that redacts sensitive fields (media_key,
file_enc_sha256, file_sha256 and optionally media_key_timestamp) when formatted,
while still printing non-sensitive fields (url, direct_path, file_length);
locate the UploadResponse type and remove #[derive(Debug)] then add a Debug
implementation that emits placeholder text like "<redacted>" or hex-truncated
values for those specific fields to prevent key leakage in logs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@wacore/src/sticker_pack.rs`:
- Around line 212-219: The builder currently only serializes
zip_upload.media_key but ignores a mismatched thumbnail key; add an explicit
validation in the sticker pack builder (where zip_upload and thumb_upload are
used) to require zip_upload.media_key == thumb_upload.media_key and fail early
if not (e.g., return a Result::Err or propagate a typed error) so you never emit
a proto with incompatible media keys; alternatively enforce this invariant in
the input types (e.g., accept a single MediaKey used for both uploads) and
update the code paths that set file_sha256/thumbnail_sha256 to use the
validated/shared media_key.

---

Outside diff comments:
In `@src/upload.rs`:
- Around line 232-242: The UploadResponse struct currently derives Debug and
will print secret key material; replace the derived Debug with a custom impl for
UploadResponse that redacts sensitive fields (media_key, file_enc_sha256,
file_sha256 and optionally media_key_timestamp) when formatted, while still
printing non-sensitive fields (url, direct_path, file_length); locate the
UploadResponse type and remove #[derive(Debug)] then add a Debug implementation
that emits placeholder text like "<redacted>" or hex-truncated values for those
specific fields to prevent key leakage in logs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9395d103-82a0-46ce-ad82-7ee7ae0f4f3d

📥 Commits

Reviewing files that changed from the base of the PR and between 771d8e5 and a4ff6d7.

📒 Files selected for processing (7)
  • src/features/status.rs
  • src/upload.rs
  • tests/e2e/tests/media.rs
  • tests/e2e/tests/newsletter.rs
  • wacore/binary/src/jid.rs
  • wacore/src/send.rs
  • wacore/src/sticker_pack.rs

Comment thread wacore/src/sticker_pack.rs
- UploadResponse/MediaUploadInfo: Vec<u8> → [u8; 32] for media_key,
  file_sha256, file_enc_sha256 (eliminates heap allocs on construction
  and makes Clone a cheap memcpy)
- UploadOptions::media_key: Vec<u8> → [u8; 32] (removes try_from dance)
- Status::send_image/send_video: take UploadResponse by value (moves
  instead of cloning Strings)
- DM send: move message into DeviceSentMessage instead of cloning
- Group send: compute phash eagerly, avoiding full Vec<Jid> clone
- Jid::new: accept impl Into<String> so callers with owned Strings
  avoid reallocation
@jlucaso1
jlucaso1 force-pushed the perf/reduce-allocations-upload-send branch from a4ff6d7 to 6d51c9c Compare March 31, 2026 20:22
@jlucaso1
jlucaso1 merged commit e487c20 into main Mar 31, 2026
6 of 8 checks passed
@jlucaso1
jlucaso1 deleted the perf/reduce-allocations-upload-send branch March 31, 2026 20:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant