Skip to content

Commit

Permalink
Merge pull request #33 from yatharthmathur/ym_add_hashmaps
Browse files Browse the repository at this point in the history
feat(TYPES): added hashmaps in the store
  • Loading branch information
yatharthmathur authored Jan 12, 2024
2 parents 3dc4be9 + e6a8a19 commit 2a9cf3e
Show file tree
Hide file tree
Showing 7 changed files with 366 additions and 23 deletions.
9 changes: 8 additions & 1 deletion src/data_store/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@ pub enum TypeConversionError {
// Add other type cast error variants as needed
}

#[derive(Debug)]
pub enum TypeConversionImpossible {
IncompatibleTypes,
AsReference,
AsMutable,
}

#[derive(Debug)]
pub enum ValueError {
TypeConversionImpossible,
TypeConversionImpossible(TypeConversionImpossible),
TypeConversionError(TypeConversionError),
}
137 changes: 137 additions & 0 deletions src/data_store/implementations/hmaps/hmaps.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use crate::data_store::{errors::ValueError, store::KeyValueStore, value_entry::ValueEntry};
use std::{
collections::HashMap,
time::{Duration, Instant},
};

impl KeyValueStore {
/// Inserts a Key-Value(in HashMap<(String, String)> type) pair in the KeyValueStore
pub fn set_hmap(&mut self, key: String, value: Vec<(String, String)>, ttl: Option<u64>) {
let expiration = Instant::now() + Duration::from_millis(ttl.unwrap_or(self.default_ttl));
let value_entry = ValueEntry::from_hashmap(HashMap::from_iter(value), expiration);
self._insert(&key, &value_entry);
}

/// Gets a Value (converted to set<String> type) associated to the Key in the KeyValueStore
pub fn get_hmap(&self, key: String) -> Option<Result<HashMap<String, String>, ValueError>> {
match self._get_or_none_if_expired(&key) {
Some(value_entry) => Some(value_entry.get_value_as_hmap()),
_ => None,
}
}

fn _get_mut_hmap(
&mut self,
key: String,
) -> Option<Result<&mut HashMap<String, String>, ValueError>> {
match self._get_mut_or_none_if_expired(&key) {
Some(value_entry) => Some(value_entry.get_value_as_mut_hmap()),
None => None,
}
}

/// Set a key-value pair in the hash map associated with a key
/// Then return the size of the hmap.
pub fn hmap_insert(
&mut self,
key: String,
kv_pair: (String, String),
) -> Option<Result<usize, ValueError>> {
match self._get_mut_hmap(key) {
Some(Ok(hmap)) => {
hmap.insert(kv_pair.0, kv_pair.1);
Some(Ok(hmap.len()))
}
Some(Err(e)) => Some(Err(e)),
None => None,
}
}

/// Gets a value for a provided hmap_key from the hash map associated with the storage key
pub fn hmap_get(&self, key: String, hmap_key: String) -> Option<Result<String, ValueError>> {
match self.get_hmap(key) {
Some(Ok(hmap)) => {
if let Some(value) = hmap.get(&hmap_key) {
Some(Ok(value.to_owned()))
} else {
None
}
}
Some(Err(e)) => Some(Err(e)),
None => None,
}
}

/// Removes a key-value pair for a provided hmap_key from the hash map associated with the storage key
/// also returns the pair
pub fn hmap_remove(
&mut self,
key: String,
hmap_key: String,
) -> Option<Result<(String, String), ValueError>> {
match self._get_mut_hmap(key) {
Some(Ok(hmap)) => {
if let Some(value) = hmap.remove_entry(&hmap_key) {
Some(Ok(value))
} else {
None
}
}
Some(Err(e)) => Some(Err(e)),
None => None,
}
}

/// Checks if a hmap_key is present in the hmap associated with a key
pub fn hmap_contains_key(
&self,
key: String,
hmap_key: String,
) -> Option<Result<bool, ValueError>> {
match self.get_hmap(key) {
Some(Ok(hmap)) => Some(Ok(hmap.contains_key(&hmap_key))),
Some(Err(e)) => Some(Err(e)),
None => None,
}
}

/// Gets the size of the hmap associated with a key
pub fn hmap_size(&self, key: String) -> Option<Result<usize, ValueError>> {
match self.get_hmap(key) {
Some(Ok(hmap)) => Some(Ok(hmap.len())),
Some(Err(e)) => Some(Err(e)),
None => None,
}
}

// Gets all the hmap_keys of the hmap associated with a key
pub fn hmap_keys(&self, key: String) -> Option<Result<Vec<String>, ValueError>> {
match self.get_hmap(key) {
Some(Ok(hmap)) => Some(Ok(Vec::from_iter(hmap.keys().map(|item| item.to_owned())))),
Some(Err(e)) => Some(Err(e)),
None => None,
}
}

// Gets all the hmap_values of the hmap associated with a key
pub fn hmap_values(&self, key: String) -> Option<Result<Vec<String>, ValueError>> {
match self.get_hmap(key) {
Some(Ok(hmap)) => Some(Ok(Vec::from_iter(
hmap.values().map(|item| item.to_owned()),
))),
Some(Err(e)) => Some(Err(e)),
None => None,
}
}

// Gets all the (hmap_keys, hmap_values) pairs of the hmap associated with a key
pub fn hmap_items(&self, key: String) -> Option<Result<Vec<(String, String)>, ValueError>> {
match self.get_hmap(key) {
Some(Ok(hmap)) => Some(Ok(Vec::from_iter(
hmap.iter().map(|(k, v)| (k.to_owned(), v.to_owned())),
))),
Some(Err(e)) => Some(Err(e)),
None => None,
}
}
}
2 changes: 2 additions & 0 deletions src/data_store/implementations/hmaps/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod hmaps;
mod tests;
151 changes: 151 additions & 0 deletions src/data_store/implementations/hmaps/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
use crate::data_store::store::KeyValueStore;

#[test]
fn test_insert_get_hmap() {
let mut store = KeyValueStore::new(5000);
store.set_hmap("ABC".to_string(), vec![], None);

assert_eq!(
store
.hmap_insert("ABC".to_string(), ("A".to_string(), "B".to_string()))
.unwrap()
.unwrap(),
1
);
assert_eq!(store.hmap_size("ABC".to_string()).unwrap().unwrap(), 1);

assert_eq!(
store
.hmap_insert("ABC".to_string(), ("B".to_string(), "C".to_string()))
.unwrap()
.unwrap(),
2
);
assert_eq!(store.hmap_size("ABC".to_string()).unwrap().unwrap(), 2);

assert!(store
.hmap_contains_key("ABC".to_string(), "B".to_string())
.unwrap()
.unwrap());
assert_eq!(
store
.hmap_contains_key("ABC".to_string(), "C".to_string())
.unwrap()
.unwrap(),
false
);
}

#[test]
fn test_hmap_keys_values_items() {
let mut store = KeyValueStore::new(5000);
store.set_hmap("ABC".to_string(), vec![], None);

assert_eq!(
store
.hmap_insert("ABC".to_string(), ("A".to_string(), "B".to_string()))
.unwrap()
.unwrap(),
1
);
assert_eq!(store.hmap_size("ABC".to_string()).unwrap().unwrap(), 1);

assert_eq!(
store
.hmap_insert("ABC".to_string(), ("B".to_string(), "C".to_string()))
.unwrap()
.unwrap(),
2
);
assert_eq!(store.hmap_size("ABC".to_string()).unwrap().unwrap(), 2);

assert_eq!(
store
.hmap_insert("ABC".to_string(), ("C".to_string(), "A".to_string()))
.unwrap()
.unwrap(),
3
);
assert_eq!(store.hmap_size("ABC".to_string()).unwrap().unwrap(), 3);

let keys = store.hmap_keys("ABC".to_string()).unwrap().unwrap();
let mut sorted_keys = keys.to_owned();
sorted_keys.sort();

let values = store.hmap_values("ABC".to_string()).unwrap().unwrap();
let values_in_order_of_keys: Vec<String> = keys
.iter()
.map(|item| {
store
.hmap_get("ABC".to_string(), item.to_owned())
.unwrap()
.unwrap()
})
.collect();

let mut items = store.hmap_items("ABC".to_string()).unwrap().unwrap();
items.sort();

assert_eq!(sorted_keys, vec!["A", "B", "C"]);
assert_eq!(values, values_in_order_of_keys);
assert_eq!(
items,
vec![
("A".to_string(), "B".to_string()),
("B".to_string(), "C".to_string()),
("C".to_string(), "A".to_string())
]
);
}

#[test]
fn test_remove_hmap() {
let mut store = KeyValueStore::new(5000);
store.set_hmap("ABC".to_string(), vec![], None);

assert_eq!(
store
.hmap_insert("ABC".to_string(), ("A".to_string(), "B".to_string()))
.unwrap()
.unwrap(),
1
);
assert_eq!(store.hmap_size("ABC".to_string()).unwrap().unwrap(), 1);

assert_eq!(
store
.hmap_insert("ABC".to_string(), ("B".to_string(), "C".to_string()))
.unwrap()
.unwrap(),
2
);
assert_eq!(store.hmap_size("ABC".to_string()).unwrap().unwrap(), 2);

assert_eq!(
store
.hmap_remove("ABC".to_string(), "A".to_string())
.unwrap()
.unwrap(),
("A".to_string(), "B".to_string())
);
assert_eq!(store.hmap_size("ABC".to_string()).unwrap().unwrap(), 1);

assert_eq!(
store
.hmap_contains_key("ABC".to_string(), "A".to_string())
.unwrap()
.unwrap(),
false
);

assert!(store
.hmap_remove("ABC".to_string(), "C".to_string())
.is_none());
assert_eq!(
store
.hmap_contains_key("ABC".to_string(), "C".to_string())
.unwrap()
.unwrap(),
false
);
}
7 changes: 2 additions & 5 deletions src/data_store/implementations/hsets/hsets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ impl KeyValueStore {
/// Inserts a Key-Value(in HashSet<String> type) pair in the KeyValueStore
pub fn set_hset(&mut self, key: String, value: Vec<String>, ttl: Option<u64>) {
let expiration = Instant::now() + Duration::from_millis(ttl.unwrap_or(self.default_ttl));
let value_entry = ValueEntry::from_set(HashSet::from_iter(value), expiration);
let value_entry = ValueEntry::from_hset(HashSet::from_iter(value), expiration);
self._insert(&key, &value_entry);
}

Expand All @@ -22,10 +22,7 @@ impl KeyValueStore {

fn _get_mut_hset(&mut self, key: String) -> Option<Result<&mut HashSet<String>, ValueError>> {
match self._get_mut_or_none_if_expired(&key) {
Some(value_entry) => match value_entry.get_value_as_mut_hset() {
Ok(hset) => Some(Ok(hset)),
Err(e) => Some(Err(e)),
},
Some(value_entry) => Some(value_entry.get_value_as_mut_hset()),
None => None,
}
}
Expand Down
1 change: 1 addition & 0 deletions src/data_store/implementations/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod bytes;
mod hmaps;
mod hsets;
mod integers;
mod lists;
Expand Down
Loading

0 comments on commit 2a9cf3e

Please sign in to comment.