Struct rustbreak::Database[][src]

pub struct Database<Data, Back, DeSer> { /* fields omitted */ }

The Central Database to RustBreak

It has 3 Type Generics:

  • Data: Is the Data, you must specify this
  • Back: The storage backend.
  • DeSer: The Serializer/Deserializer or short DeSer. Check the deser module for other strategies.

Panics

If the backend or the de/serialization panics, the database is poisoned. This means that any subsequent writes/reads will fail with an error::RustbreakErrorKind::PoisonError. You can only recover from this by re-creating the Database Object.

Methods

impl<Data, Back, DeSer> Database<Data, Back, DeSer> where
    Data: Serialize + DeserializeOwned + Debug + Clone + Send,
    Back: Backend + Debug,
    DeSer: DeSerializer<Data> + Debug + Send + Sync + Clone
[src]

Write lock the database and get write access to the Data container

This gives you an exclusive lock on the memory object. Trying to open the database in writing will block if it is currently being written to.

Panics

If you panic in the closure, the database is poisoned. This means that any subsequent writes/reads will fail with an std::sync::PoisonError. You can only recover from this by re-creating the Database Object.

If you do not have full control over the code being written, and cannot incur the cost of having a single operation panicking then use Database::write_safe.

Examples

use rustbreak::{FileDatabase, deser::Ron};

#[derive(Debug, Serialize, Deserialize, Clone)]
struct Data {
    level: u32,
}

let db = FileDatabase::<Data, Ron>::from_file(file, Data { level: 0 })?;

db.write(|db| {
    db.level = 42;
})?;

// You can also return from a `.read()`. But don't forget that you cannot return references
// into the structure
let value = db.read(|db| db.level)?;
assert_eq!(42, value);

Write lock the database and get write access to the Data container in a safe way

This gives you an exclusive lock on the memory object. Trying to open the database in writing will block if it is currently being written to.

This differs to Database::write in that a clone of the internal data is made, which is then passed to the closure. Only if the closure doesn't panic is the internal model updated.

Depending on the size of the database this can be very costly. This is a tradeoff to make for panic safety.

You should read the documentation about this: UnwindSafe

Panics

When the closure panics, it is caught and a error::RustbreakErrorKind::WritePanic will be returned.

Examples

use rustbreak::{
    FileDatabase,
    deser::Ron,
    error::{
        RustbreakError,
        RustbreakErrorKind,
    }
};

#[derive(Debug, Serialize, Deserialize, Clone)]
struct Data {
    level: u32,
}

let db = FileDatabase::<Data, Ron>::from_file(file, Data { level: 0 })?;

let result = db.write_safe(|db| {
    db.level = 42;
    panic!("We panic inside the write code.");
}).expect_err("This should have been caught");

match result.kind() {
    RustbreakErrorKind::WritePanic => {
        // We can now handle this, in this example we will just ignore it
    }
    e => {
        println!("{:#?}", e);
        // You should always have generic error catching here.
        // This future-proofs your code, and makes your code more robust.
        // In this example this is unreachable though, and to assert that we have this
        // macro here
        unreachable!();
    }
}

// We read it back out again, it has not changed
let value = db.read(|db| db.level)?;
assert_eq!(0, value);

Read lock the database and get write access to the Data container

This gives you a read-only lock on the database. You can have as many readers in parallel as you wish.

Errors

May return:

  • error::RustbreakErrorKind::Backend

Panics

If you panic in the closure, the database is poisoned. This means that any subsequent writes/reads will fail with an error::RustbreakErrorKind::Poison. You can only recover from this by re-creating the Database Object.

Read lock the database and get access to the underlying struct

This gives you access to the underlying struct, allowing for simple read only operations on it.

Examples

use rustbreak::{FileDatabase, deser::Ron};

#[derive(Debug, Serialize, Deserialize, Clone)]
struct Data {
    level: u32,
}

let db = FileDatabase::<Data, Ron>::from_file(file, Data { level: 0 })?;

db.write(|db| {
    db.level = 42;
})?;

let data = db.borrow_data()?;

assert_eq!(42, data.level);

Write lock the database and get access to the underlying struct

This gives you access to the underlying struct, allowing you to modify it.

Panics

If you panic while holding this reference, the database is poisoned. This means that any subsequent writes/reads will fail with an std::sync::PoisonError. You can only recover from this by re-creating the Database Object.

If you do not have full control over the code being written, and cannot incur the cost of having a single operation panicking then use Database::write_safe.

Examples

use rustbreak::{FileDatabase, deser::Ron};

#[derive(Debug, Serialize, Deserialize, Clone)]
struct Data {
    level: u32,
}

let db = FileDatabase::<Data, Ron>::from_file(file, Data { level: 0 })?;

{
    let mut data = db.borrow_data_mut()?;
    data.level = 42;
}

let data = db.borrow_data()?;

assert_eq!(42, data.level);

Load the Data from the backend

Flush the data structure to the backend

Get a clone of the data as it is in memory right now

To make sure you have the latest data, call this method with load true

Puts the data as is into memory

To save the data afterwards, call with save true.

Create a database from its constituents

Break a database into its individual parts

Tries to clone the Data in the Database.

This method returns a MemoryDatabase which has an empty vector as a backend initially. This means that the user is responsible for assigning a new backend if an alternative is wanted.

Examples

use rustbreak::{FileDatabase, deser::Ron};

#[derive(Debug, Serialize, Deserialize, Clone)]
struct Data {
    level: u32,
}

let db = FileDatabase::<Data, Ron>::from_file(file, Data { level: 0 })?;

db.write(|db| {
    db.level = 42;
})?;

db.save()?;

let other_db = db.try_clone()?;

// You can also return from a `.read()`. But don't forget that you cannot return references
// into the structure
let value = other_db.read(|db| db.level)?;
assert_eq!(42, value);

impl<Data, DeSer> Database<Data, FileBackend, DeSer> where
    Data: Serialize + DeserializeOwned + Debug + Clone + Send,
    DeSer: DeSerializer<Data> + Debug + Send + Sync + Clone
[src]

Create new FileDatabase from Path

Create new FileDatabase from a file

impl<Data, DeSer> Database<Data, MemoryBackend, DeSer> where
    Data: Serialize + DeserializeOwned + Debug + Clone + Send,
    DeSer: DeSerializer<Data> + Debug + Send + Sync + Clone
[src]

Create new FileDatabase from Path

impl<Data, DeSer> Database<Data, MmapStorage, DeSer> where
    Data: Serialize + DeserializeOwned + Debug + Clone + Send,
    DeSer: DeSerializer<Data> + Debug + Send + Sync + Clone
[src]

Create new MmapDatabase.

Create new MmapDatabase with specified initial size.

impl<Data, Back, DeSer> Database<Data, Back, DeSer>
[src]

Exchanges the DeSerialization strategy with the new one

impl<Data, Back, DeSer> Database<Data, Back, DeSer>
[src]

Exchanges the Backend with the new one

The new backend does not necessarily have the latest data saved to it, so a .save should be called to make sure that it is saved.

impl<Data, Back, DeSer> Database<Data, Back, DeSer> where
    Data: Serialize + DeserializeOwned + Debug + Clone + Send,
    Back: Backend + Debug,
    DeSer: DeSerializer<Data> + Debug + Send + Sync + Clone
[src]

Converts from one data type to another

This method is useful to migrate from one datatype to another

Trait Implementations

impl<Data: Debug, Back: Debug, DeSer: Debug> Debug for Database<Data, Back, DeSer>
[src]

Formats the value using the given formatter. Read more

Auto Trait Implementations

impl<Data, Back, DeSer> Send for Database<Data, Back, DeSer> where
    Back: Send,
    Data: Send,
    DeSer: Send

impl<Data, Back, DeSer> Sync for Database<Data, Back, DeSer> where
    Back: Send,
    Data: Send + Sync,
    DeSer: Sync