core_crypto_ffi/
decrypted_message.rs

1// We can't otherwise silence the deprecation warnings generated by macros on the message definitions
2#![allow(deprecated)]
3
4use core_crypto::prelude::{MlsBufferedConversationDecryptMessage, MlsConversationDecryptMessage};
5#[cfg(target_family = "wasm")]
6use wasm_bindgen::prelude::*;
7
8use crate::{ClientId, CoreCryptoError, CoreCryptoResult, NewCrlDistributionPoints, ProposalBundle, WireIdentity};
9
10/// See [core_crypto::prelude::decrypt::MlsConversationDecryptMessage]
11#[derive(Debug)]
12#[cfg_attr(
13    target_family = "wasm",
14    wasm_bindgen(getter_with_clone),
15    derive(serde::Serialize, serde::Deserialize)
16)]
17#[cfg_attr(not(target_family = "wasm"), derive(uniffi::Record))]
18pub struct DecryptedMessage {
19    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly))]
20    pub message: Option<Vec<u8>>,
21    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly))]
22    pub proposals: Vec<ProposalBundle>,
23    /// It is set to false if ingesting this MLS message has resulted in the client being removed from the group (i.e. a Remove commit)
24    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly, js_name = isActive))]
25    pub is_active: bool,
26    /// Commit delay hint (in milliseconds) to prevent clients from hammering the server with epoch changes
27    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly, js_name = commitDelay))]
28    pub commit_delay: Option<u64>,
29    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly, js_name = senderClientId))]
30    pub sender_client_id: Option<ClientId>,
31    /// true when the decrypted message resulted in an epoch change i.e. it was a commit
32    ///
33    /// Deprecated: this member will be removed in the future. Prefer using the `EpochObserver` interface.
34    #[deprecated = "This member will be removed in the future. Prefer using the `EpochObserver` interface."]
35    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly, js_name = hasEpochChanged))]
36    pub has_epoch_changed: bool,
37    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly))]
38    pub identity: WireIdentity,
39    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly, js_name = bufferedMessages))]
40    pub buffered_messages: Option<Vec<BufferedDecryptedMessage>>,
41    /// New CRL Distribution of members of this group
42    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly, js_name = crlNewDistributionPoints))]
43    pub crl_new_distribution_points: NewCrlDistributionPoints,
44}
45
46impl TryFrom<MlsConversationDecryptMessage> for DecryptedMessage {
47    type Error = CoreCryptoError;
48
49    fn try_from(from: MlsConversationDecryptMessage) -> Result<Self, Self::Error> {
50        let proposals = from
51            .proposals
52            .into_iter()
53            .map(ProposalBundle::try_from)
54            .collect::<CoreCryptoResult<Vec<_>>>()?;
55
56        let buffered_messages = from
57            .buffered_messages
58            .map(|bm| {
59                bm.into_iter()
60                    .map(TryInto::try_into)
61                    .collect::<CoreCryptoResult<Vec<_>>>()
62            })
63            .transpose()?;
64
65        #[expect(deprecated)]
66        Ok(Self {
67            message: from.app_msg,
68            proposals,
69            is_active: from.is_active,
70            commit_delay: from.delay,
71            sender_client_id: from.sender_client_id.map(ClientId),
72            has_epoch_changed: from.has_epoch_changed,
73            identity: from.identity.into(),
74            buffered_messages,
75            crl_new_distribution_points: from.crl_new_distribution_points.into(),
76        })
77    }
78}
79
80/// to avoid recursive structs
81#[derive(Debug, Clone)]
82#[cfg_attr(
83    target_family = "wasm",
84    wasm_bindgen(getter_with_clone),
85    derive(serde::Serialize, serde::Deserialize)
86)]
87#[cfg_attr(not(target_family = "wasm"), derive(uniffi::Record))]
88pub struct BufferedDecryptedMessage {
89    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly))]
90    pub message: Option<Vec<u8>>,
91    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly))]
92    pub proposals: Vec<ProposalBundle>,
93    /// It is set to false if ingesting this MLS message has resulted in the client being removed from the group (i.e. a Remove commit)
94    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly, js_name = isActive))]
95    pub is_active: bool,
96    /// Commit delay hint (in milliseconds) to prevent clients from hammering the server with epoch changes
97    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly, js_name = commitDelay))]
98    pub commit_delay: Option<u64>,
99    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly, js_name = senderClientId))]
100    pub sender_client_id: Option<ClientId>,
101    /// true when the decrypted message resulted in an epoch change i.e. it was a commit
102    ///
103    /// Deprecated: this member will be removed in the future. Prefer using the `EpochObserver` interface.
104    #[deprecated = "This member will be removed in the future. Prefer using the `EpochObserver` interface."]
105    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly, js_name = hasEpochChanged))]
106    pub has_epoch_changed: bool,
107    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly))]
108    pub identity: WireIdentity,
109    /// New CRL Distribution of members of this group
110    #[cfg_attr(target_family = "wasm", wasm_bindgen(readonly, js_name = crlNewDistributionPoints))]
111    pub crl_new_distribution_points: NewCrlDistributionPoints,
112}
113
114impl TryFrom<MlsBufferedConversationDecryptMessage> for BufferedDecryptedMessage {
115    type Error = CoreCryptoError;
116
117    fn try_from(from: MlsBufferedConversationDecryptMessage) -> Result<Self, Self::Error> {
118        let proposals = from
119            .proposals
120            .into_iter()
121            .map(ProposalBundle::try_from)
122            .collect::<CoreCryptoResult<Vec<_>>>()?;
123
124        #[expect(deprecated)]
125        Ok(Self {
126            message: from.app_msg,
127            proposals,
128            is_active: from.is_active,
129            commit_delay: from.delay,
130            sender_client_id: from.sender_client_id.map(ClientId),
131            has_epoch_changed: from.has_epoch_changed,
132            identity: from.identity.into(),
133            crl_new_distribution_points: from.crl_new_distribution_points.into(),
134        })
135    }
136}