pub struct CompactMessage {Show 16 fields
pub id: [u8; 32],
pub at: u64,
pub expiration_secs: u32,
pub flags: MessageFlags,
pub npub_idx: u16,
pub replied_to: Option<Box<[u8; 32]>>,
pub replied_to_npub_idx: u16,
pub wrapper_id: Option<Box<[u8; 32]>>,
pub content: Box<str>,
pub replied_to_content: Option<Box<str>>,
pub attachments: TinyVec<CompactAttachment>,
pub reactions: TinyVec<CompactReaction>,
pub edit_history: Option<Box<Vec<EditEntry>>>,
pub preview_metadata: Option<Box<SiteMetadata>>,
pub emoji_tags: Option<Box<Vec<EmojiTag>>>,
pub addressed_bots: Option<Box<Vec<u16>>>,
}Expand description
Memory-efficient message with binary IDs and interned npubs.
Compared to the regular Message struct:
- IDs use
[u8; 32]instead of hex String (saves ~56 bytes each) - npubs use u16 index into interner (saves ~85 bytes each)
- Booleans packed into MessageFlags (saves ~24 bytes + 2 for replied_to_has_attachment)
- Boxed optional IDs (replied_to, wrapper_id) save ~40 bytes when None
- Compact timestamp (u32 seconds since 2020) saves 4 bytes
- TinyVec for attachments/reactions (8 bytes vs 24 = saves 32 bytes)
- Box
for content (8 bytes vs 24 = saves 16 bytes) - Total savings: ~350+ bytes per message
Fields§
§id: [u8; 32]Message ID as binary (64 hex chars -> 32 bytes)
at: u64Timestamp in milliseconds (full precision for sub-second ordering)
expiration_secs: u32NIP-40 expiry as unix SECONDS (0 = permanent). u32 holds it until 2106 and costs 4 bytes inline — self-destruct messages are rare and short- lived, so a boxed Option would only add heap churn on the purge path.
flags: MessageFlagsPacked boolean flags (mine, pending, failed, replied_to_has_attachment)
npub_idx: u16Index into NpubInterner for sender’s npub (NO_NPUB if none)
replied_to: Option<Box<[u8; 32]>>Replied-to message ID (boxed - None for ~70% of messages saves 24 bytes)
replied_to_npub_idx: u16Index into NpubInterner for replied-to author (NO_NPUB if none)
wrapper_id: Option<Box<[u8; 32]>>Wrapper event ID for gift-wrapped messages (boxed - saves 25 bytes when None)
content: Box<str>Message content (Box
replied_to_content: Option<Box<str>>Content of replied-to message
attachments: TinyVec<CompactAttachment>File attachments (CompactAttachment = ~120 bytes vs Attachment’s ~320 bytes)
reactions: TinyVec<CompactReaction>Emoji reactions (CompactReaction = ~82 bytes vs Reaction’s ~292 bytes)
edit_history: Option<Box<Vec<EditEntry>>>Edit history - boxed since <1% of messages are edited (saves 16 bytes inline)
preview_metadata: Option<Box<SiteMetadata>>Link preview metadata - boxed since ~216 bytes but rare (saves ~208 bytes)
NIP-30 emoji tags travelling with this rumor — boxed because the vast majority of messages have none, so the cold path stays cheap.
addressed_bots: Option<Box<Vec<u16>>>Bot routing targets as interned npub handles — boxed because only command invocations carry any.
Implementations§
Source§impl CompactMessage
impl CompactMessage
Sourcepub fn id_hex(&self) -> String
pub fn id_hex(&self) -> String
Get the message ID as a string (hex for event IDs, “pending-…” for pending)
Sourcepub fn replied_to_hex(&self) -> String
pub fn replied_to_hex(&self) -> String
Get the replied-to ID as a hex string, or empty if none
Sourcepub fn wrapper_id_hex(&self) -> Option<String>
pub fn wrapper_id_hex(&self) -> Option<String>
Get wrapper ID as hex string if present
Sourcepub fn timestamp_ms(&self) -> u64
pub fn timestamp_ms(&self) -> u64
Get timestamp as milliseconds (for compatibility with frontend)
Sourcepub fn apply_edit(
&mut self,
new_content: String,
edited_at: u64,
emoji_tags: Vec<EmojiTag>,
)
pub fn apply_edit( &mut self, new_content: String, edited_at: u64, emoji_tags: Vec<EmojiTag>, )
Apply an edit to this message.
emoji_tags are the NIP-30 custom-emoji tags resolved from the new
content; they’re adopted only when this edit is the newest revision so
an out-of-order older edit can’t clobber the live content’s emoji.
Sourcepub fn replied_to_has_attachment(&self) -> Option<bool>
pub fn replied_to_has_attachment(&self) -> Option<bool>
Get replied_to_has_attachment from flags
Sourcepub fn add_reaction(
&mut self,
reaction: Reaction,
interner: &mut NpubInterner,
) -> bool
pub fn add_reaction( &mut self, reaction: Reaction, interner: &mut NpubInterner, ) -> bool
Add a reaction to this message Note: Since TinyVec is immutable, this rebuilds the entire reactions list
Sourcepub fn remove_reaction(&mut self, reaction_id: &str) -> bool
pub fn remove_reaction(&mut self, reaction_id: &str) -> bool
Remove a reaction by its hex event id. Returns true if one was removed.
pub fn is_mine(&self) -> bool
pub fn is_pending(&self) -> bool
pub fn is_failed(&self) -> bool
pub fn set_pending(&mut self, value: bool)
pub fn set_failed(&mut self, value: bool)
pub fn set_mine(&mut self, value: bool)
Source§impl CompactMessage
impl CompactMessage
Sourcepub fn from_message(msg: &Message, interner: &mut NpubInterner) -> Self
pub fn from_message(msg: &Message, interner: &mut NpubInterner) -> Self
Convert from a regular Message (borrowed), interning npubs
Sourcepub fn from_message_owned(msg: Message, interner: &mut NpubInterner) -> Self
pub fn from_message_owned(msg: Message, interner: &mut NpubInterner) -> Self
Convert from a regular Message (owned) - ZERO-COPY for strings!
Takes ownership of the Message and moves strings directly. Use this when you don’t need the original Message anymore.
Sourcepub fn to_message(&self, interner: &NpubInterner) -> Message
pub fn to_message(&self, interner: &NpubInterner) -> Message
Convert back to a regular Message, resolving npubs from interner
Trait Implementations§
Source§impl Clone for CompactMessage
impl Clone for CompactMessage
Source§fn clone(&self) -> CompactMessage
fn clone(&self) -> CompactMessage
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for CompactMessage
impl Debug for CompactMessage
Auto Trait Implementations§
impl Freeze for CompactMessage
impl RefUnwindSafe for CompactMessage
impl Send for CompactMessage
impl Sync for CompactMessage
impl Unpin for CompactMessage
impl UnsafeUnpin for CompactMessage
impl UnwindSafe for CompactMessage
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more