Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions wacore/src/types/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ impl Serialize for LazyHistorySync {
/// be at most 64 kinds.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
#[non_exhaustive]
pub enum EventKind {
Connected,
Disconnected,
Expand Down Expand Up @@ -247,8 +248,21 @@ pub enum EventKind {
NewsletterLiveUpdate,
RawNode,
MexNotification,
// When adding a variant, mind the 64-kind ceiling below (EventInterest packs
// each discriminant as a bit in a u64) and keep the guard pointing at the
// last variant.
}

impl EventKind {
/// Bit-index ceiling: [`EventInterest`] packs each kind's discriminant into a
/// `u64`, so there can be at most 64 kinds.
pub const CAPACITY: u8 = 64;
}

// Build-time tripwire: a new variant that would overflow EventInterest's bitmask
// fails compilation instead of silently corrupting the mask at runtime.
const _: () = assert!((EventKind::MexNotification as u8) < EventKind::CAPACITY);
Comment on lines +262 to +264

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consider adding an automated variant count check.

Listen, this assertion is smart, but it relies on developers remembering to update it manually whenever they add a variant. If someone adds EventKind::NewVariant but forgets to change MexNotification to NewVariant in this assertion, the check won't catch overflow until we hit 64+ variants.

The comment tells people what to do, and that's good. But we can do better. Consider adding a unit test that programmatically counts EventKind variants and asserts the total is ≤ 64. That way we get automated enforcement without relying on human discipline.

Something like:

#[test]
fn event_kind_capacity_enforced() {
    // If this test fails, we've exceeded EventInterest's u64 bitmask capacity.
    // Solution: either remove variants or switch EventInterest to u128.
    let count = /* derive variant count or maintain a manual list in test */;
    assert!(count <= EventKind::CAPACITY as usize);
}

This gives you defense in depth. The const assertion catches it if the last variant is updated correctly; the test catches it if someone forgets.

We need WhatsApp to scale. Manual processes don't scale.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wacore/src/types/events.rs` around lines 262 - 264, Add a unit test that
programmatically counts EventKind variants and asserts the count is <=
EventKind::CAPACITY to catch forgotten updates automatically; implement the test
(e.g., using a derived iterator like strum::EnumVariantNames/EnumIter or by
constructing a list of EventKind::... variants) and assert!(count <=
EventKind::CAPACITY as usize), referencing EventKind and EventInterest/CAPACITY
so the CI fails if the enum grows beyond the u64 bitmask capacity.


/// A set of [`EventKind`]s a handler wants delivered. The event bus skips
/// materializing and dispatching events whose kind no handler wants, so a
/// handler that subscribes to a few kinds never pays for boxing the others.
Expand Down
1 change: 1 addition & 0 deletions wacore/src/types/presence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub enum ChatPresenceMedia {

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(from = "String")]
#[non_exhaustive]
pub enum ReceiptType {
Delivered,
/// Sent but NOT delivered: WA Web downgrades a delivery ack to this when the
Expand Down
44 changes: 0 additions & 44 deletions wacore/src/types/user.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use waproto::whatsapp as wa;

#[derive(Debug, Clone)]
Expand All @@ -15,46 +14,3 @@ pub struct LocalChatSettings {
pub pinned: bool,
pub archived: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PrivacySetting {
All,
Contacts,
ContactBlacklist,
MatchLastSeen,
Known,
None,
#[serde(other)]
Undefined,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PrivacySettingType {
GroupAdd,
Last,
Status,
Profile,
ReadReceipts,
Online,
CallAdd,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PrivacySettings {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub group_add: Option<PrivacySetting>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_seen: Option<PrivacySetting>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub status: Option<PrivacySetting>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub profile: Option<PrivacySetting>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub read_receipts: Option<PrivacySetting>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub call_add: Option<PrivacySetting>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub online: Option<PrivacySetting>,
}
Loading