pub struct OfflineProtocol { /* private fields */ }Expand description
Main entry point for the Offline Protocol SDK.
This struct combines all protocol components and provides a unified API for sending/receiving messages with automatic transport selection and reliable delivery.
Implementations§
Source§impl OfflineProtocol
impl OfflineProtocol
Sourcepub fn create_group(&mut self, group_name: &str) -> Result<GroupInfo>
pub fn create_group(&mut self, group_name: &str) -> Result<GroupInfo>
Creates a new MLS group.
The group is created locally via MLS. Members can be invited with
invite_to_group(). Messages sent via send_group_message() are
MLS-encrypted and route through whichever transport DORS selects.
If Internet is available the group is also registered with the
relay server for optimized fan-out.
Sourcepub fn invite_to_group(
&mut self,
group_id: &str,
invitee_user_id: &str,
) -> Result<()>
pub fn invite_to_group( &mut self, group_id: &str, invitee_user_id: &str, ) -> Result<()>
Invites a user to an MLS group.
Requires the invitee’s key package to be available in pending_key_packages.
Sends a Welcome to the invitee and a Commit to all existing members.
Admission is where recipient validation belongs. The removal and role paths deliberately do not validate: a roster entry admitted by an older build (before the id rules tightened) must stay removable, and a gate there would turn “a bad member exists” into “a bad member cannot be removed” — the wrong direction for a moderation control.
Sourcepub fn remove_from_group(
&mut self,
group_id: &str,
member_id: &str,
) -> Result<()>
pub fn remove_from_group( &mut self, group_id: &str, member_id: &str, ) -> Result<()>
Removes a member from an MLS group.
Sends a Commit to all remaining members.
Sourcepub fn leave_group(&mut self, group_id: &str) -> Result<()>
pub fn leave_group(&mut self, group_id: &str) -> Result<()>
Leaves an MLS group.
Notifies remaining members and then removes local group state.
Note: The MLS layer does not support self-removal Commits, so remaining
members receive a plaintext leave notification. The deterministic election
in handle_group_mls_leave will select one member to issue the MLS
remove-commit to properly advance the epoch.
Ordering note: Leave notifications are sent before deleting local MLS state. If all notification sends fail, local state is preserved and the caller receives an error so the leave can be retried. This prevents orphaned membership where the leaver is gone locally but peers never learn about the departure.
Sourcepub fn send_group_message(
&mut self,
group_id: &str,
content: &str,
priority: Option<MessagePriority>,
reply_to_msg: Option<&str>,
) -> Result<Vec<MessageId>>
pub fn send_group_message( &mut self, group_id: &str, content: &str, priority: Option<MessagePriority>, reply_to_msg: Option<&str>, ) -> Result<Vec<MessageId>>
Sends a message to all members of an MLS group.
If Internet transport is available and relay-enabled, sends a single
relay broadcast (__GRP_RELAY_BCAST__). Otherwise falls back to
per-member fan-out via send_internal_message() where each member’s
delivery goes through the full DORS/ACK/retry stack independently.
Sourcepub fn send_group_message_with(
&mut self,
group_id: &str,
content: &str,
options: GroupSendOptions,
) -> Result<Vec<MessageId>>
pub fn send_group_message_with( &mut self, group_id: &str, content: &str, options: GroupSendOptions, ) -> Result<Vec<MessageId>>
Like Self::send_group_message, with rich media fields.
The rich fields travel inside the MLS-sealed __RICH_V1__ body of
the group ciphertext, and only when every other member advertised
rich_versions (see GroupSendOptions); otherwise they are
silently dropped, never cleartext.
Sourcepub fn forward_message_to_group(
&mut self,
original_message: &Message,
group_id: &str,
priority: Option<MessagePriority>,
) -> Result<Vec<MessageId>>
pub fn forward_message_to_group( &mut self, original_message: &Message, group_id: &str, priority: Option<MessagePriority>, ) -> Result<Vec<MessageId>>
Forwards a message to all members of a group with forwarding attribution.
Similar to send_group_message but attaches ForwardInfo to preserve
the original sender and forward count. The message content is encrypted
via MLS for the group and fan-out follows the same path as regular
group messages (including relay broadcast when available).
When every other group member advertised the sealed rich payload, the
attribution and the original media_metadata — including cloud-media
encryption_key/iv secrets, which only the sealed body may carry —
travel inside the group MLS ciphertext, so forwarded cloud media stays
openable. Otherwise the media metadata is dropped (never cleartext)
and only the hop-visible payload attribution survives.
Sourcepub fn group_rich_readiness(&self, group_id: &str) -> Result<GroupRichReadiness>
pub fn group_rich_readiness(&self, group_id: &str) -> Result<GroupRichReadiness>
Whether a rich group send right now would seal its extras, and which
members are in the way. See GroupRichReadiness. Read-only: uses
the fan-out cache with an MLS fallback but never mutates state, and
does not probe unknown members (the send path’s drop branch does).
Sourcepub fn group_relay_sync_state(&self, group_id: &str) -> RelaySyncState
pub fn group_relay_sync_state(&self, group_id: &str) -> RelaySyncState
The relay-side registration state of a group. See RelaySyncState.
Synced wins over an outstanding re-registration: once the relay has
positively acknowledged the group on this connection, its registry
entry survives regardless of any in-flight idempotent re-sync, so
relay-dependent commands are already safe to issue.
Sourcepub fn request_group_relay_registration(
&mut self,
group_id: &str,
) -> Result<bool>
pub fn request_group_relay_registration( &mut self, group_id: &str, ) -> Result<bool>
Registers (or re-registers) a group with the relay server on demand.
The supported path for making a mesh-created group known to the
relay before issuing relay-dependent server commands for it (invite
links, server-side fan-out) — never raw-send CreateGroup. The
outcome arrives asynchronously as GroupRelaySyncChanged:
synced: true, reason: "registered" on the relay’s ack, false
with "error" / "ack_timeout" on denial or a relay that never
answers. Idempotent: an already-Synced group returns Ok(true)
without re-sending (the automatic re-sync on membership changes
covers roster updates).
Returns Ok(true) when the registration frame was queued (or the
group is already synced), Ok(false) when relay grouping is
disabled or the Internet transport is unavailable, Err when the
group is unknown locally.
Sourcepub fn list_groups(&self) -> Result<Vec<String>>
pub fn list_groups(&self) -> Result<Vec<String>>
Lists all MLS groups (excluding 1:1 sessions).
Sourcepub fn get_group_info(&self, group_id: &str) -> Result<Option<GroupInfo>>
pub fn get_group_info(&self, group_id: &str) -> Result<Option<GroupInfo>>
Gets information about an MLS group.
Sourcepub fn set_member_role(
&mut self,
group_id: &str,
target_user_id: &str,
role: GroupRole,
) -> Result<()>
pub fn set_member_role( &mut self, group_id: &str, target_user_id: &str, role: GroupRole, ) -> Result<()>
Changes a member’s role in a group (admin only). Broadcasts the change to all group members.
Sourcepub fn get_member_role(
&self,
group_id: &str,
user_id: &str,
) -> Result<GroupRole>
pub fn get_member_role( &self, group_id: &str, user_id: &str, ) -> Result<GroupRole>
Gets a member’s role in a group.
A group that exists but has no role metadata (created before role
tracking) reports the same default an unrecorded user gets: Member.
Sourcepub fn get_group_roles(
&self,
group_id: &str,
) -> Result<HashMap<String, GroupRole>>
pub fn get_group_roles( &self, group_id: &str, ) -> Result<HashMap<String, GroupRole>>
Gets all member roles in a group.
A group that exists but has no role metadata (created before role tracking) reports no explicit roles.
Sourcepub fn rename_group(&mut self, group_id: &str, new_name: &str) -> Result<()>
pub fn rename_group(&mut self, group_id: &str, new_name: &str) -> Result<()>
Renames a group (admin only). Updates the local group name and broadcasts the change to all members.
Sourcepub fn set_relay_capabilities(&mut self, capabilities: Vec<String>)
pub fn set_relay_capabilities(&mut self, capabilities: Vec<String>)
Replaces the set of capability tokens advertised by the connected relay.
Called by the platform internet bridge with the capabilities list
from the relay’s Authenticated answer, before it reports the
transport up via internet_status_changed(true) — the false→true
flush must already see the capabilities, or the first sends after a
reconnect would take the capability-less path. Wholesale replace:
each authentication describes the relay actually connected now.
Relays that predate the advertisement yield an empty list, which
reads as “no v2 contract” and keeps group sends on per-member
fan-out.
The list is wire-supplied: it is bounded to
MAX_RELAY_CAPABILITIES tokens of at most
MAX_RELAY_CAPABILITY_TOKEN_BYTES bytes each; excess entries and
oversized tokens are dropped.
Sourcepub fn handle_relay_group_delivery_report(
&mut self,
report_json: &str,
) -> Result<()>
pub fn handle_relay_group_delivery_report( &mut self, report_json: &str, ) -> Result<()>
Consumes a relay GroupMessageSent settled delivery report
(forwarded verbatim by the platform bridge) for a broadcast this
sender has in flight.
Settles the RelayBroadcastPending entry correlated by
message_id, then re-sends a per-member __GRP_MLS_MSG__ copy —
through the ordinary outbox/ACK/park ladder — to every MLS roster
member the relay did not reach over a socket or a push: the members
it names in missed, plus every roster member it does not name at
all (the relay’s registered roster can be a strict subset of the MLS
roster, so “not mentioned” must read as “not reached”, never as
“covered”). Duplicates are safe: the copies carry the logical id, so
a member that did receive the relay’s copy absorbs them by dedup.
Reports that correlate with nothing (already settled by a previous
attempt’s report, or downgraded meanwhile) are ignored. A report
whose group_id does not match the armed entry is ignored too — the
entry stays armed and the timeout path recovers.
Emits Event::group_message_delivery_report with the relay’s
delivered/pushed lists and the members re-issued per-member.
Source§impl OfflineProtocol
impl OfflineProtocol
Sourcepub fn block_user(&mut self, user_id: &str) -> Result<()>
pub fn block_user(&mut self, user_id: &str) -> Result<()>
Blocks a user. Messages from this user will be silently dropped (no ACK sent, no event emitted). The blocked user receives no notification.
Blocking is idempotent — calling this for an already-blocked user succeeds silently.
Sourcepub fn unblock_user(&mut self, user_id: &str) -> Result<()>
pub fn unblock_user(&mut self, user_id: &str) -> Result<()>
Unblocks a previously blocked user.
Clears any stale MLS session state, pending key packages, and queued messages for the peer so that a fresh key exchange can occur on re-discovery.
Unblocking a non-blocked user succeeds silently.
Sourcepub fn get_blocked_users(&self) -> Vec<String>
pub fn get_blocked_users(&self) -> Vec<String>
Returns the list of currently blocked user IDs, sorted for stable output.
Sourcepub fn is_user_blocked(&self, user_id: &str) -> bool
pub fn is_user_blocked(&self, user_id: &str) -> bool
Checks whether a user is currently blocked.
Source§impl OfflineProtocol
impl OfflineProtocol
Sourcepub fn state(&self) -> ProtocolState
pub fn state(&self) -> ProtocolState
Gets the current protocol state.
Sourcepub fn config(&self) -> &ProtocolConfig
pub fn config(&self) -> &ProtocolConfig
Gets the configuration.
Sourcepub fn mesh_services(&self) -> &MeshServices
pub fn mesh_services(&self) -> &MeshServices
Gets a reference to the mesh services registry.
Sourcepub fn transport_manager_mut(&mut self) -> &mut TransportManager
pub fn transport_manager_mut(&mut self) -> &mut TransportManager
Gets a mutable reference to the transport manager.
This allows external code (e.g., FFI) to add transports dynamically.
Sourcepub fn transport_manager(&self) -> &TransportManager
pub fn transport_manager(&self) -> &TransportManager
Gets a reference to the transport manager.
Sourcepub fn file_transfer_manager_mut(&mut self) -> &mut FileTransferManager
pub fn file_transfer_manager_mut(&mut self) -> &mut FileTransferManager
Returns a mutable reference to the file transfer manager.
Sourcepub fn file_transfer_manager(&self) -> &FileTransferManager
pub fn file_transfer_manager(&self) -> &FileTransferManager
Returns a reference to the file transfer manager.
Sourcepub fn mls_manager(&self) -> Option<&Arc<RwLock<MlsManager>>>
pub fn mls_manager(&self) -> Option<&Arc<RwLock<MlsManager>>>
Gets access to the MLS manager for advanced operations.
Returns None if MLS is not initialized.
Sourcepub fn update_dors_config(&mut self, config: DorsConfig)
pub fn update_dors_config(&mut self, config: DorsConfig)
Updates the DORS configuration at runtime.
This replaces the current DORS selector configuration with the provided config.
Sourcepub fn update_ack_config(&mut self, config: AckConfig) -> Result<()>
pub fn update_ack_config(&mut self, config: AckConfig) -> Result<()>
Updates the ACK configuration at runtime.
Note: This affects new ACK registrations; existing pending ACKs keep their original timeout.
Validated the same way Self::update_retry_config is — by building
the candidate configuration and running the real validator — rather than
by repeating its checks inline. Hand-rolled copies drift: a constraint
added to ProtocolConfig::validate for a new AckConfig field would be
enforced at construction and silently skipped on the runtime-update path.
Sourcepub fn update_retry_config(&mut self, config: RetryConfig) -> Result<()>
pub fn update_retry_config(&mut self, config: RetryConfig) -> Result<()>
Updates the retry configuration at runtime.
Note: This affects new retry entries; existing entries keep their original timing.
Sourcepub fn update_dedup_config(&mut self, config: DeduplicatorConfig) -> Result<()>
pub fn update_dedup_config(&mut self, config: DeduplicatorConfig) -> Result<()>
Updates the deduplication configuration at runtime.
Note: This clears the deduplication cache and applies the new config.
Validated the same way its two siblings are, and for a reason that only
appeared once they were. Both of those run the whole
ProtocolConfig::validate, which checks the Bloom parameters this
method installs — so while this one accepted anything, a configuration
it had already stored could make a perfectly valid
Self::update_retry_config fail, complaining about a Bloom filter the
caller never mentioned. Deduplicator::with_config fails safe on those
values rather than panicking, so the cost was a confusing rejection
rather than a crash — but a rejection attributed to the wrong call is
its own kind of expensive.
Sourcepub fn deduplicator_stats(&self) -> DeduplicatorStats
pub fn deduplicator_stats(&self) -> DeduplicatorStats
Gets deduplicator statistics for monitoring.
Sourcepub fn pending_queue_metrics(&self) -> PendingQueueMetrics
pub fn pending_queue_metrics(&self) -> PendingQueueMetrics
Gets pending encrypted message queue counters and gauges.
Sourcepub fn pending_ack_count(&self) -> usize
pub fn pending_ack_count(&self) -> usize
Gets the current ACK manager statistics.
Sourcepub fn retry_queue_size(&self) -> usize
pub fn retry_queue_size(&self) -> usize
Gets the current retry queue statistics.
Sourcepub fn is_known_peer(&self, peer_id: &str) -> bool
pub fn is_known_peer(&self, peer_id: &str) -> bool
Returns whether peer_id is currently tracked as a discovered
neighbor. Populated by Self::on_neighbor_discovered and cleared
by Self::on_neighbor_lost, by the periodic TTL sweep when the
peer has not been re-seen for KNOWN_PEER_TTL_SECS, or by
least-recently-seen eviction when tracking is at capacity — so this
can flip to false without any explicit loss signal. Blocked users
are never tracked.
Sourcepub fn mesh_relay_stats(&self) -> MeshRelayStats
pub fn mesh_relay_stats(&self) -> MeshRelayStats
Reports how much traffic this device is carrying for other people.
Useful for showing a user what their device is contributing, and for
spotting a neighborhood in trouble: a rising rate_deferred means
forwarding is hitting its ceiling, and peer_rate_limited means a
single neighbor is sending more than its share. dropped_for_capacity
is expected to stay at zero — see MeshRelayStats::dropped_for_capacity.
Sourcepub fn register_service(&mut self, descriptor: ServiceDescriptor) -> Result<()>
pub fn register_service(&mut self, descriptor: ServiceDescriptor) -> Result<()>
Registers a local service that this node offers.
Sourcepub fn unregister_service(&mut self, service_id: &str) -> Result<bool>
pub fn unregister_service(&mut self, service_id: &str) -> Result<bool>
Unregisters a local service. Returns true if the service was found and removed.
Sourcepub fn discover_services(&mut self, service_id: Option<&str>) -> Result<String>
pub fn discover_services(&mut self, service_id: Option<&str>) -> Result<String>
Broadcasts a service discovery query to all known peers.
Returns a query_id. Responses arrive asynchronously as ServiceDiscovered events.
Note: Discovery responses currently travel only one hop back (to the immediate sender of the query). Multi-hop response relay is not yet implemented, so services more than one hop away will generate responses that reach intermediate forwarders but not the original querier.
Source§impl OfflineProtocol
impl OfflineProtocol
Sourcepub fn handle_resolved_key_package(&mut self, data: &[u8]) -> Result<()>
pub fn handle_resolved_key_package(&mut self, data: &[u8]) -> Result<()>
Handles a key-package record returned by a resolution query.
Deliberately narrow: this channel answers exactly one question, so anything that is not a key package is dropped rather than dispatched. The records come from a public routing tag that anyone may publish to, and a query returns whatever the relay holds there — without this gate, a squatter could deliver any internal control frame through a path that never went past the receive loop’s dedup and block checks.
What survives the gate is not trusted here either. It goes through
process_internal_message_via, so the Ed25519 signature and the
sender-address derivation decide whose key package it is: a record
planted at the queried peer’s tag by somebody else is signed by that
party’s key, which derives to that party’s address, so it registers
under their identity — never under the peer we asked about. A record
signed by nobody is refused outright.
Source§impl OfflineProtocol
impl OfflineProtocol
Sourcepub fn receive_message(&mut self) -> Option<Message>
pub fn receive_message(&mut self) -> Option<Message>
Receives the next available message.
Source§impl OfflineProtocol
impl OfflineProtocol
Sourcepub fn on_relay_address_declared(&self, declared: &str)
pub fn on_relay_address_declared(&self, declared: &str)
Verifies the relay’s AddressDeclared acknowledgement against the
address this node actually holds.
This is the lockstep assertion for the relay leg of addressing. The
bridge declares Self::local_address and signs a proof over a
per-connection challenge; the relay verifies that the declared address
derives from the signing key and echoes back what it bound. Agreement
means every frame the relay forwards from here on is attributed to the
same identity the core stamps into Message.sender, which is what
validate_transport_sender strict-matches on the receiving side.
A disagreement is reported, never acted on: see
SecurityWarningCode::RelayAddressBindingMismatch for why tearing the
connection down would buy nothing. Callers pass the echoed address
verbatim — an empty or malformed one simply cannot match and is reported
like any other mismatch.
Reached only through the FFI’s dedicated entry point, not through message-plane injection, so a notification payload cannot synthesize it.
Sourcepub fn on_relay_address_declaration_refused(&self, reason: &str)
pub fn on_relay_address_declaration_refused(&self, reason: &str)
Records the relay refusing this connection’s address declaration.
Non-fatal by contract on both sides — the connection stays authenticated
and keeps working in account-name space. What degrades is new MLS
session establishment over the relay; see
SecurityWarningCode::RelayAddressDeclarationRefused. reason is the
relay’s own text: opaque, remote-chosen, and logged rather than
emitted — an event field never carries text a remote party wrote.
Attributed to this node rather than to a peer (the failure is ours, and no peer is involved), following the same convention as the Nostr slot-exhaustion warning.
Source§impl OfflineProtocol
impl OfflineProtocol
Sourcepub fn send_message(
&mut self,
recipient: impl Into<String>,
content: impl Into<String>,
priority: Option<MessagePriority>,
reply_to_msg: Option<impl Into<String>>,
) -> Result<MessageId>
pub fn send_message( &mut self, recipient: impl Into<String>, content: impl Into<String>, priority: Option<MessagePriority>, reply_to_msg: Option<impl Into<String>>, ) -> Result<MessageId>
Sends a message.
§Arguments
recipient- Recipient’s user IDcontent- Message contentpriority- Message priority (optional, defaults to Medium)reply_to_msg- ID of the message this is replying to (optional)
§Returns
Returns the message ID if successful.
§Auto-Encryption
When encryption is enabled and MLS is initialized, messages are automatically
encrypted before sending. If no session exists with the recipient but we have
their key package, a session is created automatically. If no key package is
available and store_pending is enabled, the message is queued until a key
package is received.
Sourcepub fn send_message_with(
&mut self,
recipient: impl Into<String>,
content: impl Into<String>,
options: SendMessageOptions,
) -> Result<MessageId>
pub fn send_message_with( &mut self, recipient: impl Into<String>, content: impl Into<String>, options: SendMessageOptions, ) -> Result<MessageId>
Sends a message with rich options: priority and reply threading (as
on Self::send_message), plus quoted-reply context, rich media
metadata, and forward attribution.
The rich fields only ever travel inside the MLS-sealed __RICH_V1__
body, and only toward recipients whose key package advertised
rich_versions support (gated by
EncryptionConfig::rich_payload_enabled). Toward anyone else they
are silently dropped — never sent cleartext — so the message degrades
to plain text with reply_to_msg threading intact.
Returns InvalidArgument for ContentType::FileChunk (an internal
transport content type — the receiver would swallow the message into
its file-transfer manager) and for rich extras whose serialized size
exceeds 32 KiB (oversized bodies inflate the MLS plaintext into heavy
transport fragmentation).
Sourcepub fn forward_message(
&mut self,
original_message: &Message,
new_recipient: impl Into<String>,
priority: Option<MessagePriority>,
) -> Result<MessageId>
pub fn forward_message( &mut self, original_message: &Message, new_recipient: impl Into<String>, priority: Option<MessagePriority>, ) -> Result<MessageId>
Forwards a message to a new recipient with attribution to the original sender.
Creates a new message with the original content and attaches ForwardInfo
tracking the original sender, message ID, timestamp, and forward count.
If the message was already forwarded, the original attribution is preserved
and forward_count is incremented.
Toward a recipient that advertised the sealed rich payload, the
attribution and the original media_metadata — including any
cloud-media encryption_key/iv secrets — travel inside the MLS-sealed
__RICH_V1__ body, so forwarded cloud media stays openable. Toward
anyone else they ride the legacy cleartext outer fields, from which
the transport chokepoint strips the secrets — attribution and display
hints survive, but the media key cannot be delivered.
§Arguments
original_message- The message to forwardnew_recipient- Recipient’s user IDpriority- Message priority (optional, defaults to Medium)
§Returns
Returns the new message ID if successful.
Sourcepub fn send_message_via_transport(
&mut self,
recipient: impl Into<String>,
content: impl Into<String>,
priority: Option<MessagePriority>,
transport: TransportType,
reply_to_msg: Option<impl Into<String>>,
) -> Result<MessageId>
pub fn send_message_via_transport( &mut self, recipient: impl Into<String>, content: impl Into<String>, priority: Option<MessagePriority>, transport: TransportType, reply_to_msg: Option<impl Into<String>>, ) -> Result<MessageId>
Sends a message via a specific transport type (bypassing DORS).
Sourcepub fn send_media(
&mut self,
recipient: impl Into<String>,
file_data: Vec<u8>,
file_name: impl Into<String>,
content_type: ContentType,
media_metadata: Option<MediaMetadata>,
) -> Result<String>
pub fn send_media( &mut self, recipient: impl Into<String>, file_data: Vec<u8>, file_name: impl Into<String>, content_type: ContentType, media_metadata: Option<MediaMetadata>, ) -> Result<String>
Sends a media attachment (image, video, audio, file, etc.) to a recipient.
The file data is chunked and each chunk is sent as an individual message
with content_type: FileChunk. The first chunk carries the full
MediaMetadata so the receiver can display a preview before all chunks
arrive. Individual chunk messages require ACKs and participate in retry
logic so delivery is tracked and recoverable per chunk. MediaSent is
emitted only after all chunks are ACKed.
§Encryption
With auto-encryption active (encryption enabled and MLS initialized),
chunk bytes — and the chunk-0 media metadata and original content type —
travel inside MLS ciphertext, using the same session the text path uses.
The session must already be confirmed: media is never queued pending
establishment and never falls back to plaintext. When the session is
not ready this returns Error::SessionNotReady (after kicking
establishment if a key package is available); retry after the
secure_session_established event. When encryption is required but MLS
is not initialized this returns Error::EncryptFailed. Plaintext
chunks are sent only when auto-encryption is inactive AND
require_encryption was explicitly set to false (it defaults to
true): the explicit encryption opt-out, or encryption enabled but
MLS never initialized (matching the text path). Every plaintext
transfer emits a
crate::events::SecurityWarningCode::PlaintextSend warning, once
per peer.
Returns a file_id that can be used to track progress or cancel.
Sourcepub fn send_media_with(
&mut self,
recipient: impl Into<String>,
file_data: Vec<u8>,
file_name: impl Into<String>,
content_type: ContentType,
options: MediaSendOptions,
) -> Result<String>
pub fn send_media_with( &mut self, recipient: impl Into<String>, file_data: Vec<u8>, file_name: impl Into<String>, content_type: ContentType, options: MediaSendOptions, ) -> Result<String>
Sends a media attachment with rich options: the chunk-0 media
metadata (as on Self::send_media), plus caption, reply threading,
quoted-reply context, forward attribution, and an optional
caller-supplied file_id.
The rich fields only ever travel inside the MLS-sealed chunk-0
plaintext (under the v2 media envelope), and only toward recipients
whose key package advertised rich_versions support (gated by
EncryptionConfig::rich_payload_enabled). Toward anyone else —
including every plaintext (encryption opt-out) transfer — they are
silently dropped, never sent cleartext.
Returns InvalidArgument for an unparsable reply_to_msg, rich
extras whose serialized size exceeds 32 KiB, or a file_id that is
empty, over the wire field bound, or already carried by an active
outbound transfer. Encryption preconditions match
Self::send_media.
Sourcepub fn on_transport_send_confirmed(&mut self, message_id: &str) -> Result<()>
pub fn on_transport_send_confirmed(&mut self, message_id: &str) -> Result<()>
Confirms that a message was successfully sent by the transport layer.
Sourcepub fn on_transport_send_failed(
&mut self,
message_id: &str,
transport_error: Option<String>,
) -> Result<()>
pub fn on_transport_send_failed( &mut self, message_id: &str, transport_error: Option<String>, ) -> Result<()>
Handles asynchronous transport send failures for pending welcome sends and outbound connection requests.
Sourcepub fn internet_control_op(
&self,
message: &Message,
) -> Option<(&'static str, String)>
pub fn internet_control_op( &self, message: &Message, ) -> Option<(&'static str, String)>
Classifies an outbound internet frame as a server-plane control op the
platform bridge should translate to (or mirror as) a relay-native
message instead of an opaque SendMessage.
Returns (op, payload) where payload is the JSON after the prefix
(empty string for payload-less ops). None means normal traffic —
send verbatim.
Ops and their bridge semantics:
group_relay_register/group_relay_broadcast— self-addressed relay hints (send_group_messageoptimization); REPLACE with relay-nativeCreateGroup+member deltas /SendGroupMessage. The relay does not intercept content prefixes, so untranslated frames would be echoed back uselessly.group_mls_leave— TAP, don’t replace: the per-member leave notification must still be delivered verbatim, but the bridge also sends one relay-nativeLeaveGroupso the relay’s group registry (which feeds invite links and broadcast fan-out) doesn’t go stale.
Connection ops (__CONN_REQ__/__CONN_ACC__/__CONN_REJ__/
__CONN_CAN__) deliberately do NOT classify: they ship verbatim as
opaque SendMessage frames so the Ed25519 control signature in the
message metadata survives to the receiver’s security gate. The former
relay-native translation (SendConnectionRequest & co.) rebuilt them
unsigned on the receiving bridge, which the gate now rejects
unconditionally — control traffic must be signed. Verbatim
also gains the relay’s push-notification fallback for offline
recipients, which the relay-native connection frames never had. The
cost is that pre-SDK relay clients (which only speak the relay-native
frames) no longer interoperate with connection ops — an accepted
trade: the SDK’s internet transport is the only supported relay
client.
Only frames originated by this device classify. The mesh relays
third-party messages verbatim (try_relay_message). The relay-hint
ops additionally require the self-addressed recipient (that is how
the core marks them as hints rather than traffic), so they classify
only when sender AND recipient are both this device.
Self-origination is proven by hop_count == 0, not by the sender
field: sender is an unauthenticated wire field, so a mesh peer
could forge sender == self on a frame we then relay — but
try_relay_message increments the hop before re-sending, while every
locally-originated frame leaves send_internal_message at hop 0.
(Defense in depth: the receive loop also drops inbound frames
claiming our own origin before they can reach the relay path.)
Sourcepub fn send_connection_request(
&mut self,
recipient: &str,
sender_name: &str,
key_package: Option<Vec<u8>>,
initial_message: Option<String>,
) -> Result<MessageId>
pub fn send_connection_request( &mut self, recipient: &str, sender_name: &str, key_package: Option<Vec<u8>>, initial_message: Option<String>, ) -> Result<MessageId>
Sends a connection request to another user via any available transport.
The request is routed through DORS, so it works over Internet, BLE, or WiFi Direct.
§Arguments
recipient- The user ID of the recipientsender_name- Display name of the senderkey_package- Optional MLS key package for encrypted session setupinitial_message- Optional first message shown with the request (surfaced verbatim in the recipient’sConnectionRequestReceivedevent; apps typically seed the conversation with it on accept). At most 4096 UTF-8 bytes (MAX_INITIAL_MESSAGE_BYTES, crate-private) — longer input is rejected withError::InvalidArgument.
§Encryption
Connection requests are internal control messages sent in plaintext,
exempt from require_encryption (same as key packages and welcome
messages) — an initial_message is therefore NOT end-to-end
encrypted and should be treated like the sender display name.
Sourcepub fn accept_connection_request(
&mut self,
recipient: &str,
accepter_name: &str,
key_package: Option<Vec<u8>>,
) -> Result<MessageId>
pub fn accept_connection_request( &mut self, recipient: &str, accepter_name: &str, key_package: Option<Vec<u8>>, ) -> Result<MessageId>
Accepts a connection request from another user via any available transport.
The response is routed through DORS, so it works over Internet, BLE, or WiFi Direct.
§Arguments
recipient- The user ID of the original requesteraccepter_name- Display name of the accepting partykey_package- Optional MLS key package for encrypted session setup
§Encryption
Connection accepts are internal control messages sent in plaintext,
exempt from require_encryption (same as key packages and welcome messages).
Sourcepub fn reject_connection_request(
&mut self,
recipient: &str,
) -> Result<MessageId>
pub fn reject_connection_request( &mut self, recipient: &str, ) -> Result<MessageId>
Rejects a connection request from another user via any available transport.
The response is routed through DORS, so it works over Internet, BLE, or WiFi Direct.
§Arguments
recipient- The user ID of the original requester
§Encryption
Connection rejects are internal control messages sent in plaintext,
exempt from require_encryption (same as key packages and welcome messages).
Sourcepub fn cancel_connection_request(
&mut self,
recipient: &str,
) -> Result<MessageId>
pub fn cancel_connection_request( &mut self, recipient: &str, ) -> Result<MessageId>
Cancels a previously sent connection request via any available transport.
The cancellation is routed through DORS, so it works over Internet, BLE, or WiFi Direct.
§Arguments
recipient- The user ID of the original request recipient
§Encryption
Connection cancellations are internal control messages sent in plaintext,
exempt from require_encryption (same as key packages and welcome messages).
Sourcepub fn send_presence_update(
&mut self,
recipient: &str,
status: PresenceStatus,
) -> Result<MessageId>
pub fn send_presence_update( &mut self, recipient: &str, status: PresenceStatus, ) -> Result<MessageId>
Sends a presence update to a single peer (unicast).
This sends to one recipient at a time. To broadcast presence to multiple peers, the caller must invoke this method once per peer.
§Arguments
recipient- The user ID of the peer to notifystatus- Presence status
Sourcepub fn send_typing_indicator(
&mut self,
recipient: &str,
conversation_id: &str,
is_typing: bool,
) -> Result<MessageId>
pub fn send_typing_indicator( &mut self, recipient: &str, conversation_id: &str, is_typing: bool, ) -> Result<MessageId>
Sends a typing indicator to a peer.
§Arguments
recipient- The user ID of the peer to notifyconversation_id- Opaque conversation key, carried to the peer and echoed back on its event. Never parsed or routed on. Conventionally the peer’s address for a DM and the group id for a group; any stable string works, but a display name does not (those change).is_typing- Whether the user started or stopped typing
Sourcepub fn send_read_receipt(
&mut self,
recipient: &str,
message_ids: Vec<String>,
) -> Result<MessageId>
pub fn send_read_receipt( &mut self, recipient: &str, message_ids: Vec<String>, ) -> Result<MessageId>
Sends a read receipt to a peer, indicating that the given messages have been read.
§Arguments
recipient- The user ID of the peer who sent the messagesmessage_ids- IDs of the messages that were read (max 256)
Source§impl OfflineProtocol
impl OfflineProtocol
Sourcepub fn on_peer_presence(
&mut self,
peer_id: &str,
online: bool,
last_seen_ms: Option<i64>,
)
pub fn on_peer_presence( &mut self, peer_id: &str, online: bool, last_seen_ms: Option<i64>, )
Ingests an authoritative per-peer presence signal (the internet relay’s
PresenceStatusWithLastSeen answer, bridged by the platform layer).
online drives the same reachability machinery as a transport-level
discovery — outbox flush, welcome re-arm, auto key exchange — plus a
rescue for the store-less-relay hole: a welcome whose wire send was
confirmed (Sent) while the peer was actually offline was dropped by
the relay (it forwards or pushes, never stores), and
Self::rearm_welcome_for_peer deliberately never touches Sent.
The peer being provably online is the safe moment to rebuild and
re-send it: if the original did land, the receiver dedups by message
id and the confirmation probe resolves the lifecycle.
offline parks retry-pending welcomes pending a reachability edge,
without burning budget. In-flight records (SendAttempted) are left
to their confirm deadline — a DeliveryError-driven failure or the
confirm timeout resolves them, after which the next offline tick parks.
The welcome re-arm/re-send on the online edge is throttled per peer
with exponential backoff (WELCOME_PRESENCE_RESCUE_BASE_SECS ..
WELCOME_PRESENCE_RESCUE_MAX_SECS): presence answers arrive on the
platform’s ~20s watch tick, and a peer that is online but can never
prove the session (stale key package after a reinstall, incompatible
version) must not be re-sent the multi-frame MLS welcome on every
tick forever. A throttled online tick still flushes queued data-plane
traffic for the peer.
Emits presence_updated with source: Internet — this function is
the relay-sourced half of the unified stream and must only be fed
relay-observed signals (bridged via internet_peer_presence);
peer-sent __PRESENCE__ self-reports are handled in
message_dispatch and emit source: Peer. Self, blocked, or empty
peer ids are dropped entirely: an app waiting on presence_updated
for a blocked peer will never see it.
Sourcepub fn welcome_pending_peers(&self) -> Vec<String>
pub fn welcome_pending_peers(&self) -> Vec<String>
Peers with a welcome lifecycle whose session has not been proven —
the internet presence watch set. Includes Sent records (wire-
confirmed but never session-confirmed): only a presence signal can
rescue those over a store-less relay.
Lifecycles older than WELCOME_WATCHLIST_MAX_AGE_SECS are excluded:
a permanently-dead peer must not occupy watch-rotation slots (and keep
its parked record alive via expires_at pushes) forever.
Source§impl OfflineProtocol
impl OfflineProtocol
Sourcepub fn note_nostr_event_received(&mut self, created_at_secs: i64)
pub fn note_nostr_event_received(&mut self, created_at_secs: i64)
Records that a Nostr relay event dated created_at_secs (unix seconds)
was received and decoded, advancing the receive watermark and persisting
it if it has moved far enough.
Call this only for frames that deserialized into a Message — see
NostrTransport::advance_receive_watermark for why an undecodable
frame must not move the mark.
Sourcepub fn restore_nostr_transport_state(&mut self)
pub fn restore_nostr_transport_state(&mut self)
Installs the persisted Nostr state into a transport that was registered
after Self::initialize_mls ran.
Both restores below are no-ops when no Nostr transport is registered,
which is exactly the state initialize_mls runs them in for the FFI:
the Nostr transport is derived from this device’s address, so the
bindings layer cannot construct it until initialize_mls has produced
one, and it installs the transport immediately afterwards. Without this
second pass that transport keeps the ephemeral signing key it was
constructed with — rotating this install’s Nostr identity on every
launch, so peers who sealed to the pubkey we advertised last time get
frames we can no longer open — and starts with no receive watermark, so
every cold start replays the full first-run backfill window.
Safe to call whether or not the first pass found a transport: the
signing-secret restore is guarded by nostr_secret_persisted, which a
transport-less pass leaves unset, and the watermark only ever moves
forward.
Sourcepub fn telemetry_install_id(&self) -> Option<String>
pub fn telemetry_install_id(&self) -> Option<String>
Returns a stable, opaque per-install telemetry identifier, or None
until the persistent scrub secret is available.
The id is SHA-256(secret || domain) truncated to a 32-character hex
string, where secret is the per-install scrub secret managed by
Self::restore_or_init_scrub_secret. The secret cannot be recovered
from the id, and the fixed domain string keeps the id un-correlatable
with opaque identifiers the scrubber produces for telemetry records:
the domain contains :, which id validation
(offline_protocol_core::types::validate_id_chars) rejects in every
UserId/AppId, so no validated identifier reaching the scrubber can
ever equal the domain and collide with the install id.
Returns None while the SDK is still on the random per-instance
fallback secret — i.e. before secure storage is provided via
super::OfflineProtocol::initialize_mls, or when persistence failed
this session. In that state the id would not be stable across launches,
so none is exposed.
Deliberately derived from the persistent fallback secret, not from an
installed crate::telemetry::TelemetryConfig::with_scrub_secret
override: the install id must not rotate when a sink is (re)installed,
and must not be computable from an app-chosen secret.
The domain string is part of the public contract: changing it would silently rotate every device’s install id. Frozen — do not edit.
Source§impl OfflineProtocol
impl OfflineProtocol
Sourcepub fn new(config: ProtocolConfig) -> Result<Self>
pub fn new(config: ProtocolConfig) -> Result<Self>
Sourcepub fn initialize_mls(
&mut self,
secure_storage: Arc<dyn MlsStorage>,
protocol_state_storage: Arc<dyn ProtocolStateStorage>,
) -> Result<()>
pub fn initialize_mls( &mut self, secure_storage: Arc<dyn MlsStorage>, protocol_state_storage: Arc<dyn ProtocolStateStorage>, ) -> Result<()>
Initializes MLS encryption and protocol persistence.
This must be called before encryption can be used. The storage
secure_storage must be a platform-native credential store.
protocol_state_storage must be scoped to the app container and is
removed when that container is deleted.
Ownership model:
OfflineProtocolis the single authoritative owner ofMlsManager- initialization is idempotent per protocol instance
- subsequent calls return without replacing the existing manager
- manager publication is transactional: restore must succeed before
mls_managerbecomes visible to callers
The two storage domains are intentionally different trait objects. This prevents message-plane state from inheriting the lifecycle of Keychain or another credential store.
Sourcepub fn local_address(&self) -> Option<&str>
pub fn local_address(&self) -> Option<&str>
Returns this device’s address, once it has one.
None before initialize_mls: the address is the hash of an identity
key that lives in this profile’s storage, and storage does not arrive
until then. It never changes afterwards, and it is stable across
restarts of the same profile because the key is.
Sourcepub fn is_mls_initialized(&self) -> bool
pub fn is_mls_initialized(&self) -> bool
Checks if MLS encryption is initialized.
Sourcepub fn set_mls_event_emitter(&mut self, emitter: Arc<dyn MlsEventEmitter>)
pub fn set_mls_event_emitter(&mut self, emitter: Arc<dyn MlsEventEmitter>)
Configures the MLS lifecycle event emitter.
Sourcepub fn install_telemetry_sink(
&mut self,
sink: Arc<dyn TelemetrySink>,
config: TelemetryConfig,
) -> Result<()>
pub fn install_telemetry_sink( &mut self, sink: Arc<dyn TelemetrySink>, config: TelemetryConfig, ) -> Result<()>
Installs the unified telemetry sink for this protocol instance.
Every subsequent protocol Event and MLS lifecycle event is
additionally forwarded to sink as a
crate::telemetry::TelemetryRecord, gated by the verbosity tier
and identifier-scrubbing preferences in config. Protocol events
flow through as TelemetryRecord::Protocol, MLS lifecycle events
as TelemetryRecord::Mls.
This does not replace the legacy crate::EventCallback and
MlsEventEmitter paths — they continue to fire independently for
backward compatibility.
Events emitted before this call (for example
crate::mls_observability::MlsLifecycleEvent::Initialized fired
during initialize_mls) are not replayed to a sink installed later.
§Re-install semantics
Calling this method a second time replaces the previously installed
sink and config — the old sink stops receiving records as soon as
this call returns. The per-instance fallback secret is preserved so
opaque identifiers stay stable across the swap when the new config
does not carry its own scrub_secret.
The per-tick diff snapshots (transport status, device capability,
metrics cadence) are rearmed on every install: the next
process() tick observes the current state as its baseline and emits
no synthetic transitions for transports that were already available
at install time. Apps that need the current transport statuses at
install time should pull them explicitly via
TransportManager::get_all_transport_statuses.
The escalation-trigger dedupe window (ESCALATION_TRIGGER_DEDUPE_SECS
inside TransportManager) is not rearmed. A sink installed
within that window after an escalation event fired to a previous
sink may miss the next occurrence of the same reason until the
window elapses. This is intentional: the dedupe is a property of
the routing engine, not of the observer.
§Lifecycle
Installing a sink wires the structured routing-decision callback
on the underlying TransportManager. The callback lives for the
life of the protocol instance or until another
install_telemetry_sink call replaces it — start() and stop()
do not toggle it. This means apps can install a sink before
start() and see routing records from the very first send(),
and a stop() → start() cycle preserves the wiring so no
re-install is needed. Conversely, apps that never install a sink
pay no per-send() routing-emission overhead.
§Errors
Returns Err if the shared-state mutex is poisoned (indicating an
earlier panic in another thread while holding the lock). On error no
sink is installed, and the legacy emission paths are unaffected.
Sourcepub fn on_neighbor_discovered(&mut self, peer_id: &str)
pub fn on_neighbor_discovered(&mut self, peer_id: &str)
Called when a new neighbor is discovered.
When auto key exchange is enabled, this method sends our key package to the newly discovered peer to enable encrypted communication.
§Arguments
peer_id- The ID of the discovered peer
Sourcepub fn flush_outbox_all(&mut self)
pub fn flush_outbox_all(&mut self)
Immediately attempts to send all pending outbox messages across all peers.
Called when a transport becomes available (e.g. internet reconnects) to flush all queued messages, bypassing backoff timers.
Sourcepub fn presence_watch_peers(&self) -> Vec<String>
pub fn presence_watch_peers(&self) -> Vec<String>
Peers the platform layer should watch via relay CheckPresence
queries: every peer with an undelivered or session-unproven MLS
welcome (Self::welcome_pending_peers) plus every recipient of an
outbox message not currently awaiting an ACK — which includes DMs
parked on a relay recipient_unreachable verdict. The relay’s
presence-online answer lands in Self::on_peer_presence, whose
flush_outbox_for_peer_via is what re-drives (un-parks) those messages,
so the SDK — not the app — owns the “watch my DeliveryError
recipients” duty. Bounded by the outbox cap (500 entries).
Sourcepub fn on_neighbor_lost(&mut self, peer_id: &str)
pub fn on_neighbor_lost(&mut self, peer_id: &str)
Called when a neighbor is lost.
Cleans up tracking state for the lost peer.
§Arguments
peer_id- The ID of the lost peer
Sourcepub fn establish_secure_session(
&mut self,
peer_id: &str,
) -> Result<Option<WelcomeMessage>>
pub fn establish_secure_session( &mut self, peer_id: &str, ) -> Result<Option<WelcomeMessage>>
Establishes a secure MLS session with a peer.
This high-level method handles the complete session establishment flow:
- Checks if a session already exists (returns Ok(None) if so)
- Checks for a pending key package from the peer
- If found, imports the key package, creates the session, and sends the Welcome message
- If no key package is available, returns an error
This method is designed for use by application code that needs explicit control over session establishment, as opposed to the automatic encryption flow.
§Arguments
peer_id- The ID of the peer to establish a session with
§Returns
Ok(Some(WelcomeMessage))- Session created, Welcome message returned (and sent to peer)Ok(None)- Session already existsErr(SessionNotReady(state))- Establishment in progress; caller can retry or show “Establishing…”
Sourcepub fn has_pending_key_package(&self, peer_id: &str) -> bool
pub fn has_pending_key_package(&self, peer_id: &str) -> bool
Sourcepub fn get_establishment_state(
&self,
peer_id: &str,
) -> Result<EstablishmentState>
pub fn get_establishment_state( &self, peer_id: &str, ) -> Result<EstablishmentState>
Returns the current establishment state for a peer.
Use this to show “Establishing…” or drive retries without calling send/establish.
Sourcepub fn peer_supports_rich_payload(&self, peer_id: &str) -> bool
pub fn peer_supports_rich_payload(&self, peer_id: &str) -> bool
Whether rich extras (reply context, rich media metadata, forward
attribution) on a send toward peer_id would travel in the sealed
rich body — i.e. the peer’s last key package advertised the
capability (surviving restarts) and our own rich_payload_enabled
kill switch is on. When false the extras are silently dropped and
the message degrades to plain text, so apps can use this to render
honest degraded-reply UX instead of discovering the drop after the
fact.
Sourcepub fn manual_mls_create_session(
&mut self,
peer_id: &str,
) -> Result<WelcomeMessage>
pub fn manual_mls_create_session( &mut self, peer_id: &str, ) -> Result<WelcomeMessage>
Creates a session using manually imported key material.
This entrypoint is for bindings that expose low-level MLS APIs. It must still keep protocol-level session lifecycle state in sync with MLS state.
Sourcepub fn manual_mls_import_key_package(
&mut self,
peer_id: &str,
key_package_data: &[u8],
) -> Result<()>
pub fn manual_mls_import_key_package( &mut self, peer_id: &str, key_package_data: &[u8], ) -> Result<()>
Imports a contact’s key package and records them encryption-capable.
The entry point for bindings that expose low-level MLS APIs. It exists
because the FFI wrapper used to reach straight for the MlsManager and
pass the since-deleted KeyPackageTrust::FirstUse — so an app could
import a key package
under any peer id with no correlation to that peer, bypassing the check
establish_secure_session performs. The identity claim no longer needs
the detour: import_key_package re-derives the address from the leaf
signature key and refuses a mismatch on its own. The routing stays
because the capability record lives here, not on the manager.
Sourcepub fn manual_mls_delete_session(&mut self, peer_id: &str) -> Result<()>
pub fn manual_mls_delete_session(&mut self, peer_id: &str) -> Result<()>
Deletes a 1:1 session and clears protocol-level lifecycle state.
Sourcepub fn manual_mls_join_session(
&mut self,
welcome: &WelcomeMessage,
) -> Result<GroupInfo>
pub fn manual_mls_join_session( &mut self, welcome: &WelcomeMessage, ) -> Result<GroupInfo>
Joins a session from a Welcome message and synchronizes confirmation state.
Sourcepub fn manual_mls_process_welcome(
&mut self,
welcome: &WelcomeMessage,
) -> Result<GroupInfo>
pub fn manual_mls_process_welcome( &mut self, welcome: &WelcomeMessage, ) -> Result<GroupInfo>
Processes an MLS Welcome message and synchronizes confirmation state.
Sourcepub fn manual_mls_decrypt_from_user(
&mut self,
encrypted: &EncryptedMessage,
) -> Result<Option<Vec<u8>>>
pub fn manual_mls_decrypt_from_user( &mut self, encrypted: &EncryptedMessage, ) -> Result<Option<Vec<u8>>>
Decrypts a user-scoped MLS message and synchronizes confirmation state.
Sourcepub fn manual_mls_decrypt(
&mut self,
encrypted: &EncryptedMessage,
) -> Result<Option<Vec<u8>>>
pub fn manual_mls_decrypt( &mut self, encrypted: &EncryptedMessage, ) -> Result<Option<Vec<u8>>>
Decrypts any MLS message and synchronizes confirmation state for 1:1 flows.
Trait Implementations§
Source§impl Drop for OfflineProtocol
impl Drop for OfflineProtocol
Auto Trait Implementations§
impl !Freeze for OfflineProtocol
impl !RefUnwindSafe for OfflineProtocol
impl !UnwindSafe for OfflineProtocol
impl Send for OfflineProtocol
impl Sync for OfflineProtocol
impl Unpin for OfflineProtocol
impl UnsafeUnpin for OfflineProtocol
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> Declassify for T
impl<T> Declassify for T
type Declassified = T
fn declassify(self) -> T
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