luct-store 0.2.0

Collection of storage backends for the luct project
Documentation
//! Collection of implementations of different [`Stores`](luct_core::store::Store)
#![forbid(unsafe_code)]

// TODO: Move browser store into this crate

mod file;
mod last;
mod lru;
mod switch;

pub use file::FilesystemStore;
pub use last::LastValCacheStore;
pub use lru::LruCacheStore;
use luct_core::{
    Fingerprint,
    v1::{SignedCertificateTimestamp, SignedTreeHead},
};
pub use switch::StoreSwitch;

/// Indicates, that a key can be serialized as a [`String`].
///
/// Some [`Store`](luct_core::store::Store) implementations need to internally store keys
/// as a [`String`].
///
/// These implementations need to restrict their key type to [`StringStoreKey`].
///
/// # Caution
/// In the case of [`StringStoreKey`], it is important that the [`String`] representation of the key
/// has the same ordering as the actual keys.
/// This is relevant for [`OrderedStores`](luct_core::store::OrderedStore).
pub trait StringStoreKey: Clone + Ord + Send + 'static {
    fn serialize_key(&self) -> String;
    fn deserialize_key(key: &str) -> Option<Self>;
}

/// Indicates, that a value can be serialized as a [`String`].
///
/// Some [`Store`](luct_core::store::Store) implementations need to internally store values
/// as a [`String`].
///
/// These implementations need to restrict their value type to [`StringStoreValue`].
pub trait StringStoreValue: Clone + Send + Eq + 'static {
    fn serialize_value(&self) -> String;
    fn deserialize_value(value: &str) -> Option<Self>;
}

impl StringStoreKey for u64 {
    fn serialize_key(&self) -> String {
        self.to_string()
    }

    fn deserialize_key(key: &str) -> Option<Self> {
        key.parse().ok()
    }
}

impl StringStoreKey for Vec<u8> {
    fn serialize_key(&self) -> String {
        hex::encode(self)
    }

    fn deserialize_key(key: &str) -> Option<Self> {
        hex::decode(key).ok()
    }
}

impl StringStoreKey for [u8; 32] {
    fn serialize_key(&self) -> String {
        hex::encode(self)
    }

    fn deserialize_key(key: &str) -> Option<Self> {
        hex::decode(key)
            .map(|val| val.try_into().ok())
            .ok()
            .flatten()
    }
}

impl StringStoreKey for Fingerprint {
    fn serialize_key(&self) -> String {
        self.0.serialize_key()
    }

    fn deserialize_key(key: &str) -> Option<Self> {
        <[u8; 32]>::deserialize_key(key).map(Fingerprint)
    }
}

impl StringStoreValue for () {
    fn serialize_value(&self) -> String {
        String::new()
    }

    fn deserialize_value(value: &str) -> Option<Self> {
        match value {
            "" => Some(()),
            _ => None,
        }
    }
}

impl StringStoreValue for String {
    fn serialize_value(&self) -> String {
        self.clone()
    }

    fn deserialize_value(value: &str) -> Option<Self> {
        Some(value.to_string())
    }
}

impl StringStoreValue for SignedTreeHead {
    fn serialize_value(&self) -> String {
        serde_json::to_string(self).unwrap()
    }

    fn deserialize_value(value: &str) -> Option<Self> {
        serde_json::from_str(value).ok()
    }
}

impl StringStoreValue for SignedCertificateTimestamp {
    fn serialize_value(&self) -> String {
        serde_json::to_string(self).unwrap()
    }

    fn deserialize_value(value: &str) -> Option<Self> {
        serde_json::from_str(value).ok()
    }
}

// TODO: Implement RedbStore