Usess better indexes in MemoryStore

Allows to have a lot of named graphs
pull/10/head
Tpt 5 years ago
parent 8f491e309f
commit ad4563135a
  1. 626
      lib/src/store/memory.rs

@ -1,13 +1,9 @@
use crate::store::numeric_encoder::*; use crate::store::numeric_encoder::*;
use crate::store::*; use crate::store::*;
use crate::{Repository, Result}; use crate::{Repository, Result};
use std::collections::BTreeMap; use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeSet; use std::iter::{empty, once};
use std::iter::empty; use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::iter::once;
use std::sync::RwLock;
use std::sync::RwLockReadGuard;
use std::sync::RwLockWriteGuard;
/// Memory based implementation of the `Repository` trait. /// Memory based implementation of the `Repository` trait.
/// They are cheap to build using the `MemoryRepository::default()` method. /// They are cheap to build using the `MemoryRepository::default()` method.
@ -44,18 +40,23 @@ pub struct MemoryRepository {
} }
pub type MemoryRepositoryConnection<'a> = StoreRepositoryConnection<&'a MemoryStore>; pub type MemoryRepositoryConnection<'a> = StoreRepositoryConnection<&'a MemoryStore>;
type TripleMap<T> = BTreeMap<T, BTreeMap<T, BTreeSet<T>>>;
type QuadMap<T> = BTreeMap<T, TripleMap<T>>;
#[derive(Default)] #[derive(Default)]
pub struct MemoryStore { pub struct MemoryStore {
string_store: MemoryStringStore, string_store: MemoryStringStore,
graph_indexes: RwLock<BTreeMap<EncodedTerm, MemoryGraphIndexes>>, quad_indexes: RwLock<MemoryStoreIndexes>,
} }
#[derive(Default)] #[derive(Default)]
struct MemoryGraphIndexes { struct MemoryStoreIndexes {
spo: BTreeMap<EncodedTerm, BTreeMap<EncodedTerm, BTreeSet<EncodedTerm>>>, spog: QuadMap<EncodedTerm>,
pos: BTreeMap<EncodedTerm, BTreeMap<EncodedTerm, BTreeSet<EncodedTerm>>>, posg: QuadMap<EncodedTerm>,
osp: BTreeMap<EncodedTerm, BTreeMap<EncodedTerm, BTreeSet<EncodedTerm>>>, ospg: QuadMap<EncodedTerm>,
gspo: QuadMap<EncodedTerm>,
gpos: QuadMap<EncodedTerm>,
gosp: QuadMap<EncodedTerm>,
} }
impl<'a> Repository for &'a MemoryRepository { impl<'a> Repository for &'a MemoryRepository {
@ -93,108 +94,108 @@ impl StringStore for MemoryStore {
impl<'a> StoreConnection for &'a MemoryStore { impl<'a> StoreConnection for &'a MemoryStore {
fn contains(&self, quad: &EncodedQuad) -> Result<bool> { fn contains(&self, quad: &EncodedQuad) -> Result<bool> {
Ok(self Ok(self
.graph_indexes()? .quad_indexes()?
.get(&quad.graph_name) .spog
.map_or(false, |graph| { .get(&quad.subject)
graph.spo.get(&quad.subject).map_or(false, |po| { .map_or(false, |pog| {
po.get(&quad.predicate) pog.get(&quad.predicate).map_or(false, |og| {
.map_or(false, |o| o.contains(&quad.object)) og.get(&quad.object)
.map_or(false, |g| g.contains(&quad.graph_name))
}) })
})) }))
} }
fn insert(&self, quad: &EncodedQuad) -> Result<()> { fn insert(&self, quad: &EncodedQuad) -> Result<()> {
let mut graph_indexes = self.graph_indexes_mut()?; let mut quad_indexes = self.quad_indexes_mut()?;
let graph = graph_indexes insert_into_quad_map(
.entry(quad.graph_name) &mut quad_indexes.gosp,
.or_insert_with(MemoryGraphIndexes::default); quad.graph_name,
graph quad.object,
.spo quad.subject,
.entry(quad.subject) quad.predicate,
.or_default() );
.entry(quad.predicate) insert_into_quad_map(
.or_default() &mut quad_indexes.gpos,
.insert(quad.object); quad.graph_name,
graph quad.predicate,
.pos quad.object,
.entry(quad.predicate) quad.subject,
.or_default() );
.entry(quad.object) insert_into_quad_map(
.or_default() &mut quad_indexes.gspo,
.insert(quad.subject); quad.graph_name,
graph quad.subject,
.osp quad.predicate,
.entry(quad.object) quad.object,
.or_default() );
.entry(quad.subject) insert_into_quad_map(
.or_default() &mut quad_indexes.ospg,
.insert(quad.predicate); quad.object,
quad.subject,
quad.predicate,
quad.graph_name,
);
insert_into_quad_map(
&mut quad_indexes.posg,
quad.predicate,
quad.object,
quad.subject,
quad.graph_name,
);
insert_into_quad_map(
&mut quad_indexes.spog,
quad.subject,
quad.predicate,
quad.object,
quad.graph_name,
);
Ok(()) Ok(())
} }
fn remove(&self, quad: &EncodedQuad) -> Result<()> { fn remove(&self, quad: &EncodedQuad) -> Result<()> {
let mut graph_indexes = self.graph_indexes_mut()?; let mut quad_indexes = self.quad_indexes_mut()?;
let mut empty_graph = false; remove_from_quad_map(
if let Some(graph) = graph_indexes.get_mut(&quad.graph_name) { &mut quad_indexes.gosp,
{ &quad.graph_name,
let mut empty_pos = false; &quad.object,
if let Some(pos) = graph.spo.get_mut(&quad.subject) { &quad.subject,
let mut empty_os = false; &quad.predicate,
if let Some(os) = pos.get_mut(&quad.predicate) { );
os.remove(&quad.object); remove_from_quad_map(
empty_os = os.is_empty(); &mut quad_indexes.gpos,
} &quad.graph_name,
if empty_os { &quad.predicate,
pos.remove(&quad.predicate); &quad.object,
} &quad.subject,
empty_pos = pos.is_empty(); );
} remove_from_quad_map(
if empty_pos { &mut quad_indexes.gspo,
graph.spo.remove(&quad.subject); &quad.graph_name,
} &quad.subject,
} &quad.predicate,
&quad.object,
{ );
let mut empty_oss = false; remove_from_quad_map(
if let Some(oss) = graph.pos.get_mut(&quad.predicate) { &mut quad_indexes.ospg,
let mut empty_ss = false; &quad.object,
if let Some(ss) = oss.get_mut(&quad.object) { &quad.subject,
ss.remove(&quad.subject); &quad.predicate,
empty_ss = ss.is_empty(); &quad.graph_name,
} );
if empty_ss { remove_from_quad_map(
oss.remove(&quad.object); &mut quad_indexes.posg,
} &quad.predicate,
empty_oss = oss.is_empty(); &quad.object,
} &quad.subject,
if empty_oss { &quad.graph_name,
graph.pos.remove(&quad.predicate); );
} remove_from_quad_map(
} &mut quad_indexes.spog,
&quad.subject,
{ &quad.predicate,
let mut empty_sps = false; &quad.object,
if let Some(sps) = graph.osp.get_mut(&quad.object) { &quad.graph_name,
let mut empty_ps = false; );
if let Some(ps) = sps.get_mut(&quad.subject) {
ps.remove(&quad.predicate);
empty_ps = ps.is_empty();
}
if empty_ps {
sps.remove(&quad.subject);
}
empty_sps = sps.is_empty();
}
if empty_sps {
graph.osp.remove(&quad.object);
}
}
empty_graph = graph.spo.is_empty();
}
if empty_graph {
graph_indexes.remove(&quad.graph_name);
}
Ok(()) Ok(())
} }
@ -276,65 +277,47 @@ impl<'a> StoreConnection for &'a MemoryStore {
} }
impl MemoryStore { impl MemoryStore {
fn graph_indexes( fn quad_indexes(&self) -> Result<RwLockReadGuard<'_, MemoryStoreIndexes>> {
&self, Ok(self.quad_indexes.read().map_err(MutexPoisonError::from)?)
) -> Result<RwLockReadGuard<'_, BTreeMap<EncodedTerm, MemoryGraphIndexes>>> {
Ok(self.graph_indexes.read().map_err(MutexPoisonError::from)?)
} }
fn graph_indexes_mut( fn quad_indexes_mut(&self) -> Result<RwLockWriteGuard<'_, MemoryStoreIndexes>> {
&self, Ok(self.quad_indexes.write().map_err(MutexPoisonError::from)?)
) -> Result<RwLockWriteGuard<'_, BTreeMap<EncodedTerm, MemoryGraphIndexes>>> {
Ok(self.graph_indexes.write().map_err(MutexPoisonError::from)?)
} }
fn quads(&self) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { fn quads<'a>(&'a self) -> Result<impl Iterator<Item = Result<EncodedQuad>> + 'a> {
let mut result = Vec::default(); Ok(quad_map_flatten(&self.quad_indexes()?.gspo)
for (graph_name, graph) in self.graph_indexes()?.iter() { .map(|(g, s, p, o)| Ok(EncodedQuad::new(s, p, o, g)))
for (s, pos) in &graph.spo { .collect::<Vec<_>>()
for (p, os) in pos.iter() { .into_iter())
for o in os.iter() {
result.push(Ok(EncodedQuad::new(*s, *p, *o, *graph_name)))
}
}
}
}
Ok(result.into_iter())
} }
fn quads_for_subject( fn quads_for_subject(
&self, &self,
subject: EncodedTerm, subject: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(
for (graph_name, graph) in self.graph_indexes()?.iter() { option_triple_map_flatten(self.quad_indexes()?.spog.get(&subject))
if let Some(pos) = graph.spo.get(&subject) { .map(|(p, o, g)| Ok(EncodedQuad::new(subject, p, o, g)))
for (p, os) in pos.iter() { .collect::<Vec<_>>()
for o in os.iter() { .into_iter(),
result.push(Ok(EncodedQuad::new(subject, *p, *o, *graph_name))) )
}
}
}
}
Ok(result.into_iter())
} }
fn quads_for_subject_predicate( fn quads_for_subject_predicate(
&self, &self,
subject: EncodedTerm, subject: EncodedTerm,
predicate: EncodedTerm, predicate: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(option_pair_map_flatten(
for (graph_name, graph) in self.graph_indexes()?.iter() { self.quad_indexes()?
if let Some(pos) = graph.spo.get(&subject) { .spog
if let Some(os) = pos.get(&predicate) { .get(&subject)
for o in os.iter() { .and_then(|pog| pog.get(&predicate)),
result.push(Ok(EncodedQuad::new(subject, predicate, *o, *graph_name))) )
} .map(|(o, g)| Ok(EncodedQuad::new(subject, predicate, o, g)))
} .collect::<Vec<_>>()
} .into_iter())
}
Ok(result.into_iter())
} }
fn quads_for_subject_predicate_object( fn quads_for_subject_predicate_object(
@ -342,128 +325,101 @@ impl MemoryStore {
subject: EncodedTerm, subject: EncodedTerm,
predicate: EncodedTerm, predicate: EncodedTerm,
object: EncodedTerm, object: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(option_set_flatten(
for (graph_name, graph) in self.graph_indexes()?.iter() { self.quad_indexes()?
if let Some(pos) = graph.spo.get(&subject) { .spog
if let Some(os) = pos.get(&predicate) { .get(&subject)
if os.contains(&object) { .and_then(|pog| pog.get(&predicate))
result.push(Ok(EncodedQuad::new( .and_then(|og| og.get(&object)),
subject, )
predicate, .map(|g| Ok(EncodedQuad::new(subject, predicate, object, g)))
object, .collect::<Vec<_>>()
*graph_name, .into_iter())
)))
}
}
}
}
Ok(result.into_iter())
} }
fn quads_for_subject_object( fn quads_for_subject_object(
&self, &self,
subject: EncodedTerm, subject: EncodedTerm,
object: EncodedTerm, object: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(option_pair_map_flatten(
for (graph_name, graph) in self.graph_indexes()?.iter() { self.quad_indexes()?
if let Some(sps) = graph.osp.get(&object) { .ospg
if let Some(ps) = sps.get(&subject) { .get(&object)
for p in ps.iter() { .and_then(|spg| spg.get(&subject)),
result.push(Ok(EncodedQuad::new(subject, *p, object, *graph_name))) )
} .map(|(p, g)| Ok(EncodedQuad::new(subject, p, object, g)))
} .collect::<Vec<_>>()
} .into_iter())
}
Ok(result.into_iter())
} }
fn quads_for_predicate( fn quads_for_predicate(
&self, &self,
predicate: EncodedTerm, predicate: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(
for (graph_name, graph) in self.graph_indexes()?.iter() { option_triple_map_flatten(self.quad_indexes()?.posg.get(&predicate))
if let Some(oss) = graph.pos.get(&predicate) { .map(|(o, s, g)| Ok(EncodedQuad::new(s, predicate, o, g)))
for (o, ss) in oss.iter() { .collect::<Vec<_>>()
for s in ss.iter() { .into_iter(),
result.push(Ok(EncodedQuad::new(*s, predicate, *o, *graph_name))) )
}
}
}
}
Ok(result.into_iter())
} }
fn quads_for_predicate_object( fn quads_for_predicate_object(
&self, &self,
predicate: EncodedTerm, predicate: EncodedTerm,
object: EncodedTerm, object: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(option_pair_map_flatten(
for (graph_name, graph) in self.graph_indexes()?.iter() { self.quad_indexes()?
if let Some(oss) = graph.pos.get(&predicate) { .posg
if let Some(ss) = oss.get(&object) { .get(&predicate)
for s in ss.iter() { .and_then(|osg| osg.get(&object)),
result.push(Ok(EncodedQuad::new(*s, predicate, object, *graph_name))) )
} .map(|(s, g)| Ok(EncodedQuad::new(s, predicate, object, g)))
} .collect::<Vec<_>>()
} .into_iter())
}
Ok(result.into_iter())
} }
fn quads_for_object( fn quads_for_object(
&self, &self,
object: EncodedTerm, object: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(
for (graph_name, graph) in self.graph_indexes()?.iter() { option_triple_map_flatten(self.quad_indexes()?.ospg.get(&object))
if let Some(sps) = graph.osp.get(&object) { .map(|(s, p, g)| Ok(EncodedQuad::new(s, p, object, g)))
for (s, ps) in sps.iter() { .collect::<Vec<_>>()
for p in ps.iter() { .into_iter(),
result.push(Ok(EncodedQuad::new(*s, *p, object, *graph_name))) )
}
}
}
}
Ok(result.into_iter())
} }
fn quads_for_graph( fn quads_for_graph(
&self, &self,
graph_name: EncodedTerm, graph_name: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(
if let Some(graph) = self.graph_indexes()?.get(&graph_name) { option_triple_map_flatten(self.quad_indexes()?.gspo.get(&graph_name))
for (s, pos) in &graph.spo { .map(|(s, p, o)| Ok(EncodedQuad::new(s, p, o, graph_name)))
for (p, os) in pos.iter() { .collect::<Vec<_>>()
for o in os.iter() { .into_iter(),
result.push(Ok(EncodedQuad::new(*s, *p, *o, graph_name))) )
}
}
}
}
Ok(result.into_iter())
} }
fn quads_for_subject_graph( fn quads_for_subject_graph(
&self, &self,
subject: EncodedTerm, subject: EncodedTerm,
graph_name: EncodedTerm, graph_name: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(option_pair_map_flatten(
if let Some(graph) = self.graph_indexes()?.get(&graph_name) { self.quad_indexes()?
if let Some(pos) = graph.spo.get(&subject) { .gspo
for (p, os) in pos.iter() { .get(&graph_name)
for o in os.iter() { .and_then(|spo| spo.get(&subject)),
result.push(Ok(EncodedQuad::new(subject, *p, *o, graph_name))) )
} .map(|(p, o)| Ok(EncodedQuad::new(subject, p, o, graph_name)))
} .collect::<Vec<_>>()
} .into_iter())
}
Ok(result.into_iter())
} }
fn quads_for_subject_predicate_graph( fn quads_for_subject_predicate_graph(
@ -471,18 +427,17 @@ impl MemoryStore {
subject: EncodedTerm, subject: EncodedTerm,
predicate: EncodedTerm, predicate: EncodedTerm,
graph_name: EncodedTerm, graph_name: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(option_set_flatten(
if let Some(graph) = self.graph_indexes()?.get(&graph_name) { self.quad_indexes()?
if let Some(pos) = graph.spo.get(&subject) { .gspo
if let Some(os) = pos.get(&predicate) { .get(&graph_name)
for o in os.iter() { .and_then(|spo| spo.get(&subject))
result.push(Ok(EncodedQuad::new(subject, predicate, *o, graph_name))) .and_then(|po| po.get(&predicate)),
} )
} .map(|o| Ok(EncodedQuad::new(subject, predicate, o, graph_name)))
} .collect::<Vec<_>>()
} .into_iter())
Ok(result.into_iter())
} }
fn quads_for_subject_object_graph( fn quads_for_subject_object_graph(
@ -490,36 +445,33 @@ impl MemoryStore {
subject: EncodedTerm, subject: EncodedTerm,
object: EncodedTerm, object: EncodedTerm,
graph_name: EncodedTerm, graph_name: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(option_set_flatten(
if let Some(graph) = self.graph_indexes()?.get(&graph_name) { self.quad_indexes()?
if let Some(sps) = graph.osp.get(&object) { .gosp
if let Some(ps) = sps.get(&subject) { .get(&graph_name)
for p in ps.iter() { .and_then(|osp| osp.get(&object))
result.push(Ok(EncodedQuad::new(subject, *p, object, graph_name))) .and_then(|sp| sp.get(&subject)),
} )
} .map(|p| Ok(EncodedQuad::new(subject, p, object, graph_name)))
} .collect::<Vec<_>>()
} .into_iter())
Ok(result.into_iter())
} }
fn quads_for_predicate_graph( fn quads_for_predicate_graph(
&self, &self,
predicate: EncodedTerm, predicate: EncodedTerm,
graph_name: EncodedTerm, graph_name: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(option_pair_map_flatten(
if let Some(graph) = self.graph_indexes()?.get(&graph_name) { self.quad_indexes()?
if let Some(oss) = graph.pos.get(&predicate) { .gpos
for (o, ss) in oss.iter() { .get(&graph_name)
for s in ss.iter() { .and_then(|pos| pos.get(&predicate)),
result.push(Ok(EncodedQuad::new(*s, predicate, *o, graph_name))) )
} .map(|(o, s)| Ok(EncodedQuad::new(s, predicate, o, graph_name)))
} .collect::<Vec<_>>()
} .into_iter())
}
Ok(result.into_iter())
} }
fn quads_for_predicate_object_graph( fn quads_for_predicate_object_graph(
@ -527,44 +479,118 @@ impl MemoryStore {
predicate: EncodedTerm, predicate: EncodedTerm,
object: EncodedTerm, object: EncodedTerm,
graph_name: EncodedTerm, graph_name: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(option_set_flatten(
if let Some(graph) = self.graph_indexes()?.get(&graph_name) { self.quad_indexes()?
if let Some(oss) = graph.pos.get(&predicate) { .gpos
if let Some(ss) = oss.get(&object) { .get(&graph_name)
for s in ss.iter() { .and_then(|pos| pos.get(&predicate))
result.push(Ok(EncodedQuad::new(*s, predicate, object, graph_name))) .and_then(|os| os.get(&object)),
} )
} .map(|s| Ok(EncodedQuad::new(s, predicate, object, graph_name)))
} .collect::<Vec<_>>()
} .into_iter())
Ok(result.into_iter())
} }
fn quads_for_object_graph( fn quads_for_object_graph(
&self, &self,
object: EncodedTerm, object: EncodedTerm,
graph_name: EncodedTerm, graph_name: EncodedTerm,
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> { ) -> Result<impl Iterator<Item = Result<EncodedQuad>>> {
let mut result = Vec::default(); Ok(option_pair_map_flatten(
if let Some(graph) = self.graph_indexes()?.get(&graph_name) { self.quad_indexes()?
if let Some(sps) = graph.osp.get(&object) { .gosp
for (s, ps) in sps.iter() { .get(&graph_name)
for p in ps.iter() { .and_then(|osp| osp.get(&object)),
result.push(Ok(EncodedQuad::new(*s, *p, object, graph_name))) )
} .map(|(s, p)| Ok(EncodedQuad::new(s, p, object, graph_name)))
} .collect::<Vec<_>>()
} .into_iter())
}
Ok(result.into_iter())
} }
} }
fn wrap_error<E: 'static, I: Iterator<Item = Result<E>> + 'static>( fn wrap_error<'a, E: 'static, I: Iterator<Item = Result<E>> + 'a>(
iter: Result<I>, iter: Result<I>,
) -> Box<dyn Iterator<Item = Result<E>>> { ) -> Box<dyn Iterator<Item = Result<E>> + 'a> {
match iter { match iter {
Ok(iter) => Box::new(iter), Ok(iter) => Box::new(iter),
Err(error) => Box::new(once(Err(error))), Err(error) => Box::new(once(Err(error))),
} }
} }
fn insert_into_quad_map<T: Ord>(map: &mut QuadMap<T>, e1: T, e2: T, e3: T, e4: T) {
map.entry(e1)
.or_default()
.entry(e2)
.or_default()
.entry(e3)
.or_default()
.insert(e4);
}
fn remove_from_quad_map<T: Ord>(map1: &mut QuadMap<T>, e1: &T, e2: &T, e3: &T, e4: &T) {
let mut map2empty = false;
if let Some(map2) = map1.get_mut(e1) {
let mut map3empty = false;
if let Some(map3) = map2.get_mut(e2) {
let mut set4empty = false;
if let Some(set4) = map3.get_mut(e3) {
set4.remove(e4);
set4empty = set4.is_empty();
}
if set4empty {
map3.remove(e3);
}
map3empty = map3.is_empty();
}
if map3empty {
map2.remove(e2);
}
map2empty = map2.is_empty();
}
if map2empty {
map1.remove(e1);
}
}
fn option_set_flatten<'a, T: Clone>(i: Option<&'a BTreeSet<T>>) -> impl Iterator<Item = T> + 'a {
i.into_iter().flat_map(|s| s.iter().cloned())
}
fn option_pair_map_flatten<'a, T: Copy>(
i: Option<&'a BTreeMap<T, BTreeSet<T>>>,
) -> impl Iterator<Item = (T, T)> + 'a {
i.into_iter().flat_map(|kv| {
kv.iter().flat_map(|(k, vs)| {
let k = *k;
vs.iter().map(move |v| (k, *v))
})
})
}
fn option_triple_map_flatten<'a, T: Copy>(
i: Option<&'a TripleMap<T>>,
) -> impl Iterator<Item = (T, T, T)> + 'a {
i.into_iter().flat_map(|spo| {
spo.iter().flat_map(|(s, po)| {
let s = *s;
po.iter().flat_map(move |(p, os)| {
let p = *p;
os.iter().map(move |o| (s, p, *o))
})
})
})
}
fn quad_map_flatten<'a, T: Copy>(gspo: &'a QuadMap<T>) -> impl Iterator<Item = (T, T, T, T)> + 'a {
gspo.iter().flat_map(|(g, spo)| {
let g = *g;
spo.iter().flat_map(move |(s, po)| {
let s = *s;
po.iter().flat_map(move |(p, os)| {
let p = *p;
os.iter().map(move |o| (g, s, p, *o))
})
})
})
}

Loading…
Cancel
Save