Skip to content

Commit

Permalink
feat: update data struct name and errors
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugo Rosenkranz-Costa committed Nov 13, 2023
1 parent b025097 commit 1466ed8
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/abe_policy/dimension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl AttributeParameters {
self.oldest_rotation_value = self.current_rotation_value
}

pub fn all_rotation_values(&self) -> impl Iterator<Item = u32> {
pub fn all_rotation_values(&self) -> impl DoubleEndedIterator<Item = u32> {
self.oldest_rotation_value..=self.current_rotation_value
}

Expand Down
2 changes: 1 addition & 1 deletion src/abe_policy/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ impl Policy {
/// The current value is returned first.
pub fn attribute_values(&self, attribute: &Attribute) -> Result<Vec<u32>, Error> {
self.get_attribute(attribute)
.map(|attr| attr.all_rotation_values().collect())
.map(|attr| attr.all_rotation_values().rev().collect())
}

/// Returns the hybridization hint of the given attribute.
Expand Down
1 change: 1 addition & 0 deletions src/core/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ pub fn refresh(
decryption_set: &HashSet<Partition>,
) -> Result<(), Error> {
verify_user_key_kmac(msk, usk)?;
// TODO: keep track of previous rotation values
usk.subkeys.clear();

for partition in decryption_set {
Expand Down
44 changes: 44 additions & 0 deletions src/data_struct/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use std::fmt::{Debug, Display};

type Key = String;
#[derive(Debug)]
pub enum Error {
EntryNotFound(Key),
ExistingEntry(Key),
AlreadyHasChild(Key),
}

impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self {
Error::EntryNotFound(key) => write!(f, "Entry not found with key: {key}."),
Error::ExistingEntry(key) => write!(f, "Already existing entry with key: {key}."),
Error::AlreadyHasChild(key) => {
write!(f, "Entry with key {key} already has a child.")
}
}
}
}

impl Error {
pub fn missing_entry<T>(key: &T) -> Self
where
T: Debug,
{
Self::EntryNotFound(format!("{:?}", key))
}

pub fn existing_entry<T>(key: &T) -> Self
where
T: Debug,
{
Self::ExistingEntry(format!("{:?}", key))
}

pub fn already_has_child<T>(key: &T) -> Self
where
T: Debug,
{
Self::AlreadyHasChild(format!("{:?}", key))
}
}
36 changes: 19 additions & 17 deletions src/data_struct/linked_hashmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,30 @@ use std::{
hash_map::{Entry, OccupiedEntry},
HashMap,
},
fmt::Debug,
hash::Hash,
};

use crate::Error;
use super::error::Error;

/// a `VersionedHashMap` stores a flat list of linked lists.
/// each map entry contains its value as well as an optional key of the next
/// entry version in the hash map.
///
/// Map {
/// k1 : VersionedEntry { "data v1", k1' }
/// k2 : VersionedEntry { "...", None }
/// k1' : VersionedEntry { "data v2", k1'' }
/// k3 : VersionedEntry { "value 1", k3' }
/// k3' : VersionedEntry { "value 2", None }
/// k1'': VersionedEntry { "data v3", None }
/// k1 : { "data v1", k1' }
/// k2 : { "...", None }
/// k1' : { "data v2", k1'' }
/// k3 : { "value 1", k3' }
/// k3' : { "value 2", None }
/// k1'': { "data v3", None }
/// }
///
/// The entry versions are stored in chronological order so that from any
/// given version one can find all the following versions until the current one.
///
/// New entry versions can only be added at the back of the chain and removing
/// starts from the beginning ensuring the order stays consistent.
#[derive(Default)]
pub struct VersionedHashMap<K, V> {
map: HashMap<K, VersionedEntry<K, V>>,
Expand Down Expand Up @@ -60,7 +64,7 @@ struct VersionedHashMapIterator<'a, K, V> {
impl<'a, K, V> Iterator for VersionedHashMapIterator<'a, K, V>
where
V: Clone,
K: Hash + Eq + PartialEq + Clone + PartialOrd + Ord,
K: Hash + Eq + PartialEq + Clone + PartialOrd + Ord + Debug,
{
type Item = (&'a K, &'a V);

Expand All @@ -76,7 +80,7 @@ where

impl<K, V> VersionedHashMap<K, V>
where
K: Hash + PartialEq + Eq + Clone + PartialOrd + Ord,
K: Hash + PartialEq + Eq + Clone + PartialOrd + Ord + Debug,
V: Clone,
{
pub fn new() -> Self {
Expand Down Expand Up @@ -105,7 +109,7 @@ where
fn expected_entry(&mut self, key: K) -> Result<OccupiedEntry<K, VersionedEntry<K, V>>, Error> {
match self.map.entry(key) {
Entry::Occupied(e) => Ok(e),
Entry::Vacant(_) => Err(Error::KeyError("Key not found".to_string())),
Entry::Vacant(e) => Err(Error::missing_entry(e.key())),
}
}

Expand All @@ -116,7 +120,7 @@ where

pub fn insert_root(&mut self, key: K, value: V) -> Result<(), Error> {
match self.map.entry(key.clone()) {
Entry::Occupied(_) => Err(Error::KeyError("Key is already used".to_string())),
Entry::Occupied(_) => Err(Error::existing_entry(&key)),
Entry::Vacant(entry) => {
entry.insert(VersionedEntry::new(value));
//self.roots.push(key);
Expand All @@ -127,20 +131,18 @@ where
}

pub fn insert(&mut self, parent_key: &K, key: K, value: V) -> Result<(), Error> {
// Get parent element from hashmap and check that it has no child already
// Get parent from hashmap and check that it does not already have a child
let parent_entry = match self.map.get(parent_key) {
Some(linked_entry) => Ok(linked_entry),
None => Err(Error::KeyError("Parent key not found".to_string())),
None => Err(Error::missing_entry(parent_key)),
}?;
if parent_entry.next_key.is_some() {
return Err(Error::KeyError(
"Parent already contains a next key".to_string(),
));
return Err(Error::already_has_child(parent_key));
}

// Insert new key-value pair in hashmap and set parent child
match self.map.entry(key.clone()) {
Entry::Occupied(_) => Err(Error::KeyError("Key is already used".to_string())),
Entry::Occupied(_) => Err(Error::existing_entry(&key)),
Entry::Vacant(entry) => {
entry.insert(VersionedEntry::new(value));
// cannot hold mutable reference from parent_entry
Expand Down
56 changes: 38 additions & 18 deletions src/data_struct/linked_vec.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::LinkedList;

use crate::Error;
use super::error::Error;

/// a `VersionedVec` stores for each entry a linked list of versions.
/// The entry versions are stored in reverse chronological order:
Expand Down Expand Up @@ -37,27 +37,36 @@ impl<T> VersionedVec<T> {
}

pub fn len(&self) -> usize {
//self.data.iter().map(|list| list.len()).sum()
self.length
}

pub fn is_empty(&self) -> bool {
self.len() == 0
}

pub fn push_front(&mut self, chain_index: usize, item: T) -> Result<(), Error> {
let chain = self
.data
.get_mut(chain_index)
.ok_or(Error::missing_entry(&chain_index))?;

self.length += 1;
chain.push_front(item);
Ok(())
}

/// Inserts entry versions in reverse chronological order
/// The iterator must be in chronological order as the items are inserted
/// backward.
pub fn insert_new_chain(&mut self, iterator: impl Iterator<Item = T>) -> Result<(), Error> {
pub fn insert_new_chain(&mut self, iterator: impl Iterator<Item = T>) {
let mut new_list = LinkedList::new();
for item in iterator {
new_list.push_front(item);
}

self.length += new_list.len();
self.data.push(new_list);

Ok(())
if !new_list.is_empty() {
self.length += new_list.len();
self.data.push(new_list);
}
}

/// Removes old entry versions.
Expand All @@ -74,9 +83,20 @@ impl<T> VersionedVec<T> {
}*/

/// Removes old entry version.
pub fn pop_back(&mut self, chain_index: usize) -> Option<T> {
// TODO: update len
self.data.get_mut(chain_index)?.pop_back()
pub fn pop_back(&mut self, chain_index: usize) -> Result<T, Error> {
let chain = self
.data
.get_mut(chain_index)
.ok_or(Error::missing_entry(&chain_index))?;

let removed_item = chain.pop_back().expect("chains should not be empty");
self.length -= 1;

if chain.is_empty() {
self.data.swap_remove(chain_index);
}

Ok(removed_item)
}

/// Provides reference to the oldest entry version.
Expand Down Expand Up @@ -108,23 +128,23 @@ fn test_linked_vec() -> Result<(), Error> {
(11, "key111".to_string()),
]
.into_iter(),
)?;
lv.insert_new_chain(vec![(2, "key2".to_string()), (22, "key22".to_string())].into_iter())?;
lv.insert_new_chain(vec![(3, "key3".to_string())].into_iter())?;
);
lv.insert_new_chain(vec![(2, "key2".to_string()), (22, "key22".to_string())].into_iter());
lv.insert_new_chain(vec![(3, "key3".to_string())].into_iter());

assert_eq!(lv.data.len(), 3);
assert_eq!(lv.len(), 6);

assert!(lv.pop_back(0).is_some());
lv.pop_back(0)?;
assert_eq!(lv.len(), 5);

assert!(lv.pop_back(1).is_some());
lv.pop_back(1)?;
assert_eq!(lv.len(), 4);

assert!(lv.pop_back(2).is_some());
lv.pop_back(2)?;
assert_eq!(lv.len(), 3);
// the chain 3 was completely removed
assert!(lv.pop_back(2).is_none());
lv.pop_back(2)?;

assert_eq!(lv.iter_chain(0).collect::<Vec<_>>().len(), 2);

Expand Down
2 changes: 2 additions & 0 deletions src/data_struct/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub mod linked_hashmap;
pub mod linked_vec;

pub mod error;

use linked_hashmap::VersionedHashMap;
use linked_vec::VersionedVec;

0 comments on commit 1466ed8

Please sign in to comment.