Crate daybreak

source ·
Expand description

Daybreak

Daybreak was a Ruby Daybreak inspired single file Database. It has now since evolved into something else. Please check v1 for a more similar version.

This is a continuation of the Rustbreak project, which is now archived.

You will find an overview here in the docs, but to give you a more complete tale of how this is used please check the examples.

At its core, Daybreak is an attempt at making a configurable general-purpose store Database. It features the possibility of:

  • Choosing what kind of Data is stored in it
  • Which kind of Serialization is used for persistence
  • Which kind of persistence is used

This means you can take any struct you can serialize and deserialize and stick it into this Database. It is then encoded with Ron, Yaml, JSON, Bincode, anything really that uses Serde operations!

There are three helper type aliases MemoryDatabase, FileDatabase, and PathDatabase, each backed by their respective backend.

The MemoryBackend saves its data into a Vec<u8>, which is not that useful on its own, but is needed for compatibility with the rest of the Library.

The FileDatabase is a classical file based database. You give it a path or a file, and it will use it as its storage. You still get to pick what encoding it uses.

The PathDatabase is very similar, but always requires a path for creation. It features atomic saves, so that the old database contents won’t be lost when panicing during the save. It should therefore be preferred to a FileDatabase.

Using the Database::with_deser and Database::with_backend one can switch between the representations one needs. Even at runtime! However this is only useful in a few scenarios.

If you have any questions feel free to ask at the main repo.

Quickstart

Add this to your Cargo.toml:

[dependencies.rustbreak]
version = "2"
features = ["ron_enc"] # You can also use "yaml_enc" or "bin_enc"
use daybreak::{deser::Ron, MemoryDatabase};

let db = MemoryDatabase::<HashMap<u32, String>, Ron>::memory(HashMap::new())?;

println!("Writing to Database");
db.write(|db| {
    db.insert(0, String::from("world"));
    db.insert(1, String::from("bar"));
});

db.read(|db| {
    // db.insert("foo".into(), String::from("bar"));
    // The above line will not compile since we are only reading
    println!("Hello: {:?}", db.get(&0));
})?;

Or alternatively:

use daybreak::{deser::Ron, MemoryDatabase};

let db = MemoryDatabase::<HashMap<u32, String>, Ron>::memory(HashMap::new())?;

println!("Writing to Database");
{
    let mut data = db.borrow_data_mut()?;
    data.insert(0, String::from("world"));
    data.insert(1, String::from("bar"));
}

let data = db.borrow_data()?;
println!("Hello: {:?}", data.get(&0));

Error Handling

Handling errors in Daybreak is straightforward. Every Result has as its fail case as error::Error. This means that you can now either continue bubbling up said error case, or handle it yourself.

use daybreak::{deser::Ron, error::Error, MemoryDatabase};
let db = match MemoryDatabase::<usize, Ron>::memory(0) {
    Ok(db) => db,
    Err(e) => {
        // Do something with `e` here
        std::process::exit(1);
    }
};

Panics

This Database implementation uses RwLock and Mutex under the hood. If either the closures given to Database::write or any of the Backend implementation methods panic the respective objects are then poisoned. This means that you cannot panic under any circumstances in your closures or custom backends.

Currently there is no way to recover from a poisoned Database other than re-creating it.

Examples

There are several more or less in-depth example programs you can check out! Check them out here: Examples

  • config.rs shows you how a possible configuration file could be managed with rustbreak
  • full.rs shows you how the database can be used as a hashmap store
  • switching.rs show you how you can easily swap out different parts of the Database Note: To run this example you need to enable the feature yaml like so: cargo run --example switching --features yaml
  • server/ is a fully fledged example app written with the Rocket framework to make a form of micro-blogging website. You will need rust nightly to start it.

Features

Daybreak comes with following optional features:

  • ron_enc which enables the Ron de/serialization
  • yaml_enc which enables the Yaml de/serialization
  • bin_enc which enables the Bincode de/serialization
  • ‘mmap’ whhich enables memory map backend.

Enable them in your Cargo.toml file to use them. You can safely have them all turned on per-default.

Re-exports

pub use crate::deser::DeSerializer;
pub use crate::error::*;

Modules

The persistence backends of the Database.
Different serialization and deserialization methods one can use
The rustbreak errors that can be returned

Structs

The Central Database to Daybreak.

Type Definitions

A database backed by a file.
A database backed by a byte vector (Vec<u8>).
A database backed by anonymous memory map.
A database backed by a file, using atomic saves.