openmls_sqlite_storage 0.2.0

A storage provider for OpenMLS based on SQlite based on the rusqlite crate.
Documentation
use std::marker::PhantomData;

use openmls_traits::storage::{Entity, Key};
use rusqlite::{
    types::{FromSql, ToSqlOutput},
    ToSql,
};
use serde::Serialize;

use crate::{codec::Codec, STORAGE_PROVIDER_VERSION};

#[derive(Debug, Serialize)]
pub(super) struct KeyRefWrapper<'a, C: Codec, T: Key<STORAGE_PROVIDER_VERSION>>(
    pub &'a T,
    pub PhantomData<C>,
);

impl<C: Codec, T: Key<STORAGE_PROVIDER_VERSION>> ToSql for KeyRefWrapper<'_, C, T> {
    fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
        let key_bytes =
            C::to_vec(&self.0).map_err(|e| rusqlite::Error::ToSqlConversionFailure(Box::new(e)))?;
        Ok(ToSqlOutput::Owned(rusqlite::types::Value::Blob(key_bytes)))
    }
}

pub(super) struct EntityWrapper<C: Codec, T: Entity<STORAGE_PROVIDER_VERSION>>(
    pub T,
    pub PhantomData<C>,
);

impl<C: Codec, T: Entity<STORAGE_PROVIDER_VERSION>> FromSql for EntityWrapper<C, T> {
    fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
        let entity = C::from_slice(value.as_blob()?)
            .map_err(|e| rusqlite::types::FromSqlError::Other(Box::new(e)))?;
        Ok(Self(entity, PhantomData))
    }
}

pub(super) struct EntityRefWrapper<'a, C: Codec, T: Entity<STORAGE_PROVIDER_VERSION>>(
    pub &'a T,
    pub PhantomData<C>,
);

impl<C: Codec, T: Entity<STORAGE_PROVIDER_VERSION>> ToSql for EntityRefWrapper<'_, C, T> {
    fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
        let entity_bytes =
            C::to_vec(&self.0).map_err(|e| rusqlite::Error::ToSqlConversionFailure(Box::new(e)))?;
        Ok(ToSqlOutput::Owned(rusqlite::types::Value::Blob(
            entity_bytes,
        )))
    }
}

pub(super) struct EntitySliceWrapper<'a, C: Codec, T: Entity<STORAGE_PROVIDER_VERSION>>(
    pub &'a [T],
    pub PhantomData<C>,
);

impl<C: Codec, T: Entity<STORAGE_PROVIDER_VERSION>> ToSql for EntitySliceWrapper<'_, C, T> {
    fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
        let entity_bytes =
            C::to_vec(&self.0).map_err(|e| rusqlite::Error::ToSqlConversionFailure(Box::new(e)))?;
        Ok(ToSqlOutput::Owned(rusqlite::types::Value::Blob(
            entity_bytes,
        )))
    }
}

pub(super) struct EntityVecWrapper<C: Codec, T: Entity<STORAGE_PROVIDER_VERSION>>(
    pub Vec<T>,
    pub PhantomData<C>,
);

impl<C: Codec, T: Entity<STORAGE_PROVIDER_VERSION>> FromSql for EntityVecWrapper<C, T> {
    fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
        let entities = C::from_slice(value.as_blob()?)
            .map_err(|e| rusqlite::types::FromSqlError::Other(Box::new(e)))?;
        Ok(Self(entities, PhantomData))
    }
}