pak-db

Crates.iopak-db
lib.rspak-db
version0.2.2
created_at2025-03-07 07:38:18.445563+00
updated_at2026-01-12 05:47:37.064325+00
descriptionA read-only database format designed for speed, ease of use and data sharing.
homepage
repository
max_upload_size
id1582500
size125,589
Brooks Palin (MrVintage710)

documentation

README

alt text

Crates.io Version docs.rs

This crate is still in very early development and is not ready for production use.

Pak is a simple read-only database file that is meant for persistence of rust types for distribution. It is designed to be fast and easy to use.

Why Pak?

Pak was made for a very specific use case. Its designed to store a lot of data, be fast to read data, and easy to use in an enviornment where the you don't need to mutate the data often.

You should use Pak if you:

  • Want to easily persist rust types and share them between programs and/or runs.
  • Need to store alot of data and that can be efficiently accessed and shared.
  • Don't care about runtime mutability.

You shouldn't use Pak if you:

  • Need to modify data during runtime.
  • Require complex queries with the SQL language. (Pak does not support SQL queries right now, it may in the future.)

How to use Pak

There are 3 steps to using Pak. First you must make data to store, then you build the Pak, then you must query the data.

Adding Required Crates

Make sure that you add the following to your Cargo.toml file:

[dependencies]
pak-db = "0.2.0"
serde = { version = "1.0.228", features = ["derive"] }

Serde is a crate that assists in serialzation and deserialisation of objects. The traits that it provides is needed to use Pak.

Making Data Pakable

To make data Pakable, you simply must implement the Serialize and Deserialize traits.

#[derive(Serialize, Deserialize)]
pub struct Person {
    name: String,
    age: u32,
}

This will allow your types to be serialized and deserialized by Pak.

You also may want to implement the PakItemSearchable trait to allow your types to be searched by Pak.

impl PakItemSearchable for Person {
    fn get_indices(&self, indices : &mut Indices) {
        // The following values can be used as indices: 
        // &str
        // String
        // f64, f32
        // i64, i32, i16, i8
        // u64, u32, u16, u8
        // bool
        // Plus any type above inside of: Option<T>, Vec<T>
        indices.add("name", self.name.clone());
        indices.add("age", self.age.clone());
    }
}

This will allow any Person type to be searched by Pak, given a name. You can return as many indices as you want, but remember that this will add size to the Pak file. If you are trying to optimize for space, you may want to consider only indexing the values that you want to search with Pak.

Building a Pak file.

Once you have all of the data that you want to store in a Pak file, you can build it using the PakBuilder struct as so:

use pak::PakBuilder;

let person = Person { name: "John Doe".to_string(), age: 30 };

let mut paker = PakBuilder::new();

//This will add the object to the Pak file with it's searchable indices and return the pointer to the object.
let pointer = paker.pak(person);

//This will add the object to the Pak file without searchable indices and return the pointer to the object.
let pointer = paker.pak_no_search(person);

// This will build the Pak file and return the Pak object.
let pak = paker.build_file("output.pak");

// This will build the Pak file in memory and return the Pak object.
let pak = paker.build_memory(); 

Note that whenever you pak an object, the pointer to that object is returned. This is the primary way to access a non searchable object in the Pak file. You can save these pointers on any object in the pak, as they implement the Serialize and Deserialize traits.

Consuming a Pak File

After you have built the pak file, you can open it by calling the following:

let pak = Pak::new_from_file("output.pak");

This creates and instance of the Pak struct that you can read from. The primary way to do that is to use the query function.

use pak::index::{PakIndex, PakIndexIdentifier}

//This is a simple query that will look in the pak for a "Person" object with a name value of "John".
let query = "name".equals("John");

//This will query for all structs of type person with a name value of "John"
let result = pak.query::<(Person,)>(query);

Pak also contains a simple and light weight query language called pql (pak query language). Here is an example of how to use it:

let result = pak.query_pql::<(Person, )>("name = John & age < 35")

If you want to query more then one type, just add it to the type signature

// Movie and Pet also derive Deserialize
let result = pak.query_pql::<(Person, Pet, Movie)>("name = John | age < 35")

If you want to get all instances of a certain type from the Pak, you can do one of the following:

let result = pak.query_pql::<(Person, )>("all")
let result = pak.query::<(Person,)>(PakQuery::All);

For more information on queries, see the query documentation.

Commit count: 0

cargo fmt