#![forbid(missing_docs)]
use std::cell::RefCell;
use std::cmp::Ordering;
use std::rc::Rc;
mod join;
mod map;
mod treefrog;
pub use treefrog::{
extend_anti::ExtendAnti, extend_with::ExtendWith, filter_anti::FilterAnti,
filter_with::FilterWith, Leaper, RelationLeaper,
};
#[derive(Clone)]
pub struct Relation<Tuple: Ord> {
pub elements: Vec<Tuple>,
}
impl<Tuple: Ord> Relation<Tuple> {
pub fn merge(self, other: Self) -> Self {
let mut elements1 = self.elements;
let mut elements2 = other.elements;
if elements1.is_empty() {
return Relation {
elements: elements2,
};
}
if elements2.is_empty() {
return Relation {
elements: elements1,
};
}
if elements1[0] > elements2[0] {
std::mem::swap(&mut elements1, &mut elements2);
}
if elements1[elements1.len() - 1] < elements2[0] {
elements1.extend(elements2.into_iter());
return Relation {
elements: elements1,
};
}
let mut elements = Vec::with_capacity(elements1.len() + elements2.len());
let mut elements1 = elements1.drain(..);
let mut elements2 = elements2.drain(..).peekable();
elements.push(elements1.next().unwrap());
if elements.first() == elements2.peek() {
elements2.next();
}
for elem in elements1 {
while elements2.peek().map(|x| x.cmp(&elem)) == Some(Ordering::Less) {
elements.push(elements2.next().unwrap());
}
if elements2.peek().map(|x| x.cmp(&elem)) == Some(Ordering::Equal) {
elements2.next();
}
elements.push(elem);
}
elements.extend(elements2);
Relation { elements }
}
fn from_vec(mut elements: Vec<Tuple>) -> Self {
elements.sort();
elements.dedup();
Relation { elements }
}
}
impl<Tuple: Ord, I: IntoIterator<Item = Tuple>> From<I> for Relation<Tuple> {
fn from(iterator: I) -> Self {
Relation::from_vec(iterator.into_iter().collect())
}
}
impl<Tuple: Ord> std::ops::Deref for Relation<Tuple> {
type Target = [Tuple];
fn deref(&self) -> &Self::Target {
&self.elements[..]
}
}
pub struct Iteration {
variables: Vec<Box<dyn VariableTrait>>,
}
impl Iteration {
pub fn new() -> Self {
Iteration {
variables: Vec::new(),
}
}
pub fn changed(&mut self) -> bool {
let mut result = false;
for variable in self.variables.iter_mut() {
if variable.changed() {
result = true;
}
}
result
}
pub fn variable<Tuple: Ord + 'static>(&mut self, name: &str) -> Variable<Tuple> {
let variable = Variable::new(name);
self.variables.push(Box::new(variable.clone()));
variable
}
pub fn variable_indistinct<Tuple: Ord + 'static>(&mut self, name: &str) -> Variable<Tuple> {
let mut variable = Variable::new(name);
variable.distinct = false;
self.variables.push(Box::new(variable.clone()));
variable
}
}
trait VariableTrait {
fn changed(&mut self) -> bool;
}
pub struct Variable<Tuple: Ord> {
distinct: bool,
name: String,
pub stable: Rc<RefCell<Vec<Relation<Tuple>>>>,
pub recent: Rc<RefCell<Relation<Tuple>>>,
to_add: Rc<RefCell<Vec<Relation<Tuple>>>>,
}
impl<Tuple: Ord> Variable<Tuple> {
pub fn from_join<K: Ord, V1: Ord, V2: Ord>(
&self,
input1: &Variable<(K, V1)>,
input2: &Variable<(K, V2)>,
logic: impl FnMut(&K, &V1, &V2) -> Tuple,
) {
join::join_into(input1, input2, self, logic)
}
pub fn from_antijoin<K: Ord, V: Ord>(
&self,
input1: &Variable<(K, V)>,
input2: &Relation<K>,
logic: impl FnMut(&K, &V) -> Tuple,
) {
join::antijoin_into(input1, input2, self, logic)
}
pub fn from_map<T2: Ord>(&self, input: &Variable<T2>, logic: impl FnMut(&T2) -> Tuple) {
map::map_into(input, self, logic)
}
pub fn from_leapjoin<'a, SourceTuple: Ord, Val: Ord + 'a>(
&self,
source: &Variable<SourceTuple>,
leapers: &mut [&mut dyn Leaper<'a, SourceTuple, Val>],
logic: impl FnMut(&SourceTuple, &Val) -> Tuple,
) {
treefrog::leapjoin_into(source, leapers, self, logic)
}
}
impl<Tuple: Ord> Clone for Variable<Tuple> {
fn clone(&self) -> Self {
Variable {
distinct: self.distinct,
name: self.name.clone(),
stable: self.stable.clone(),
recent: self.recent.clone(),
to_add: self.to_add.clone(),
}
}
}
impl<Tuple: Ord> Variable<Tuple> {
fn new(name: &str) -> Self {
Variable {
distinct: true,
name: name.to_string(),
stable: Rc::new(RefCell::new(Vec::new())),
recent: Rc::new(RefCell::new(Vec::new().into())),
to_add: Rc::new(RefCell::new(Vec::new())),
}
}
pub fn insert(&self, relation: Relation<Tuple>) {
if !relation.is_empty() {
self.to_add.borrow_mut().push(relation);
}
}
pub fn complete(self) -> Relation<Tuple> {
assert!(self.recent.borrow().is_empty());
assert!(self.to_add.borrow().is_empty());
let mut result: Relation<Tuple> = Vec::new().into();
while let Some(batch) = self.stable.borrow_mut().pop() {
result = result.merge(batch);
}
result
}
}
impl<Tuple: Ord> VariableTrait for Variable<Tuple> {
fn changed(&mut self) -> bool {
if !self.recent.borrow().is_empty() {
let mut recent =
::std::mem::replace(&mut (*self.recent.borrow_mut()), Vec::new().into());
while self
.stable
.borrow()
.last()
.map(|x| x.len() <= 2 * recent.len())
== Some(true)
{
let last = self.stable.borrow_mut().pop().unwrap();
recent = recent.merge(last);
}
self.stable.borrow_mut().push(recent);
}
let to_add = self.to_add.borrow_mut().pop();
if let Some(mut to_add) = to_add {
while let Some(to_add_more) = self.to_add.borrow_mut().pop() {
to_add = to_add.merge(to_add_more);
}
if self.distinct {
for batch in self.stable.borrow().iter() {
let mut slice = &batch[..];
if slice.len() > 4 * to_add.elements.len() {
to_add.elements.retain(|x| {
slice = join::gallop(slice, |y| y < x);
slice.is_empty() || &slice[0] != x
});
} else {
to_add.elements.retain(|x| {
while !slice.is_empty() && &slice[0] < x {
slice = &slice[1..];
}
slice.is_empty() || &slice[0] != x
});
}
}
}
*self.recent.borrow_mut() = to_add;
}
!self.recent.borrow().is_empty()
}
}