Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
43 changes: 43 additions & 0 deletions xmtp-ffi/include/xmtp_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,33 @@ enum XmtpFfiDeliveryStatus
typedef int32_t XmtpFfiDeliveryStatus;
#endif // __cplusplus

enum XmtpFfiReactionAction
#ifdef __cplusplus
: int32_t
#endif // __cplusplus
{
XMTP_FFI_REACTION_ACTION_UNSPECIFIED = 0,
XMTP_FFI_REACTION_ACTION_ADDED = 1,
XMTP_FFI_REACTION_ACTION_REMOVED = 2,
};
#ifndef __cplusplus
typedef int32_t XmtpFfiReactionAction;
#endif // __cplusplus

enum XmtpFfiReactionSchema
#ifdef __cplusplus
: int32_t
#endif // __cplusplus
{
XMTP_FFI_REACTION_SCHEMA_UNSPECIFIED = 0,
XMTP_FFI_REACTION_SCHEMA_UNICODE = 1,
XMTP_FFI_REACTION_SCHEMA_SHORTCODE = 2,
XMTP_FFI_REACTION_SCHEMA_CUSTOM = 3,
};
#ifndef __cplusplus
typedef int32_t XmtpFfiReactionSchema;
#endif // __cplusplus

/**
* Consent entity type.
*/
Expand Down Expand Up @@ -515,6 +542,18 @@ typedef struct XmtpFfiGroupPermissions {
struct XmtpFfiPermissionPolicySet policy_set;
} XmtpFfiGroupPermissions;

/**
* Ffi data for Reaction content
*/
typedef struct XmtpFfiReaction {
char *reference;
char *reference_inbox_id;
char *sender_inbox_id;
XmtpFfiReactionAction action;
char *content;
XmtpFfiReactionSchema schema;
} XmtpFfiReaction;

/**
* An enriched (decoded) message exposed to C.
* Contains metadata + the original encoded content bytes for upper-layer decoding.
Expand Down Expand Up @@ -558,6 +597,10 @@ typedef struct XmtpFfiEnrichedMessage {
* Expiration timestamp in nanoseconds (0 = no expiration).
*/
int64_t expires_at_ns;
/**
* Array of reactions
*/
struct XmtpFfiReaction *reactions;
/**
* Number of reactions.
*/
Expand Down
33 changes: 33 additions & 0 deletions xmtp-ffi/src/conversation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1532,6 +1532,38 @@ pub(crate) fn decoded_to_enriched(
let len = b.len() as i32;
(Box::into_raw(b) as *mut u8, len)
};

let reactions_vec: Vec<FfiReaction> = msg
.reactions
.iter()
.filter_map(|r| match &r.content {
xmtp_mls::messages::decoded_message::MessageBody::Reaction(reaction) => Some(FfiReaction {
reference: to_c_string(&hex::encode(&reaction.reference)),
reference_inbox_id: to_c_string(&reaction.reference_inbox_id),
sender_inbox_id: to_c_string(&r.metadata.sender_inbox_id),
action: match reaction.action() {
xmtp_proto::xmtp::mls::message_contents::content_types::ReactionAction::Added => FfiReactionAction::Added,
xmtp_proto::xmtp::mls::message_contents::content_types::ReactionAction::Removed => FfiReactionAction::Removed,
xmtp_proto::xmtp::mls::message_contents::content_types::ReactionAction::Unspecified => FfiReactionAction::Unspecified,
},
content: to_c_string(&reaction.content),
schema: match reaction.schema() {
xmtp_proto::xmtp::mls::message_contents::content_types::ReactionSchema::Unspecified => FfiReactionSchema::Unspecified,
xmtp_proto::xmtp::mls::message_contents::content_types::ReactionSchema::Unicode => FfiReactionSchema::Unicode,
xmtp_proto::xmtp::mls::message_contents::content_types::ReactionSchema::Shortcode => FfiReactionSchema::Shortcode,
xmtp_proto::xmtp::mls::message_contents::content_types::ReactionSchema::Custom => FfiReactionSchema::Custom,
},
}),
_ => None,
})
.collect();

let reactions = if reactions_vec.is_empty() {
std::ptr::null_mut()
} else {
Box::into_raw(reactions_vec.into_boxed_slice()) as *mut FfiReaction
Comment on lines +1561 to +1564
};
Comment on lines +1561 to +1565

FfiEnrichedMessage {
id: to_c_string(&hex::encode(&msg.metadata.id)),
group_id: to_c_string(&hex::encode(&msg.metadata.group_id)),
Expand All @@ -1556,6 +1588,7 @@ pub(crate) fn decoded_to_enriched(
None => std::ptr::null_mut(),
},
expires_at_ns: msg.metadata.expires_at_ns.unwrap_or(0),
reactions,
num_reactions: msg.reactions.len() as i32,
num_replies: msg.num_replies as i32,
content_bytes,
Expand Down
31 changes: 31 additions & 0 deletions xmtp-ffi/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::cell::RefCell;
use std::ffi::{CStr, CString, c_char};
use std::sync::OnceLock;

use tokio::runtime::Runtime;

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -205,6 +206,23 @@ pub enum FfiPreferenceUpdateKind {
HmacKey = 1,
}

#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FfiReactionAction {
Unspecified = 0,
Added = 1,
Removed = 2,
}

#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FfiReactionSchema {
Unspecified = 0,
Unicode = 1,
Shortcode = 2,
Custom = 3,
}

// ---------------------------------------------------------------------------
// Data transfer types (flat, repr(C))
// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -438,6 +456,17 @@ pub struct FfiGroupMetadata {
pub conversation_type: FfiConversationType,
}

/// Ffi data for Reaction content
#[repr(C)]
pub struct FfiReaction {
pub reference: *mut c_char,
pub reference_inbox_id: *mut c_char,
pub sender_inbox_id: *mut c_char,
pub action: FfiReactionAction,
pub content: *mut c_char,
pub schema: FfiReactionSchema,
}

/// Permission policy set for a conversation.
#[repr(C)]
pub struct FfiPermissionPolicySet {
Expand Down Expand Up @@ -483,6 +512,8 @@ pub struct FfiEnrichedMessage {
pub fallback_text: *mut c_char,
/// Expiration timestamp in nanoseconds (0 = no expiration).
pub expires_at_ns: i64,
/// Array of reactions
pub reactions: *mut FfiReaction,
/// Number of reactions.
pub num_reactions: i32,
/// Number of replies.
Expand Down
68 changes: 63 additions & 5 deletions xmtp-sys/src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,23 @@ pub enum XmtpFfiDeliveryStatus {
}
#[repr(i32)]
#[non_exhaustive]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum XmtpFfiReactionAction {
XMTP_FFI_REACTION_ACTION_UNSPECIFIED = 0,
XMTP_FFI_REACTION_ACTION_ADDED = 1,
XMTP_FFI_REACTION_ACTION_REMOVED = 2,
}
#[repr(i32)]
#[non_exhaustive]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum XmtpFfiReactionSchema {
XMTP_FFI_REACTION_SCHEMA_UNSPECIFIED = 0,
XMTP_FFI_REACTION_SCHEMA_UNICODE = 1,
XMTP_FFI_REACTION_SCHEMA_SHORTCODE = 2,
XMTP_FFI_REACTION_SCHEMA_CUSTOM = 3,
}
#[repr(i32)]
#[non_exhaustive]
#[doc = " Consent entity type."]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum XmtpFfiConsentEntityType {
Expand Down Expand Up @@ -693,6 +710,43 @@ impl Default for XmtpFfiGroupPermissions {
}
}
}
#[doc = " Ffi data for Reaction content"]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct XmtpFfiReaction {
pub reference: *mut ::core::ffi::c_char,
pub reference_inbox_id: *mut ::core::ffi::c_char,
pub sender_inbox_id: *mut ::core::ffi::c_char,
pub action: XmtpFfiReactionAction,
pub content: *mut ::core::ffi::c_char,
pub schema: XmtpFfiReactionSchema,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of XmtpFfiReaction"][::core::mem::size_of::<XmtpFfiReaction>() - 48usize];
["Alignment of XmtpFfiReaction"][::core::mem::align_of::<XmtpFfiReaction>() - 8usize];
["Offset of field: XmtpFfiReaction::reference"]
[::core::mem::offset_of!(XmtpFfiReaction, reference) - 0usize];
["Offset of field: XmtpFfiReaction::reference_inbox_id"]
[::core::mem::offset_of!(XmtpFfiReaction, reference_inbox_id) - 8usize];
["Offset of field: XmtpFfiReaction::sender_inbox_id"]
[::core::mem::offset_of!(XmtpFfiReaction, sender_inbox_id) - 16usize];
["Offset of field: XmtpFfiReaction::action"]
[::core::mem::offset_of!(XmtpFfiReaction, action) - 24usize];
["Offset of field: XmtpFfiReaction::content"]
[::core::mem::offset_of!(XmtpFfiReaction, content) - 32usize];
["Offset of field: XmtpFfiReaction::schema"]
[::core::mem::offset_of!(XmtpFfiReaction, schema) - 40usize];
};
impl Default for XmtpFfiReaction {
fn default() -> Self {
let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
unsafe {
::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " An enriched (decoded) message exposed to C.\n Contains metadata + the original encoded content bytes for upper-layer decoding."]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
Expand All @@ -717,6 +771,8 @@ pub struct XmtpFfiEnrichedMessage {
pub fallback_text: *mut ::core::ffi::c_char,
#[doc = " Expiration timestamp in nanoseconds (0 = no expiration)."]
pub expires_at_ns: i64,
#[doc = " Array of reactions"]
pub reactions: *mut XmtpFfiReaction,
#[doc = " Number of reactions."]
pub num_reactions: i32,
#[doc = " Number of replies."]
Expand All @@ -728,7 +784,7 @@ pub struct XmtpFfiEnrichedMessage {
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of XmtpFfiEnrichedMessage"][::core::mem::size_of::<XmtpFfiEnrichedMessage>() - 104usize];
["Size of XmtpFfiEnrichedMessage"][::core::mem::size_of::<XmtpFfiEnrichedMessage>() - 112usize];
["Alignment of XmtpFfiEnrichedMessage"]
[::core::mem::align_of::<XmtpFfiEnrichedMessage>() - 8usize];
["Offset of field: XmtpFfiEnrichedMessage::id"]
Expand All @@ -753,14 +809,16 @@ const _: () = {
[::core::mem::offset_of!(XmtpFfiEnrichedMessage, fallback_text) - 64usize];
["Offset of field: XmtpFfiEnrichedMessage::expires_at_ns"]
[::core::mem::offset_of!(XmtpFfiEnrichedMessage, expires_at_ns) - 72usize];
["Offset of field: XmtpFfiEnrichedMessage::reactions"]
[::core::mem::offset_of!(XmtpFfiEnrichedMessage, reactions) - 80usize];
["Offset of field: XmtpFfiEnrichedMessage::num_reactions"]
[::core::mem::offset_of!(XmtpFfiEnrichedMessage, num_reactions) - 80usize];
[::core::mem::offset_of!(XmtpFfiEnrichedMessage, num_reactions) - 88usize];
["Offset of field: XmtpFfiEnrichedMessage::num_replies"]
[::core::mem::offset_of!(XmtpFfiEnrichedMessage, num_replies) - 84usize];
[::core::mem::offset_of!(XmtpFfiEnrichedMessage, num_replies) - 92usize];
["Offset of field: XmtpFfiEnrichedMessage::content_bytes"]
[::core::mem::offset_of!(XmtpFfiEnrichedMessage, content_bytes) - 88usize];
[::core::mem::offset_of!(XmtpFfiEnrichedMessage, content_bytes) - 96usize];
["Offset of field: XmtpFfiEnrichedMessage::content_bytes_len"]
[::core::mem::offset_of!(XmtpFfiEnrichedMessage, content_bytes_len) - 96usize];
[::core::mem::offset_of!(XmtpFfiEnrichedMessage, content_bytes_len) - 104usize];
};
impl Default for XmtpFfiEnrichedMessage {
fn default() -> Self {
Expand Down
Loading
Loading