armdb 0.8.0

sharded bitcask key-value storage optimized for NVMe
Documentation
//! The encrypted-participant rejection, which needs no fault injection.
//!
//! Kept apart from `tx_encrypted.rs` so it runs under plain `--features
//! encryption`: that file also needs `test-faults`, and a test only reachable
//! with two features at once is a test nobody runs.
#![cfg(feature = "encryption")]

use std::sync::Arc;

use armdb::armour::Db;
use armdb::{CollectionMeta, Config, NoHook, RapiraCodec, TtlHook, TxConfig, TypedMap};
use armour_core::GetType;
use rapira::Rapira;

type Id = [u8; 8];

fn id(n: u64) -> Id {
    n.to_be_bytes()
}

#[derive(Clone, Debug, PartialEq, Eq, GetType, Rapira)]
struct Secret {
    text: String,
}
impl CollectionMeta for Secret {
    type SelfId = Id;
    const NAME: &'static str = "secrets";
}

const DATA_KEY: [u8; 32] = [0x11; 32];

fn open_secrets(db: &Arc<Db>) -> Arc<TypedMap<Id, Secret, RapiraCodec, TtlHook<Secret, NoHook>>> {
    let mut cfg = Config::test();
    cfg.encryption_key = Some(DATA_KEY);
    db.open_typed_map::<Secret, RapiraCodec, _>(cfg, NoHook, &[])
        .unwrap()
}

#[test]
fn tx_encrypted_collection_requires_an_encrypted_log() {
    let dir = tempfile::tempdir().unwrap();
    let db = Arc::new(Db::open_with_tx_config(dir.path(), TxConfig::default()).unwrap());
    let secrets = open_secrets(&db);

    let err = db
        .tx()
        .put(
            &secrets,
            &id(1),
            &Secret {
                text: "hello".into(),
            },
        )
        .unwrap()
        .commit()
        .unwrap_err();
    assert!(matches!(err, armdb::DbError::Config(_)), "{err}");
    assert!(secrets.get(&id(1)).is_none(), "nothing was written");
}