Skip to main content

core_crypto_keystore/connection/
mls.rs

1use openmls_traits::key_store::MlsEntity;
2
3use crate::{CryptoKeystoreError, CryptoKeystoreResult, Database, Transaction, transaction::read_mls_entity};
4
5/// convenience methods to modify the in-flight transaction
6impl Database {
7    /// Do an operation on an existing keystore transaction.
8    ///
9    /// This does not create, commit, or abort an existing transaction; it just provides a standardized
10    /// helper to acquire it while creating appropriate errors.
11    async fn with_transaction<R>(&self, operation: impl AsyncFnOnce(&Transaction) -> R) -> CryptoKeystoreResult<R> {
12        let guard = self.transaction.lock().await;
13        let transaction = guard
14            .as_ref()
15            .ok_or(CryptoKeystoreError::MutatingOperationWithoutTransaction)?
16            .upgrade()
17            .await
18            .ok_or(CryptoKeystoreError::MutatingOperationWithoutTransaction)?;
19
20        Ok(operation(&transaction).await)
21    }
22}
23
24#[inline(always)]
25pub fn deser<T: MlsEntity>(bytes: &[u8]) -> Result<T, CryptoKeystoreError> {
26    Ok(postcard::from_bytes(bytes)?)
27}
28
29#[inline(always)]
30pub fn ser<T: MlsEntity>(value: &T) -> Result<Vec<u8>, CryptoKeystoreError> {
31    Ok(postcard::to_stdvec(value)?)
32}
33
34#[cfg_attr(target_os = "unknown", async_trait::async_trait(?Send))]
35#[cfg_attr(not(target_os = "unknown"), async_trait::async_trait)]
36impl openmls_traits::key_store::OpenMlsKeyStore for Database {
37    type Error = CryptoKeystoreError;
38
39    async fn store<V: MlsEntity + Sync>(&self, id: &[u8], value: &V) -> Result<(), Self::Error>
40    where
41        Self: Sized,
42    {
43        self.with_transaction(async |tx| tx.store(id, value).await)
44            .await
45            .flatten()
46    }
47
48    async fn read<V: MlsEntity>(&self, id: &[u8]) -> Option<V>
49    where
50        Self: Sized,
51    {
52        let conn = self.conn().await;
53        read_mls_entity(&conn, id)
54    }
55
56    async fn delete<V: MlsEntity>(&self, id: &[u8]) -> Result<(), Self::Error> {
57        self.with_transaction(async |tx| tx.delete::<V>(id).await)
58            .await
59            .flatten()
60    }
61}