Initial commit
This commit is contained in:
26
Cargo.toml
Normal file
26
Cargo.toml
Normal file
@@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "ironsea_index_hashmap"
|
||||
version = "0.1.0"
|
||||
authors = ["EPFL-DIAS", "Lionel Sambuc <lionel.sambuc@epfl.ch>"]
|
||||
|
||||
edition = "2018"
|
||||
|
||||
description = "Simple `HashMap`-based index implementation for the Iron Sea database toolkit."
|
||||
homepage = "https://crates.io/crates/ironsea_index_hashmap"
|
||||
repository = "https://github.com/epfl-dias/ironsea_index_hashmap"
|
||||
readme = "README.md"
|
||||
|
||||
keywords = []
|
||||
categories = ["database-implementations", "data-structures"]
|
||||
|
||||
license = "MIT"
|
||||
#license-file = "LICENSE"
|
||||
|
||||
include = ["Cargo.toml", "README.md", "LICENSE", "ACKNOWLEDGEMENTS", "src/**/*.rs"]
|
||||
|
||||
[dependencies]
|
||||
ironsea_index = "^0.1"
|
||||
ironsea_table = "^0.1"
|
||||
|
||||
serde = "^1.0"
|
||||
serde_derive = "^1.0"
|
||||
32
README.md
Normal file
32
README.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Iron Sea - Index Hash Map
|
||||
|
||||
A simple hash map index for the Iron Sea toolkit.
|
||||
|
||||
## Iron Sea: Database Toolkit
|
||||
|
||||
**Iron Sea** provides a set of database engine bricks, which can be combined and applied on arbitrary data structures.
|
||||
|
||||
Unlike a traditional database, it does not assume a specific physical structure for the tables nor the records, but relies on the developper to provide a set of extractor functions which are used by the specific indices provided.
|
||||
|
||||
This enables the index implementations to be agnostic from the underlying data structure, and re-used.
|
||||
|
||||
### Software
|
||||
|
||||
* Rust: https://www.rust-lang.org
|
||||
|
||||
## Documentation
|
||||
|
||||
For more information, please refer to the [documentation](https://epfl-dias.github.io/ironsea_index_hashmap/).
|
||||
|
||||
If you want to build the documentation and access it locally, you can use:
|
||||
|
||||
```sh
|
||||
cargo doc --open
|
||||
```
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
This open source software code was developed in part or in whole in the
|
||||
Human Brain Project, funded from the European Union’s Horizon 2020
|
||||
Framework Programme for Research and Innovation under the Specific Grant
|
||||
Agreement No. 785907 (Human Brain Project SGA2).
|
||||
102
src/borrowed.rs
Normal file
102
src/borrowed.rs
Normal file
@@ -0,0 +1,102 @@
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use std::marker;
|
||||
|
||||
use ironsea_index::Indexed;
|
||||
use ironsea_index::Record;
|
||||
use ironsea_table::Table;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Index<T, R, K>
|
||||
where
|
||||
T: Table<R>,
|
||||
R: Record<K>,
|
||||
K: Hash + Eq + PartialEq + Ord,
|
||||
{
|
||||
table: HashMap<K, R>,
|
||||
keys: Vec<K>,
|
||||
_marker: marker::PhantomData<(T)>,
|
||||
}
|
||||
|
||||
impl<T, R, K> Index<T, R, K>
|
||||
where
|
||||
T: Table<R>,
|
||||
R: Clone + Record<K>,
|
||||
K: Hash + Eq + PartialEq + Ord,
|
||||
{
|
||||
pub fn new(table: T) -> Self {
|
||||
let size = table.get_table().len();
|
||||
let mut ht = HashMap::with_capacity(size);
|
||||
let mut keys = Vec::with_capacity(size);
|
||||
|
||||
for r in table.get_table() {
|
||||
keys.push(r.key());
|
||||
ht.insert(r.key(), r.clone());
|
||||
}
|
||||
|
||||
keys.sort_unstable();
|
||||
keys.dedup();
|
||||
|
||||
Index {
|
||||
table: ht,
|
||||
keys,
|
||||
_marker: marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn keys(&self) -> &Vec<K> {
|
||||
&self.keys
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, R, K> Indexed<T, R, K> for Index<T, R, K>
|
||||
where
|
||||
T: Table<R>,
|
||||
R: Record<K>,
|
||||
K: Hash + Eq + PartialEq + Ord,
|
||||
{
|
||||
fn find(&self, key: &K) -> Vec<&R> {
|
||||
let mut values = vec![];
|
||||
|
||||
if let Some(record) = self.table.get(key) {
|
||||
values.push(record);
|
||||
}
|
||||
|
||||
values
|
||||
}
|
||||
|
||||
fn find_range(&self, start: &K, end: &K) -> Vec<&R> {
|
||||
let start = match self.keys.binary_search(start) {
|
||||
Ok(i) => i,
|
||||
Err(i) => {
|
||||
if i >= self.keys.len() {
|
||||
self.keys.len() - 1
|
||||
} else {
|
||||
i
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let end = match self.keys.binary_search(end) {
|
||||
Ok(i) => i,
|
||||
Err(i) => {
|
||||
if i >= self.keys.len() {
|
||||
self.keys.len() - 1
|
||||
} else {
|
||||
i
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut values = vec![];
|
||||
|
||||
for i in start..end {
|
||||
let key = &self.keys[i];
|
||||
if let Some(record) = self.table.get(key) {
|
||||
values.push(record);
|
||||
}
|
||||
}
|
||||
|
||||
values
|
||||
}
|
||||
}
|
||||
10
src/lib.rs
Normal file
10
src/lib.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
mod borrowed;
|
||||
mod owned;
|
||||
|
||||
pub use ironsea_table::Table;
|
||||
|
||||
pub use borrowed::Index;
|
||||
pub use owned::IndexOwned;
|
||||
104
src/owned.rs
Normal file
104
src/owned.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use std::marker;
|
||||
|
||||
use ironsea_index::IndexedOwned;
|
||||
use ironsea_index::Record;
|
||||
use ironsea_index::RecordBuild;
|
||||
use ironsea_index::RecordFields;
|
||||
use ironsea_table::Table;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct IndexOwned<T, R, K, F>
|
||||
where
|
||||
T: Table<R>,
|
||||
R: Record<K> + RecordFields<F> + RecordBuild<K, F, R>,
|
||||
K: Hash + Eq + PartialEq + Ord,
|
||||
{
|
||||
table: HashMap<K, F>,
|
||||
keys: Vec<K>,
|
||||
_marker: marker::PhantomData<(T, R)>,
|
||||
}
|
||||
|
||||
impl<T, R, K, F> IndexOwned<T, R, K, F>
|
||||
where
|
||||
T: Table<R>,
|
||||
R: Record<K> + RecordFields<F> + RecordBuild<K, F, R>,
|
||||
K: Hash + Eq + PartialEq + Ord,
|
||||
{
|
||||
pub fn new(table: T) -> Self {
|
||||
let size = table.get_table().len();
|
||||
let mut ht = HashMap::with_capacity(size);
|
||||
let mut keys = Vec::with_capacity(size);
|
||||
|
||||
for r in table.get_table() {
|
||||
ht.insert(r.key(), r.fields());
|
||||
keys.push(r.key());
|
||||
}
|
||||
|
||||
keys.sort_unstable();
|
||||
keys.dedup();
|
||||
|
||||
IndexOwned {
|
||||
table: ht,
|
||||
keys,
|
||||
_marker: marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn keys(&self) -> &Vec<K> {
|
||||
&self.keys
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, R, K, F> IndexedOwned<T, R, K> for IndexOwned<T, R, K, F>
|
||||
where
|
||||
T: Table<R>,
|
||||
R: Record<K> + RecordFields<F> + RecordBuild<K, F, R>,
|
||||
K: Hash + Eq + PartialEq + Ord,
|
||||
{
|
||||
fn find(&self, key: &K) -> Vec<R> {
|
||||
let mut values = vec![];
|
||||
|
||||
if let Some(fields) = self.table.get(key) {
|
||||
values.push(R::build(key, fields));
|
||||
}
|
||||
|
||||
values
|
||||
}
|
||||
|
||||
fn find_range(&self, start: &K, end: &K) -> Vec<R> {
|
||||
let start = match self.keys.binary_search(start) {
|
||||
Ok(i) => i,
|
||||
Err(i) => {
|
||||
if i >= self.keys.len() {
|
||||
self.keys.len() - 1
|
||||
} else {
|
||||
i
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let end = match self.keys.binary_search(end) {
|
||||
Ok(i) => i,
|
||||
Err(i) => {
|
||||
if i >= self.keys.len() {
|
||||
self.keys.len() - 1
|
||||
} else {
|
||||
i
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut values = vec![];
|
||||
|
||||
for i in start..end {
|
||||
let key = &self.keys[i];
|
||||
if let Some(record) = self.table.get(key) {
|
||||
values.push(R::build(key, record));
|
||||
}
|
||||
}
|
||||
|
||||
values
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user