Skip to main content

Database

Struct Database 

Source
pub struct Database<D, B, F> { /* private fields */ }
Expand description

The Koit database.

The database provides reading, writing, saving and reloading functionality. It uses a reader-writer lock on the internal data structure, allowing concurrent access by readers, while writers are given exclusive access.

It requires a Format marker type

Implementations§

Source§

impl<D, B, F> Database<D, B, F>
where B: Backend, F: Format<D>,

Source

pub fn from_parts(data: D, backend: B) -> Self

Create a database from its constituents.

Source

pub async fn write<T, R>(&self, task: T) -> R
where T: FnOnce(&mut D) -> R,

Write to the data contained in the database. This gives exclusive access to the underlying data structure. The value your closure returns will be passed on as the return value of this function.

This write-locks the data structure.

Source

pub async fn write_and_then<T, Fut, R>(&self, task: T) -> R
where T: FnOnce(&mut D) -> Fut, Fut: Future<Output = R>,

Same as crate::Database::write, except the task returns a future.

Source

pub async fn read<T, R>(&self, task: T) -> R
where T: FnOnce(&D) -> R,

Read the data contained in the database. Many readers can read in parallel. The value your closure returns will be passed on as the return value of this function.

This read-locks the data structure.

Source

pub async fn read_and_then<T, Fut, R>(&self, task: T) -> R
where T: FnOnce(&D) -> Fut, Fut: Future<Output = R>,

Same as crate::Database::read, except the task returns a future.

Source

pub async fn replace(&self, data: D) -> D

Replace the actual data in the database by the given data in the parameter, returning the old data.

This write-locks the data structure.

Source

pub fn get_data_lock(&self) -> &RwLock<D>

Returns a reference to the underlying data lock.

It is recommended to use the read and write methods instead of this, to ensure locks are only held for as long as needed.

§Examples
use koit::{Database, format::Json, backend::Memory};

type Messages = Vec<String>;
let db: Database<_, _, Json> = Database::from_parts(1, Memory::default());

futures::executor::block_on(async move {
    let data_lock = db.get_data_lock();
    let mut data = data_lock.write().await;
    *data = 42;
    drop(data);

    db.read(|n| assert_eq!(*n, 42)).await;
});
Source

pub fn get_data_mut(&mut self) -> &mut D

Returns a mutable reference to the underlying data.

This borrows Database mutably; no locking takes place.

§Examples
use koit::{Database, format::Json, backend::Memory};

let mut db: Database<_, _, Json> = Database::from_parts(1, Memory::default());

let n = db.get_data_mut();
*n += 41;

futures::executor::block_on(db.read(|n| assert_eq!(*n, 42)));
Source

pub async fn save(&self) -> Result<(), KoitError>

Flush the data contained in the database to the backend.

This read-locks the data structure.

§Errors
  • If the data in the database failed to be encoded by the format, an error variant is returned.
  • If the bytes failed to be written to the backend, an error variant is returned. This may mean the backend is now corrupted.
§Panics

Some back-ends (such as crate::backend::File) might panic on some async runtimes.

Source

pub async fn reload(&self) -> Result<D, KoitError>

Update this database with data from the backend, returning the old data.

This will write-lock the internal data structure.

§Errors
  • If the bytes from teh backend failed to be decoded by the format, an error variant is returned.
  • If the bytes failed to be read by the backend, an error variant is returned.
§Panics

Some back-ends (such as crate::backend::File) might panic on some async runtimes.

Source

pub fn into_parts(self) -> (D, B)

Consume the database and return its data and backend.

Source§

impl<D, F> Database<D, File, F>
where F: Format<D>,

Source

pub async fn load_from_path<P>(path: P) -> Result<Self, KoitError>
where P: AsRef<Path>,

Available on crate feature file-backend only.

Construct the file-backed database from the given path. This attempts to load data from the given file.

§Errors

If the file cannot be read, or the formatter cannot decode the data, an error variant will be returned.

Source

pub async fn load_from_path_or_else<P, T>( path: P, factory: T, ) -> Result<Self, KoitError>
where P: AsRef<Path>, T: FnOnce() -> D,

Available on crate feature file-backend only.

Construct the file-backed database from the given path. If the file does not exist, the file is created. Then factory is called and its return value is used as the initial value. This data is immediately and saved to file.

Source

pub async fn load_from_path_or_default<P>(path: P) -> Result<Self, KoitError>
where P: AsRef<Path>, D: Default,

Available on crate feature file-backend only.

Same as load_from_path_or_else, except it uses Default instead of a factory.

Trait Implementations§

Source§

impl<D: Debug, B: Debug, F: Debug> Debug for Database<D, B, F>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<D, B, F> !Freeze for Database<D, B, F>

§

impl<D, B, F> !RefUnwindSafe for Database<D, B, F>

§

impl<D, B, F> Send for Database<D, B, F>
where D: Send, B: Send, F: Send,

§

impl<D, B, F> Sync for Database<D, B, F>
where D: Send + Sync, B: Send, F: Sync,

§

impl<D, B, F> Unpin for Database<D, B, F>
where F: Unpin, D: Unpin, B: Unpin,

§

impl<D, B, F> UnsafeUnpin for Database<D, B, F>
where D: UnsafeUnpin, B: UnsafeUnpin,

§

impl<D, B, F> UnwindSafe for Database<D, B, F>
where F: UnwindSafe, D: UnwindSafe, B: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.