Skip to content

Commit 686cc89

Browse files
committed
take key by value, reduce generic requirements on traits
1 parent 9ce44f6 commit 686cc89

File tree

4 files changed

+62
-67
lines changed

4 files changed

+62
-67
lines changed

src/lib.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,28 @@
44
55
mod providers;
66

7-
use core::borrow::Borrow;
8-
97
pub use providers::*;
108

119
/// Trait for providers of append-only key-value maps.
1210
pub trait AoraMap<K, V, const KEY_LEN: usize = 32>
13-
where
14-
K: Ord + Into<[u8; KEY_LEN]> + From<[u8; KEY_LEN]>,
15-
V: Eq,
11+
where K: Into<[u8; KEY_LEN]> + From<[u8; KEY_LEN]>
1612
{
1713
/// Checks whether given value is present in the log.
18-
fn contains_key(&self, key: &K) -> bool;
14+
fn contains_key(&self, key: K) -> bool;
1915

2016
/// Retrieves value from the log.
2117
///
2218
/// # Panics
2319
///
2420
/// Panics if the item under the provided key is not present.
25-
fn get(&self, key: &K) -> Option<V>;
21+
fn get(&self, key: K) -> Option<V>;
2622

2723
/// Retrieves value from the log.
2824
///
2925
/// # Panics
3026
///
3127
/// Panics if the item under the provided key is not present.
32-
fn get_expect(&self, key: &K) -> V { self.get(key).expect("key not found") }
28+
fn get_expect(&self, key: K) -> V { self.get(key).expect("key not found") }
3329

3430
/// Inserts (appends) an item to the append-only log. If the item is already in the log, does
3531
/// noting.
@@ -61,20 +57,20 @@ where
6157
/// indexes. The values in the index are kept in the order they were added.
6258
pub trait AoraIndex<K, V, const KEY_LEN: usize = 32, const VAL_LEN: usize = 32>
6359
where
64-
K: Ord + Into<[u8; KEY_LEN]> + From<[u8; KEY_LEN]>,
65-
V: Eq + Into<[u8; VAL_LEN]> + From<[u8; VAL_LEN]>,
60+
K: Into<[u8; KEY_LEN]> + From<[u8; KEY_LEN]>,
61+
V: Into<[u8; VAL_LEN]> + From<[u8; VAL_LEN]>,
6662
{
6763
/// Returns iterator over all known keys.
6864
fn keys(&self) -> impl Iterator<Item = K>;
6965

7066
/// Checks whether given value is present in the log.
71-
fn contains_key(&self, key: &K) -> bool { self.value_len(key) > 0 }
67+
fn contains_key(&self, key: K) -> bool { self.value_len(key) > 0 }
7268

7369
/// Measures length of the value vector for the given key.
74-
fn value_len(&self, key: &K) -> usize;
70+
fn value_len(&self, key: K) -> usize;
7571

7672
/// Retrieves value vector from the log. If the key is not present, returns an empty iterator.
77-
fn get(&self, key: &K) -> impl ExactSizeIterator<Item = V>;
73+
fn get(&self, key: K) -> impl ExactSizeIterator<Item = V>;
7874

7975
/// Pushes a new value into the value array for the given key.
8076
fn push(&mut self, key: K, val: V);
@@ -85,14 +81,14 @@ where
8581
/// Requires value to be encodable as a fixed-size array.
8682
pub trait AuraMap<K, V, const KEY_LEN: usize = 32, const VAL_LEN: usize = 32>
8783
where
88-
K: Ord + Into<[u8; KEY_LEN]> + From<[u8; KEY_LEN]>,
89-
V: Eq + Into<[u8; VAL_LEN]> + From<[u8; VAL_LEN]>,
84+
K: Into<[u8; KEY_LEN]> + From<[u8; KEY_LEN]>,
85+
V: Into<[u8; VAL_LEN]> + From<[u8; VAL_LEN]>,
9086
{
9187
/// Returns iterator over all known keys.
9288
fn keys(&self) -> impl Iterator<Item = K>;
9389

9490
/// Checks whether given value is present in the log.
95-
fn contains_key(&self, key: &K) -> bool;
91+
fn contains_key(&self, key: K) -> bool;
9692

9793
/// Retrieves value from the log.
9894
///
@@ -116,7 +112,7 @@ where
116112
/// present in the log.
117113
fn insert_only(&mut self, key: K, val: V) {
118114
if let Some(v) = self.get(&key) {
119-
if v.borrow() != &val {
115+
if v.into() != val.into() {
120116
panic!("key is already inserted");
121117
}
122118
return;
@@ -132,8 +128,9 @@ where
132128
/// # Panics
133129
///
134130
/// If the key is not present in the log.
135-
fn update_only(&mut self, key: K, val: V) {
136-
if !self.contains_key(&key) {
131+
fn update_only(&mut self, key: K, val: V)
132+
where K: Copy {
133+
if !self.contains_key(key) {
137134
panic!("the key is not known");
138135
}
139136
self.insert_or_update(key, val);

src/providers/file/aomap.rs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ use crate::AoraMap;
1717
// TODO: Make unblocking with a separate thread reading and writing to the disk, communicated
1818
// through a channel
1919
pub struct FileAoraMap<K, V, const KEY_LEN: usize = 32>
20-
where
21-
K: Ord + Into<[u8; KEY_LEN]> + From<[u8; KEY_LEN]>,
22-
V: Eq,
20+
where K: Ord + Into<[u8; KEY_LEN]> + From<[u8; KEY_LEN]>
2321
{
2422
log: RefCell<File>,
2523
idx: RefCell<File>,
@@ -28,9 +26,7 @@ where
2826
}
2927

3028
impl<K, V, const KEY_LEN: usize> FileAoraMap<K, V, KEY_LEN>
31-
where
32-
K: Ord + Into<[u8; KEY_LEN]> + From<[u8; KEY_LEN]>,
33-
V: Eq,
29+
where K: Ord + Into<[u8; KEY_LEN]> + From<[u8; KEY_LEN]>
3430
{
3531
fn prepare(path: impl AsRef<Path>, name: &str) -> (PathBuf, PathBuf) {
3632
let path = path.as_ref();
@@ -74,8 +70,8 @@ where
7470

7571
let mut index = BTreeMap::new();
7672
loop {
77-
let mut id = [0u8; KEY_LEN];
78-
let res = idx.read_exact(&mut id);
73+
let mut key_buf = [0u8; KEY_LEN];
74+
let res = idx.read_exact(&mut key_buf);
7975
if matches!(res, Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof) {
8076
break;
8177
} else {
@@ -87,7 +83,7 @@ where
8783
.expect("unable to read index entry");
8884
let pos = u64::from_le_bytes(buf);
8985

90-
index.insert(id.into(), pos);
86+
index.insert(key_buf.into(), pos);
9187
}
9288

9389
log.seek(SeekFrom::End(0))
@@ -109,11 +105,11 @@ where
109105
K: Ord + Into<[u8; KEY_LEN]> + From<[u8; KEY_LEN]>,
110106
V: Eq + StrictEncode + StrictDecode,
111107
{
112-
fn contains_key(&self, key: &K) -> bool { self.index.borrow().contains_key(key) }
108+
fn contains_key(&self, key: K) -> bool { self.index.borrow().contains_key(&key) }
113109

114-
fn get(&self, key: &K) -> Option<V> {
110+
fn get(&self, key: K) -> Option<V> {
115111
let index = self.index.borrow();
116-
let pos = index.get(key)?;
112+
let pos = index.get(&key)?;
117113

118114
let mut log = self.log.borrow_mut();
119115
log.seek(SeekFrom::Start(*pos))
@@ -124,8 +120,8 @@ where
124120
}
125121

126122
fn insert(&mut self, key: K, value: &V) {
127-
if self.contains_key(&key) {
128-
let old = self.get(&key);
123+
if self.index.borrow().contains_key(&key) {
124+
let old = self.get(key);
129125
if old.as_ref() != Some(value) {
130126
panic!(
131127
"item under the given id is different from another item under the same id \

src/providers/file/aumap.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::AuraMap;
1313
pub struct FileAuraMap<K, V, const KEY_LEN: usize = 32, const VAL_LEN: usize = 32>
1414
where
1515
K: Ord + From<[u8; KEY_LEN]> + Into<[u8; KEY_LEN]>,
16-
V: Eq + From<[u8; VAL_LEN]> + Into<[u8; VAL_LEN]>,
16+
V: From<[u8; VAL_LEN]> + Into<[u8; VAL_LEN]>,
1717
{
1818
path: PathBuf,
1919
cache: BTreeMap<K, V>,
@@ -22,7 +22,7 @@ where
2222
impl<K, V, const KEY_LEN: usize, const VAL_LEN: usize> FileAuraMap<K, V, KEY_LEN, VAL_LEN>
2323
where
2424
K: Ord + From<[u8; KEY_LEN]> + Into<[u8; KEY_LEN]>,
25-
V: Eq + From<[u8; VAL_LEN]> + Into<[u8; VAL_LEN]>,
25+
V: From<[u8; VAL_LEN]> + Into<[u8; VAL_LEN]>,
2626
{
2727
pub fn create(path: PathBuf) -> io::Result<Self> {
2828
File::create_new(&path)?;
@@ -65,9 +65,9 @@ where
6565
{
6666
fn keys(&self) -> impl Iterator<Item = K> { self.cache.keys().copied() }
6767

68-
fn contains_key(&self, key: &K) -> bool { self.cache.contains_key(key) }
68+
fn contains_key(&self, key: K) -> bool { self.cache.contains_key(&key) }
6969

70-
fn get(&self, key: &K) -> Option<V> { self.cache.get(key).copied() }
70+
fn get(&self, key: &K) -> Option<V> { self.cache.get(&key).copied() }
7171

7272
fn insert_or_update(&mut self, key: K, val: V) {
7373
*self.cache.entry(key).or_insert(val) = val;

src/providers/file/index.rs

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,69 @@
11
// SPDX-License-Identifier: Apache-2.0
22

3-
use std::collections::BTreeMap;
3+
use std::collections::HashMap;
44
use std::fs::File;
55
use std::hash::Hash;
66
use std::io::{self, Read, Write};
7+
use std::marker::PhantomData;
78
use std::path::PathBuf;
89

910
use indexmap::IndexSet;
1011

1112
use crate::AoraIndex;
1213

1314
// For now, this is just an in-memory read BTree. In the next releases we need to change this.
14-
#[derive(Clone, Debug)]
15+
#[derive(Debug)]
1516
pub struct FileAoraIndex<K, V, const KEY_LEN: usize = 32, const VAL_LEN: usize = 32>
1617
where
17-
K: Ord + From<[u8; KEY_LEN]> + Into<[u8; KEY_LEN]>,
18-
V: Eq + From<[u8; VAL_LEN]> + Into<[u8; VAL_LEN]>,
18+
K: From<[u8; KEY_LEN]> + Into<[u8; KEY_LEN]>,
19+
V: From<[u8; VAL_LEN]> + Into<[u8; VAL_LEN]>,
1920
{
2021
path: PathBuf,
21-
cache: BTreeMap<K, IndexSet<V>>,
22+
cache: HashMap<[u8; KEY_LEN], IndexSet<[u8; VAL_LEN]>>,
23+
_phantom: PhantomData<(K, V)>,
2224
}
2325

2426
impl<K, V, const KEY_LEN: usize, const VAL_LEN: usize> FileAoraIndex<K, V, KEY_LEN, VAL_LEN>
2527
where
26-
K: Ord + From<[u8; KEY_LEN]> + Into<[u8; KEY_LEN]>,
27-
V: Eq + From<[u8; VAL_LEN]> + Into<[u8; VAL_LEN]>,
28+
K: From<[u8; KEY_LEN]> + Into<[u8; KEY_LEN]>,
29+
V: From<[u8; VAL_LEN]> + Into<[u8; VAL_LEN]>,
2830
{
2931
pub fn create(path: PathBuf) -> io::Result<Self> {
3032
File::create_new(&path)?;
31-
Ok(Self { cache: BTreeMap::new(), path })
33+
Ok(Self { cache: HashMap::new(), path, _phantom: PhantomData })
3234
}
3335

3436
pub fn open(path: PathBuf) -> io::Result<Self>
3537
where V: Hash {
36-
let mut cache = BTreeMap::new();
38+
let mut cache = HashMap::new();
3739
let mut file = File::open(&path)?;
3840
let mut key_buf = [0u8; KEY_LEN];
3941
let mut val_buf = [0u8; VAL_LEN];
4042
while file.read_exact(&mut key_buf).is_ok() {
41-
let key = K::from(key_buf);
4243
let mut values = IndexSet::new();
4344
let mut len = [0u8; 4];
4445
file.read_exact(&mut len).expect("cannot read index file");
4546
let mut len = u32::from_le_bytes(len);
4647
while len > 0 {
4748
file.read_exact(&mut val_buf)
4849
.expect("cannot read index file");
49-
let res = values.insert(val_buf.into());
50+
let res = values.insert(val_buf);
5051
debug_assert!(res, "duplicate id in index file");
5152
len -= 1;
5253
}
53-
cache.insert(key, values);
54+
cache.insert(key_buf, values);
5455
}
55-
Ok(Self { path, cache })
56+
Ok(Self { path, cache, _phantom: PhantomData })
5657
}
5758

58-
pub fn save(&self) -> io::Result<()>
59-
where
60-
K: Copy,
61-
V: Copy,
62-
{
59+
pub fn save(&self) -> io::Result<()> {
6360
let mut index_file = File::create(&self.path)?;
6461
for (key, values) in &self.cache {
65-
index_file.write_all(&(*key).into())?;
62+
index_file.write_all(key)?;
6663
let len = values.len() as u32;
6764
index_file.write_all(&len.to_le_bytes())?;
6865
for value in values {
69-
index_file.write_all(&(*value).into())?;
66+
index_file.write_all(value)?;
7067
}
7168
}
7269
Ok(())
@@ -76,24 +73,29 @@ where
7673
impl<K, V, const KEY_LEN: usize, const VAL_LEN: usize> AoraIndex<K, V, KEY_LEN, VAL_LEN>
7774
for FileAoraIndex<K, V, KEY_LEN, VAL_LEN>
7875
where
79-
K: Copy + Ord + From<[u8; KEY_LEN]> + Into<[u8; KEY_LEN]>,
80-
V: Copy + Eq + Hash + From<[u8; VAL_LEN]> + Into<[u8; VAL_LEN]>,
76+
K: From<[u8; KEY_LEN]> + Into<[u8; KEY_LEN]>,
77+
V: From<[u8; VAL_LEN]> + Into<[u8; VAL_LEN]>,
8178
{
82-
fn keys(&self) -> impl Iterator<Item = K> { self.cache.keys().copied() }
79+
fn keys(&self) -> impl Iterator<Item = K> { self.cache.keys().copied().map(K::from) }
8380

84-
fn contains_key(&self, key: &K) -> bool { self.cache.contains_key(key) }
81+
fn contains_key(&self, key: K) -> bool { self.cache.contains_key(&key.into()) }
8582

86-
fn value_len(&self, key: &K) -> usize { self.cache.get(key).map(|ids| ids.len()).unwrap_or(0) }
83+
fn value_len(&self, key: K) -> usize {
84+
self.cache
85+
.get(&key.into())
86+
.map(|ids| ids.len())
87+
.unwrap_or(0)
88+
}
8789

88-
fn get(&self, key: &K) -> impl ExactSizeIterator<Item = V> {
89-
match self.cache.get(key) {
90-
Some(ids) => ids.clone().into_iter(),
91-
None => IndexSet::new().into_iter(),
90+
fn get(&self, key: K) -> impl ExactSizeIterator<Item = V> {
91+
match self.cache.get(&key.into()) {
92+
Some(ids) => ids.clone().into_iter().map(V::from),
93+
None => IndexSet::new().into_iter().map(V::from),
9294
}
9395
}
9496

9597
fn push(&mut self, key: K, val: V) {
96-
self.cache.entry(key).or_default().insert(val);
98+
self.cache.entry(key.into()).or_default().insert(val.into());
9799
self.save().expect("Cannot save index file");
98100
}
99101
}

0 commit comments

Comments
 (0)