| Crates.io | light-magic |
| lib.rs | light-magic |
| version | 0.8.0 |
| created_at | 2024-05-27 18:43:03.41679+00 |
| updated_at | 2025-09-20 21:28:55.663623+00 |
| description | A lightweight, fast and easy-to-use implementation of a persistent and optionally encrypted in-memory database |
| homepage | |
| repository | https://github.com/nwrenger/light-magic |
| max_upload_size | |
| id | 1253665 |
| size | 92,038 |
A lightweight, fast and easy-to-use implementation of a persistent or optionally encrypted in-memory database.
Please note that this database is highly optimized for read operations. Writing to the database is relatively slow when using open because each write operation involves writing data to the disk. These writes are done atomically, ensuring no data loss on a system-wide crash.
JSON file via open, or it can be operated in-memory using open_in_memory.encrypted module using the same open method.search / search_ordered and the join! macro for efficient data searching and joining.Table data type, which uses the BTreeMap type from std::collections under the hood, for efficient storage and easy access of its tables.Arc<AtomicDatabase<_>>.Add this to your Cargo.toml:
[dependencies]
light_magic = "0.8.0"
light-magic is feature-flag driven. By default, only the atomic module is enabled.
You can enable additional functionality in your Cargo.toml:
atomic: Enabled by default. Provides the basic atomic database with persistent JSON storage, type-safe tables, and the DataStore trait.encrypted: Enables the encrypted module, adding Argon2id password-based key derivation, AES-256-GCM authenticated encryption (96-bit nonces), and compact bincode serialization on top of the atomic database.Using it in an axum Server? Look here: maud-magic-rs. Otherwise, look at this general example:
use light_magic::{
atomic::DataStore,
join,
serde::{Deserialize, Serialize},
table::{PrimaryKey, Table},
};
#[derive(Default, Debug, Serialize, Deserialize)]
struct Database {
users: Table<User>,
permissions: Table<Permission>,
criminals: Table<Criminal>,
settings: Settings,
}
impl light_magic::atomic::DataStore for Database {}
// or with features = ["encrypted"]
// impl light_magic::encrypted::EncryptedDataStore for Database {}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
struct User {
id: usize,
name: String,
kind: String,
}
impl PrimaryKey for User {
type PrimaryKeyType = usize;
fn primary_key(&self) -> &Self::PrimaryKeyType {
&self.id
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
struct Permission {
user_name: String,
level: Level,
}
impl PrimaryKey for Permission {
type PrimaryKeyType = String;
fn primary_key(&self) -> &Self::PrimaryKeyType {
&self.user_name
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
enum Level {
#[default]
Admin,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
struct Criminal {
user_name: String,
entry: String,
}
impl PrimaryKey for Criminal {
type PrimaryKeyType = String;
fn primary_key(&self) -> &Self::PrimaryKeyType {
&self.user_name
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
struct Settings {
time: usize,
password: String,
}
fn main() {
let db = Database::open("./tests/test.json");
// or with features = ["encrypted"]
// let db = Database::open("./tests/test.json", "somePassword");
db.write().users.add(User {
id: 0,
name: String::from("Nils"),
kind: String::from("Young"),
});
println!("{:?}", db.read().users.get(&0));
println!("{:?}", db.read().users.search(|user| { user.name.contains("Nils") }));
db.write().permissions.add(Permission {
user_name: String::from("Nils"),
level: Level::Admin,
});
println!("{:?}", db.read().permissions.get(&String::from("Nils")));
println!("{:?}", db.read().permissions.search(|permission| { permission.level == Level::Admin }));
db.write().criminals.add(Criminal {
user_name: String::from("Nils"),
entry: String::from("No records until this day! Keep ur eyes pealed!"),
});
println!("{:?}", db.read().criminals.get(&String::from("Nils")));
println!("{:?}", db.read().criminals.search(|criminal| { criminal.entry.contains("No records") }));
db.write().settings = Settings {
time: 1718744090,
password: String::from("password"),
};
println!("{:?}", db.read().settings);
let joined = join!(db.read(), "Nils", users => name, permissions => user_name, criminals => user_name);
println!("{:?}", joined);
}