Skip to content

Instantly share code, notes, and snippets.

@SaulDoesCode
Created June 30, 2023 12:32
Show Gist options
  • Save SaulDoesCode/bbee19533f5035fc3698b1d637a82618 to your computer and use it in GitHub Desktop.
Save SaulDoesCode/bbee19533f5035fc3698b1d637a82618 to your computer and use it in GitHub Desktop.
an alias tree using redb
use std::{collections::HashMap, sync::{Arc}};
use rand::{thread_rng, distributions::Alphanumeric, Rng};
use redb::{Database, MultimapTableDefinition, ReadableMultimapTable};
lazy_static! {
static ref DB: Database = {
let db = Database::create("./alias_tree.db").expect("Failed to open database.");
db
};
}
type Astr = Arc<str>;
const SV_MONIKER_TANGLE_LOOKUP: MultimapTableDefinition<&str, u64> = MultimapTableDefinition::new("name_lookup");
const SV_MONIKER_TANGLE_LOOKUP_REVERSE: MultimapTableDefinition<u64, &str> = MultimapTableDefinition::new("name_lookup_reverse");
struct AliasTree{
root: Astr,
id: u64,
degree: usize,
nested: bool,
children: HashMap<Astr, AliasTree>
}
impl AliasTree{
fn new(root: Astr, id: Option<u64>, degree: usize, nested: bool) -> anyhow::Result<AliasTree> {
let at = AliasTree{
root,
id: match id {
Some(id) => id,
None => {
let mut rng = rand::thread_rng();
let mut id = rng.gen();
let rtx = DB.begin_read()?;
let t = rtx.open_multimap_table(SV_MONIKER_TANGLE_LOOKUP_REVERSE)?;
let mut mmv = t.get(id)?;
while let Some(Ok(_)) = mmv.next() {
id = rng.gen();
mmv = t.get(id)?;
}
id
}
},
degree,
nested,
children: HashMap::new()
};
at.save()?;
Ok(at)
}
fn aliases(&self) -> Vec<Astr>{
let mut aliases = vec![];
for (_, child) in self.children.iter() {
aliases.append(&mut child.aliases());
}
aliases
}
fn save(&self) -> anyhow::Result<()> {
let wrtx = DB.begin_write()?;
{
let mut t = wrtx.open_multimap_table(SV_MONIKER_TANGLE_LOOKUP)?;
t.insert(self.root.as_ref(), self.id)?;
let mut t = wrtx.open_multimap_table(SV_MONIKER_TANGLE_LOOKUP_REVERSE)?;
t.insert(self.id, self.root.as_ref())?;
}
wrtx.commit()?;
Ok(())
}
fn get_id(moniker: &str) -> anyhow::Result<u64> {
let rtx = DB.begin_read()?;
let ft = rtx.open_multimap_table(SV_MONIKER_TANGLE_LOOKUP)?;
let mut mmv = ft.get(moniker)?;
while let Some(Ok(ag)) = mmv.next() {
return Ok(ag.value());
}
Err(anyhow!("No id found for moniker: {}", moniker))
}
fn lookup_aliases(moniker: &str, id: Option<u64>, degrees: usize) -> anyhow::Result<Self> {
let rtx = DB.begin_read()?;
let ft = rtx.open_multimap_table(SV_MONIKER_TANGLE_LOOKUP)?;
let mut mmv = ft.get(moniker)?;
let mut aliases = vec![];
while let Some(Ok(ag)) = mmv.next() {
aliases.push(ag.value());
}
let rt = rtx.open_multimap_table(SV_MONIKER_TANGLE_LOOKUP_REVERSE)?;
let mut alias_monikers: Astrs = vec![];
for a in aliases.iter() {
let mut mmv = rt.get(*a)?;
while let Some(Ok(ag)) = mmv.next() {
alias_monikers.push(Arc::from(ag.value()));
}
}
if alias_monikers.len() == 0 {
Err(anyhow::anyhow!("moniker not found"))
} else {
if degrees != 0 {
let mut alias_results = vec![];
for a in alias_monikers {
alias_results.push(Self::lookup_aliases(
a.as_ref(),
match Self::get_id(a.as_ref()) {
Ok(id) => Some(id),
Err(_) => None
},
degrees - 1
)?);
}
}
Self::new(
Arc::from(moniker),
match id {
Some(id) => Some(id),
None => Some(aliases[0])
},
degrees,
degrees != 0
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy