interop/
util.rs

1use core_crypto::MlsTransport;
2use core_crypto::prelude::MlsCommitBundle;
3use core_crypto_ffi::CommitBundle;
4use openmls::prelude::MlsMessageOut;
5use spinoff::Spinner;
6use tokio::sync::RwLock;
7
8pub(crate) struct RunningProcess {
9    spinner: Option<Spinner>,
10    is_task: bool,
11}
12
13impl std::fmt::Debug for RunningProcess {
14    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15        f.debug_struct("RunningProcess")
16            .field("is_task", &self.is_task)
17            .finish()
18    }
19}
20
21impl RunningProcess {
22    pub(crate) fn new(msg: impl AsRef<str> + std::fmt::Display, is_task: bool) -> Self {
23        let spinner = if std::env::var("CI").is_err() {
24            Some(Spinner::new(
25                spinoff::spinners::Aesthetic,
26                msg.as_ref().to_owned(),
27                if is_task {
28                    spinoff::Color::Green
29                } else {
30                    spinoff::Color::Blue
31                },
32            ))
33        } else {
34            if is_task {
35                log::info!("{msg}");
36            } else {
37                log::debug!("{msg}");
38            }
39
40            None
41        };
42
43        Self { spinner, is_task }
44    }
45
46    pub(crate) fn update(&mut self, msg: impl AsRef<str> + std::fmt::Display) {
47        if let Some(spinner) = &mut self.spinner {
48            spinner.update_text(msg.as_ref().to_owned());
49        } else if self.is_task {
50            log::info!("{msg}");
51        } else {
52            log::debug!("{msg}");
53        }
54    }
55
56    pub(crate) fn success(self, msg: impl AsRef<str> + std::fmt::Display) {
57        if let Some(mut spinner) = self.spinner {
58            spinner.success(msg.as_ref());
59        } else {
60            log::info!("{msg}");
61        }
62    }
63}
64
65#[async_trait::async_trait]
66pub trait MlsTransportTestExt: MlsTransport {
67    async fn latest_commit_bundle(&self) -> MlsCommitBundle;
68    async fn latest_welcome_message(&self) -> MlsMessageOut {
69        self.latest_commit_bundle().await.welcome.unwrap().clone()
70    }
71}
72
73#[derive(Debug, Default)]
74pub struct MlsTransportSuccessProvider {
75    latest_commit_bundle: RwLock<Option<MlsCommitBundle>>,
76    latest_message: RwLock<Option<Vec<u8>>>,
77}
78
79#[async_trait::async_trait]
80impl MlsTransport for MlsTransportSuccessProvider {
81    async fn send_commit_bundle(
82        &self,
83        commit_bundle: MlsCommitBundle,
84    ) -> core_crypto::Result<core_crypto::MlsTransportResponse> {
85        self.latest_commit_bundle.write().await.replace(commit_bundle);
86        Ok(core_crypto::MlsTransportResponse::Success)
87    }
88
89    async fn send_message(&self, mls_message: Vec<u8>) -> core_crypto::Result<core_crypto::MlsTransportResponse> {
90        self.latest_message.write().await.replace(mls_message);
91        Ok(core_crypto::MlsTransportResponse::Success)
92    }
93}
94
95#[async_trait::async_trait]
96impl MlsTransportTestExt for MlsTransportSuccessProvider {
97    async fn latest_commit_bundle(&self) -> MlsCommitBundle {
98        self.latest_commit_bundle
99            .read()
100            .await
101            .clone()
102            .expect("latest_commit_bundle")
103    }
104}
105
106#[async_trait::async_trait]
107impl core_crypto_ffi::MlsTransport for MlsTransportSuccessProvider {
108    async fn send_commit_bundle(&self, _commit_bundle: CommitBundle) -> core_crypto_ffi::MlsTransportResponse {
109        core_crypto_ffi::MlsTransportResponse::Success
110    }
111
112    async fn send_message(&self, mls_message: Vec<u8>) -> core_crypto_ffi::MlsTransportResponse {
113        self.latest_message.write().await.replace(mls_message);
114        core_crypto_ffi::MlsTransportResponse::Success
115    }
116}