warehouse 0.1.0

A unified ergonomic caching layer for arbitrary Rust data
Documentation
/*
// Setup
let cache = Cache::builder()
    .with_versioning(MaxVersions::Last(10))
    .with_snapshot(SnapshotPolicy::OnDrop | SnapshotPolicy::Every(Duration::from_secs(30)))
    .build();

// Write
cache.insert("user_prefs", my_prefs_struct);

// Read (zero clone across threads via arc-swap)
let prefs = cache.get::<UserPrefs>("user_prefs")?;

// History
let prev = cache.get_version::<UserPrefs>("user_prefs", Version::Previous(2))?;

// Snapshot
cache.snapshot("./cache_state.bin")?;

// Warm start
let cache = Cache::from_snapshot("./cache_state.bin")?;
*/

/*
pub trait Cacheable: Send + Sync + Sized + 'static {
    fn type_id() -> TypeId;
    fn serialize(&self) -> Result<Vec<u8>, CacheError>;
    fn deserialize(bytes: &[u8]) -> Result<Self, CacheError>;
    fn schema_version() -> u32 { 1 } // for snapshot migration
}
*/

/*
#[derive(Debug, Clone, Cacheable)]
pub struct UserPrefs {
    pub theme: String,
    pub font_size: u32,
}
*/

/*
impl Cacheable for UserPrefs {
    fn type_id() -> TypeId {
        TypeId::of::<UserPrefs>()
    }

    fn serialize(&self) -> Result<Vec<u8>, CacheError> {
        // delegates to serde + bincode/rmp
        bincode::serialize(self).map_err(CacheError::from)
    }

    fn deserialize(bytes: &[u8]) -> Result<Self, CacheError> {
        bincode::deserialize(bytes).map_err(CacheError::from)
    }
}
*/

/*
use std::any::{Any, TypeId};

struct CacheEntry {
    type_id: TypeId,
    // the actual value, type-erased
    inner: Arc<dyn Any + Send + Sync>,
    // raw bytes for snapshot/restore — kept alongside
    // so you never re-serialize on every read
    serialized: Arc<[u8]>,
    version: u32,
}
*/

/*
pub struct Cache {
    entries: DashMap<CacheKey, CacheEntry>,
}

// CacheKey is a (name + TypeId) pair so "config" as UserPrefs
// and "config" as AppConfig don't collide
pub struct CacheKey {
    name: Arc<str>,
    type_id: TypeId,
}
*/

/*
impl Cache {
    pub fn insert<T: Cacheable>(&self, name: &str, value: T) -> Result<(), CacheError> {
        let bytes = value.serialize()?;
        let entry = CacheEntry {
            type_id: TypeId::of::<T>(),
            inner: Arc::new(value),
            serialized: bytes.into(),
            version: T::schema_version(),
        };
        let key = CacheKey {
            name: name.into(),
            type_id: TypeId::of::<T>(),
        };
        self.entries.insert(key, entry);
        Ok(())
    }
}
*/

/*
impl Cache {
    pub fn get<T: Cacheable>(&self, name: &str) -> Result<Arc<T>, CacheError> {
        let key = CacheKey {
            name: name.into(),
            type_id: TypeId::of::<T>(),
        };
        let entry = self.entries.get(&key).ok_or(CacheError::NotFound)?;

        // downcast the Arc<dyn Any> back to Arc<T>
        // this is safe because we keyed on TypeId
        entry.inner
            .clone()
            .downcast::<T>()  // Arc<dyn Any>::downcast
            .map_err(|_| CacheError::TypeMismatch)
    }
}
*/

/*
// Snapshot wire format per entry:
// [key_len: u32][key_bytes][type_id_hash: u64]
// [schema_version: u32][data_len: u32][data_bytes]

impl Cache {
    pub fn restore_entry(
        &self,
        name: &str,
        type_id: TypeId,
        schema_version: u32,
        bytes: &[u8],
    ) -> Result<(), CacheError> {
        // check schema version matches current binary
        // if mismatch -> call migration hook or error
        // deserialize bytes -> Box<dyn Any + Send + Sync>
        // re-box into CacheEntry and insert
    }
}
*/

/*
type DeserializeFn = fn(&[u8]) -> Result<Box<dyn Any + Send + Sync>, CacheError>;

struct TypeRegistry {
    entries: HashMap<TypeId, DeserializeFn>,
}
*/

/*
// generated by #[derive(Cacheable)] automatically
cache_every_thing::register_type!(UserPrefs);
*/

/*
User type T
    │
    ├─ #[derive(Cacheable)]
    │       ├─ impl Send + Sync enforced by compiler
    │       ├─ serialize()  ──► Vec<u8>
    │       ├─ deserialize() ◄── &[u8]
    │       └─ registers DeserializeFn in TypeRegistry
    │
    ▼
cache.insert("key", value: T)
    │
    ├─ serialize once → Arc<[u8]>
    ├─ Arc::new(value) → Arc<dyn Any + Send + Sync>
    └─ stored in DashMap<CacheKey, CacheEntry>
            │
            ├─► cache.get<T>("key")
            │       └─ Arc::clone → Arc<T>  (no data copy)
            │               └─► shared across threads freely
            │
            └─► cache.snapshot("file.bin")
                    └─ write Arc<[u8]> per entry (no re-serialize)
                            │
                            ▼
                    cache.restore("file.bin")
                            └─ TypeRegistry looks up DeserializeFn
                            └─ bytes → Box<dyn Any> → CacheEntry
*/