Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add load_or_new function that loads a DB if available, and if not, create DB #22

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions src/pickledb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::iterators::{PickleDbIterator, PickleDbListIterator};
use crate::serialization::SerializationMethod;
use crate::serialization::Serializer;

#[derive(Copy, Clone)]
/// An enum that determines the policy of dumping PickleDb changes into the file
pub enum PickleDbDumpPolicy {
/// Never dump any change, file will always remain read-only
Expand Down Expand Up @@ -71,6 +72,34 @@ impl PickleDb {
}
}

/// Attempts to load a DB from a file, and if it fails to load, constructs a new `PickleDb` instance.
///
/// # Arguments
///
/// * `db_path` - a path where the DB will be stored
/// * `dump_policy` - an enum value that determines the policy of dumping DB changes into the file. Please see
/// [PickleDb::load()](#method.load) to understand the different policy options
/// * `serialization_method` - the serialization method to use for storing the data to memory and file
///
/// # Examples
///
/// ```no_run
/// use pickledb::{PickleDb, PickleDbDumpPolicy, SerializationMethod};
///
/// let mut db = PickleDb::load_or_new("example.db", PickleDbDumpPolicy::AutoDump, SerializationMethod::Json);
/// ```
///
pub fn load_or_new<P: AsRef<Path>>(
db_path: P,
dump_policy: PickleDbDumpPolicy,
serialization_method: SerializationMethod,
) -> Result<PickleDb> {
match db_path.as_ref().exists() {
true => PickleDb::load(db_path, dump_policy, serialization_method),
false => Ok(PickleDb::new(db_path, dump_policy, serialization_method)),
}
}

/// Constructs a new `PickleDb` instance that uses [JSON serialization](https://crates.io/crates/serde_json) for storing the data.
///
/// # Arguments
Expand Down Expand Up @@ -550,14 +579,8 @@ impl PickleDb {
///
pub fn get_all(&self) -> Vec<String> {
[
self.map
.iter()
.map(|(key, _)| key.clone())
.collect::<Vec<String>>(),
self.list_map
.iter()
.map(|(key, _)| key.clone())
.collect::<Vec<String>>(),
self.map.keys().cloned().collect::<Vec<String>>(),
self.list_map.keys().cloned().collect::<Vec<String>>(),
]
.concat()
}
Expand Down
2 changes: 1 addition & 1 deletion src/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type DbListMap = HashMap<String, Vec<Vec<u8>>>;

/// An enum for specifying the serialization method to use when creating a new PickleDB database
/// or loading one from a file
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
pub enum SerializationMethod {
/// [JSON serialization](https://crates.io/crates/serde_json)
Json,
Expand Down
120 changes: 120 additions & 0 deletions tests/pickledb_key_value_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,123 @@ fn iter_test(ser_method_int: i32) {
// verify all 5 keys were seen
assert_eq!(keys_seen.iter().filter(|&t| *t).count(), 5);
}

#[rstest_parametrize(ser_method_int, case(0), case(1), case(2), case(3))]
fn basic_set_get_load_or_new(ser_method_int: i32) {
test_setup!("basic_set_get_load_or_new", ser_method_int, db_name);

let mut db = PickleDb::load_or_new(
&db_name,
PickleDbDumpPolicy::AutoDump,
ser_method!(ser_method_int),
);

// set a number
let num = 100;
db.set("num", &num).unwrap();

// set a floating point number
let float_num = 1.224;
db.set("float", &float_num).unwrap();

// set a String
let mystr = String::from("my string");
db.set("string", &mystr).unwrap();

// set a Vec
let myvec = vec![1, 2, 3];
db.set("vec", &myvec).unwrap();

// set a struct
#[derive(Serialize, Deserialize, Debug)]
struct Coor {
x: i32,
y: i32,
}
let mycoor = Coor { x: 1, y: 2 };
db.set("struct", &mycoor).unwrap();

// read a num
assert_eq!(db.get::<i32>("num").unwrap(), num);
// read a floating point number
assert_eq!(db.get::<f32>("float").unwrap(), float_num);
// read a String
assert_eq!(db.get::<String>("string").unwrap(), mystr);
// read a Vec
assert_eq!(db.get::<Vec<i32>>("vec").unwrap(), myvec);
// read a struct
assert_eq!(db.get::<Coor>("struct").unwrap().x, mycoor.x);
assert_eq!(db.get::<Coor>("struct").unwrap().y, mycoor.y);
}

#[rstest_parametrize(ser_method_int, case(0), case(1), case(2), case(3))]
fn load_or_new(ser_method_int: i32) {
test_setup!("load_or_new", ser_method_int, db_name);

let mut db = PickleDb::new(
&db_name,
PickleDbDumpPolicy::AutoDump,
ser_method!(ser_method_int),
);

// set a number
let num = 100;
db.set("num", &num).unwrap();

// set a floating point number
let float_num = 1.224;
db.set("float", &float_num).unwrap();

// set a String
let mystr = String::from("my string");
db.set("string", &mystr).unwrap();

// set a Vec
let myvec = vec![1, 2, 3];
db.set("vec", &myvec).unwrap();

// set a struct
#[derive(Serialize, Deserialize, Debug)]
struct Coor {
x: i32,
y: i32,
}
let mycoor = Coor { x: 1, y: 2 };
db.set("struct", &mycoor).unwrap();

// read a num
assert_eq!(db.get::<i32>("num").unwrap(), num);
// read a floating point number
assert_eq!(db.get::<f32>("float").unwrap(), float_num);
// read a String
assert_eq!(db.get::<String>("string").unwrap(), mystr);
// read a Vec
assert_eq!(db.get::<Vec<i32>>("vec").unwrap(), myvec);
// read a struct
assert_eq!(db.get::<Coor>("struct").unwrap().x, mycoor.x);
assert_eq!(db.get::<Coor>("struct").unwrap().y, mycoor.y);

// drop database
drop(db);

// create new database that should load from existing database
let db = PickleDb::load_or_new(
&db_name,
PickleDbDumpPolicy::AutoDump,
ser_method!(ser_method_int),
);

// assert data is identical to existing database

// read a num
assert_eq!(db.get::<i32>("num").unwrap(), num);
// read a floating point number
assert_eq!(db.get::<f32>("float").unwrap(), float_num);
// read a String
assert_eq!(db.get::<String>("string").unwrap(), mystr);
// read a Vec
assert_eq!(db.get::<Vec<i32>>("vec").unwrap(), myvec);
// read a struct
assert_eq!(db.get::<Coor>("struct").unwrap().x, mycoor.x);
assert_eq!(db.get::<Coor>("struct").unwrap().y, mycoor.y);
}