#![forbid(missing_docs)]
use std::cell::RefCell;
use std::cmp::Ordering;
use std::iter::FromIterator;
use std::rc::Rc;
mod join;
mod map;
mod test;
mod treefrog;
pub use crate::join::JoinInput;
pub use crate::treefrog::{
extend_anti::ExtendAnti,
extend_with::ExtendWith,
filter_anti::FilterAnti,
filter_with::FilterWith,
filters::{PrefixFilter, ValueFilter},
Leaper, Leapers, 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 Relation {
elements: mut elements1,
} = self;
let Relation {
elements: mut elements2,
} = other;
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 }
}
pub fn from_iter<I>(iterator: I) -> Self
where
I: IntoIterator<Item = Tuple>,
{
iterator.into_iter().collect()
}
pub fn from_leapjoin<'leap, SourceTuple: Ord, Val: Ord + 'leap>(
source: &Relation<SourceTuple>,
leapers: impl Leapers<'leap, SourceTuple, Val>,
logic: impl FnMut(&SourceTuple, &Val) -> Tuple,
) -> Self {
treefrog::leapjoin(&source.elements, leapers, logic)
}
pub fn from_join<Key: Ord, Val1: Ord, Val2: Ord>(
input1: &Relation<(Key, Val1)>,
input2: &Relation<(Key, Val2)>,
logic: impl FnMut(&Key, &Val1, &Val2) -> Tuple,
) -> Self {
join::join_into_relation(input1, input2, logic)
}
pub fn from_antijoin<Key: Ord, Val1: Ord>(
input1: &Relation<(Key, Val1)>,
input2: &Relation<Key>,
logic: impl FnMut(&Key, &Val1) -> Tuple,
) -> Self {
join::antijoin(input1, input2, logic)
}
pub fn from_map<T2: Ord>(input: &Relation<T2>, logic: impl FnMut(&T2) -> Tuple) -> Self {
input.iter().map(logic).collect()
}
pub fn from_vec(mut elements: Vec<Tuple>) -> Self {
elements.sort();
elements.dedup();
Relation { elements }
}
}
impl<Tuple: Ord> From<Vec<Tuple>> for Relation<Tuple> {
fn from(iterator: Vec<Tuple>) -> Self {
Self::from_vec(iterator)
}
}
impl<Tuple: Ord> FromIterator<Tuple> for Relation<Tuple> {
fn from_iter<I>(iterator: I) -> Self
where
I: IntoIterator<Item = Tuple>,
{
Relation::from_vec(iterator.into_iter().collect())
}
}
impl<'tuple, Tuple: 'tuple + Copy + Ord> FromIterator<&'tuple Tuple> for Relation<Tuple> {
fn from_iter<I>(iterator: I) -> Self
where
I: IntoIterator<Item = &'tuple Tuple>,
{
Relation::from_vec(iterator.into_iter().cloned().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<'me, K: Ord, V1: Ord, V2: Ord>(
&self,
input1: &'me Variable<(K, V1)>,
input2: impl JoinInput<'me, (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,
) {
self.insert(join::antijoin(input1, input2, 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<'leap, SourceTuple: Ord, Val: Ord + 'leap>(
&self,
source: &Variable<SourceTuple>,
leapers: impl Leapers<'leap, SourceTuple, Val>,
logic: impl FnMut(&SourceTuple, &Val) -> Tuple,
) {
self.insert(treefrog::leapjoin(&source.recent.borrow(), leapers, 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 extend<T>(&self, iterator: impl IntoIterator<Item = T>)
where
Relation<Tuple>: FromIterator<T>,
{
self.insert(iterator.into_iter().collect());
}
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()
}
}