<commit_before>#[derive(PartialEq, Debug)]
pub enum Error {
    StackUnderflow,
}

pub struct Stack<T>
where
    T: Copy,
{
    pub values: Vec<T>,
    pub register: Option<T>,
}

impl<T> Default for Stack<T>
where
    T: Copy,
{
    fn default() -> Self {
        Self::new()
    }
}

impl<T> Stack<T>
where
    T: Copy,
{
    pub fn new() -> Self {
        Stack {
            values: Vec::new(),
            register: None,
        }
    }

    pub fn len(&self) -> usize {
        self.values.len()
    }

    pub fn is_empty(&self) -> bool {
        self.values.is_empty()
    }

    pub fn push(&mut self, val: T) {
        self.values.push(val);
    }

    pub fn pop(&mut self) -> Option<T> {
        self.values.pop()
    }

    pub fn switch_register(&mut self) -> Result<(), Error> {
        match self.register.take() {
            Some(val) => self.push(val),
            None => self.register = Some(self.pop().ok_or(Error::StackUnderflow)?),
        }

        Ok(())
    }

    pub fn dup(&mut self) -> Result<(), Error> {
        match self.values.len() {
            0 => Err(Error::StackUnderflow),
            n => {
                let v = self.values[n - 1];
                self.values.push(v);
                Ok(())
            }
        }
    }

    pub fn drop(&mut self) -> Result<(), Error> {
        match self.values.len() {
            0 => Err(Error::StackUnderflow),
            n => {
                self.values.truncate(n - 1);
                Ok(())
            }
        }
    }

    pub fn swap(&mut self) -> Result<(), Error> {
        match self.values.len() {
            n if n >= 2 => {
                let x = self.values[n - 1];
                let y = self.values[n - 2];
                self.values[n - 2] = x;
                self.values[n - 1] = y;
                Ok(())
            }
            _ => Err(Error::StackUnderflow),
        }
    }

    pub fn swap2(&mut self) -> Result<(), Error> {
        match self.values.len() {
            n if n >= 3 => {
                let x = self.values[n - 3];
                let y = self.values[n - 2];
                let z = self.values[n - 1];
                self.values[n - 3] = z;
                self.values[n - 2] = x;
                self.values[n - 1] = y;
                Ok(())
            }
            _ => Err(Error::StackUnderflow),
        }
    }

    pub fn rshift(&mut self) {
        match self.values.len() {
            0 | 1 => {}
            n => {
                let mut v: Vec<_> = self.values.drain(0..n - 1).collect();
                self.values.append(&mut v);
            }
        }
    }

    pub fn lshift(&mut self) {
        match self.values.len() {
            0 | 1 => {}
            _ => {
                let v = self.values.remove(0);
                self.values.push(v);
            }
        }
    }
}

pub struct StackOfStacks<T>
where
    T: Copy,
{
    pub initial_stack: Stack<T>,
    pub additional_stacks: Vec<Stack<T>>,
}

impl<T> Default for StackOfStacks<T>
where
    T: Copy,
{
    fn default() -> Self {
        Self::new()
    }
}

impl<T> StackOfStacks<T>
where
    T: Copy,
{
    pub fn new() -> Self {
        StackOfStacks {
            initial_stack: Stack::<T>::new(),
            additional_stacks: vec![],
        }
    }

    pub fn push_stack(&mut self, moved_items: usize) -> Result<(), Error> {
        let vals = {
            let stack = self.top();
            let n = stack
                .len()
                .checked_sub(moved_items)
                .ok_or(Error::StackUnderflow)?;
            stack.values.split_off(n)
        };

        self.additional_stacks.push(Stack::<T> {
            values: vals,
            register: None,
        });

        Ok(())
    }

    pub fn pop_stack(&mut self) {
        if let Some(stack) = self.additional_stacks.pop() {
            self.top().values.extend(stack.values);
        } else {
            self.initial_stack.values.clear();
            self.initial_stack.register = None;
        }
    }

    pub fn top(&mut self) -> &mut Stack<T> {
        self.additional_stacks
            .last_mut()
            .unwrap_or(&mut self.initial_stack)
    }
}

#[cfg(test)]
mod tests {
    mod stack {
        use super::super::*;

        #[test]
        fn new_works() {
            let stack = Stack::<isize>::new();

            assert!(stack.is_empty());
            assert_eq!(stack.register, None);
        }

        #[test]
        fn push_works() {
            let mut stack = Stack::new();
            stack.push(5);
            stack.push(42);
            stack.push(58);

            assert_eq!(stack.len(), 3);
            assert_eq!(stack.values, vec![5, 42, 58]);
        }

        #[test]
        fn pop_works() {
            let mut stack = Stack::<isize>::new();
            stack.push(5);

            assert_eq!(stack.pop(), Some(5));
        }

        #[test]
        fn pop_empty_stack_returns_none() {
            let mut stack = Stack::<isize>::new();
            assert_eq!(stack.pop(), None);
        }

        #[test]
        fn dup_works() {
            let mut stack = Stack::new();
            stack.push(5);
            stack.push(42);

            let res = stack.dup();

            assert!(res.is_ok());
            assert_eq!(stack.values, vec![5, 42, 42]);
        }

        #[test]
        fn dup_with_empty_stack_fails() {
            let mut stack = Stack::<isize>::new();

            let res = stack.dup();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn drop_works() {
            let mut stack = Stack::new();
            stack.push(5);
            stack.push(42);

            let res = stack.drop();

            assert!(res.is_ok());
            assert_eq!(stack.values, vec![5]);
        }

        #[test]
        fn drop_with_empty_stack_fails() {
            let mut stack = Stack::<isize>::new();

            let res = stack.drop();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn switch_register_works() {
            let mut stack = Stack::new();
            stack.push(5);
            stack.push(42);
            stack.push(58);

            let res = stack.switch_register();

            assert!(res.is_ok());
            assert_eq!(stack.register, Some(58));
            assert_eq!(stack.values, vec![5, 42]);

            let res2 = stack.switch_register();

            assert!(res2.is_ok());
            assert_eq!(stack.register, None);
            assert_eq!(stack.values, vec![5, 42, 58]);
        }

        #[test]
        fn switch_empty_register_on_empty_stack_fails() {
            let mut stack = Stack::<isize>::new();

            let res = stack.switch_register();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn swap_works() {
            let mut stack = Stack::new();
            stack.push(1);
            stack.push(2);
            stack.push(3);

            let res = stack.swap();

            assert!(res.is_ok());
            assert_eq!(stack.values, vec![1, 3, 2]);
        }

        #[test]
        fn swap_with_empty_stack_fails() {
            let mut stack = Stack::<isize>::new();

            let res = stack.swap();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn swap_with_one_element_fails() {
            let mut stack = Stack::new();
            stack.push(1);

            let res = stack.swap();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn swap2_works() {
            let mut stack = Stack::new();
            stack.push(1);
            stack.push(2);
            stack.push(3);
            stack.push(4);

            let res = stack.swap2();

            assert!(res.is_ok());
            assert_eq!(stack.values, vec![1, 4, 2, 3]);
        }

        #[test]
        fn swap2_with_empty_stack_fails() {
            let mut stack = Stack::<isize>::new();

            let res = stack.swap2();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn swap2_with_one_element_fails() {
            let mut stack = Stack::new();
            stack.push(1);

            let res = stack.swap2();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn swap2_with_two_elements_fails() {
            let mut stack = Stack::new();
            stack.push(1);
            stack.push(2);

            let res = stack.swap2();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn rshift_works() {
            let mut stack = Stack::new();
            stack.push(1);
            stack.push(2);
            stack.push(3);
            stack.push(4);

            stack.rshift();

            assert_eq!(stack.values, vec![4, 1, 2, 3]);
        }

        #[test]
        fn lshift_works() {
            let mut stack = Stack::new();
            stack.push(1);
            stack.push(2);
            stack.push(3);
            stack.push(4);

            stack.lshift();

            assert_eq!(stack.values, vec![2, 3, 4, 1]);
        }
    }

    mod stack_of_stacks {
        use super::super::*;

        #[test]
        fn new_works() {
            let s = StackOfStacks::<isize>::new();

            assert_eq!(s.additional_stacks.len(), 0);
            assert_eq!(s.initial_stack.len(), 0);
            assert_eq!(s.initial_stack.register, None);
        }

        #[test]
        fn push_stack_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let res = s.push_stack(2);

            assert!(res.is_ok());

            assert_eq!(s.additional_stacks.len(), 1);
            assert_eq!(s.initial_stack.values, vec![5]);
            assert_eq!(s.additional_stacks[0].values, vec![42, 58]);
            assert_eq!(s.additional_stacks[0].register, None);
        }

        #[test]
        fn push_stack_with_all_elements_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let res = s.push_stack(3);

            assert!(res.is_ok());

            assert_eq!(s.additional_stacks.len(), 1);
            assert_eq!(s.initial_stack.values, vec![0; 0]);
            assert_eq!(s.additional_stacks[0].values, vec![5, 42, 58]);
            assert_eq!(s.additional_stacks[0].register, None);
        }

        #[test]
        fn push_stack_with_zero_elements_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let res = s.push_stack(0);

            assert!(res.is_ok());

            assert_eq!(s.additional_stacks.len(), 1);
            assert_eq!(s.initial_stack.values, vec![5, 42, 58]);
            assert_eq!(s.additional_stacks[0].values, vec![0; 0]);
            assert_eq!(s.additional_stacks[0].register, None);
        }

        #[test]
        fn push_stack_with_too_many_values_fails() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);

            let res = s.push_stack(3);

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn pop_stack_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let res = s.push_stack(2);

            assert!(res.is_ok());

            s.pop_stack();

            assert_eq!(s.additional_stacks.len(), 0);
            assert_eq!(s.initial_stack.values, vec![5, 42, 58]);
            assert_eq!(s.initial_stack.register, None);
        }

        #[test]
        fn pop_stack_with_base_register_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let _ = s.top().switch_register().unwrap();
            let _ = s.push_stack(1).unwrap();

            s.pop_stack();

            assert_eq!(s.additional_stacks.len(), 0);
            assert_eq!(s.initial_stack.values, vec![5, 42]);
            assert_eq!(s.initial_stack.register, Some(58));
        }

        #[test]
        fn pop_stack_with_top_register_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let _ = s.push_stack(2).unwrap();
            let _ = s.top().switch_register().unwrap();

            s.pop_stack();

            assert_eq!(s.additional_stacks.len(), 0);
            assert_eq!(s.initial_stack.values, vec![5, 42]);
            assert_eq!(s.initial_stack.register, None);
        }

        #[test]
        fn pop_initial_stack_makes_it_empty() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let _ = s.top().switch_register().unwrap();

            s.pop_stack();

            assert_eq!(s.additional_stacks.len(), 0);
            assert_eq!(s.initial_stack.values, vec![0; 0]);
            assert_eq!(s.initial_stack.register, None);
        }
    }
}
<commit_msg>Simplify stack handling<commit_after>#[derive(PartialEq, Debug)]
pub enum Error {
    StackUnderflow,
}

pub struct Stack<T> {
    pub values: Vec<T>,
    pub register: Option<T>,
}

impl<T> Default for Stack<T>
where
    T: Clone,
{
    fn default() -> Self {
        Self::new()
    }
}

impl<T> Stack<T>
where
    T: Clone,
{
    pub fn new() -> Self {
        Stack {
            values: Vec::new(),
            register: None,
        }
    }

    pub fn len(&self) -> usize {
        self.values.len()
    }

    pub fn is_empty(&self) -> bool {
        self.values.is_empty()
    }

    pub fn push(&mut self, val: T) {
        self.values.push(val);
    }

    pub fn pop(&mut self) -> Option<T> {
        self.values.pop()
    }

    pub fn switch_register(&mut self) -> Result<(), Error> {
        match self.register.take() {
            Some(val) => self.push(val),
            None => self.register = Some(self.pop().ok_or(Error::StackUnderflow)?),
        }

        Ok(())
    }

    pub fn dup(&mut self) -> Result<(), Error> {
        let v = self.values.last().ok_or(Error::StackUnderflow)?.clone();
        self.values.push(v);
        Ok(())
    }

    pub fn drop(&mut self) -> Result<(), Error> {
        match self.values.len() {
            0 => Err(Error::StackUnderflow),
            n => {
                self.values.truncate(n - 1);
                Ok(())
            }
        }
    }

    pub fn swap(&mut self) -> Result<(), Error> {
        match self.values.len() {
            0 | 1 => Err(Error::StackUnderflow),
            n => {
                self.values.swap(n - 2, n - 1);
                Ok(())
            }
        }
    }

    pub fn swap2(&mut self) -> Result<(), Error> {
        match self.values.len() {
            0...2 => Err(Error::StackUnderflow),
            n => {
                self.values.swap(n - 2, n - 1);
                self.values.swap(n - 3, n - 2);
                Ok(())
            }
        }
    }

    pub fn rshift(&mut self) {
        let e = self.values.pop();
        if let Some(e) = e {
            self.values.insert(0, e);
        }
    }

    pub fn lshift(&mut self) {
        match self.values.len() {
            0 | 1 => {}
            _ => {
                let v = self.values.remove(0);
                self.values.push(v);
            }
        }
    }
}

pub struct StackOfStacks<T> {
    pub initial_stack: Stack<T>,
    pub additional_stacks: Vec<Stack<T>>,
}

impl<T> Default for StackOfStacks<T>
where
    T: Clone,
{
    fn default() -> Self {
        Self::new()
    }
}

impl<T> StackOfStacks<T>
where
    T: Clone,
{
    pub fn new() -> Self {
        StackOfStacks {
            initial_stack: Stack::new(),
            additional_stacks: vec![],
        }
    }

    pub fn push_stack(&mut self, moved_items: usize) -> Result<(), Error> {
        let vals = {
            let stack = self.top();
            let n = stack
                .len()
                .checked_sub(moved_items)
                .ok_or(Error::StackUnderflow)?;
            stack.values.split_off(n)
        };

        self.additional_stacks.push(Stack {
            values: vals,
            register: None,
        });

        Ok(())
    }

    pub fn pop_stack(&mut self) {
        if let Some(stack) = self.additional_stacks.pop() {
            self.top().values.extend(stack.values);
        } else {
            self.initial_stack.values.clear();
            self.initial_stack.register = None;
        }
    }

    pub fn top(&mut self) -> &mut Stack<T> {
        self.additional_stacks
            .last_mut()
            .unwrap_or(&mut self.initial_stack)
    }
}

#[cfg(test)]
mod tests {
    mod stack {
        use super::super::*;

        #[test]
        fn new_works() {
            let stack = Stack::<isize>::new();

            assert!(stack.is_empty());
            assert_eq!(stack.register, None);
        }

        #[test]
        fn push_works() {
            let mut stack = Stack::new();
            stack.push(5);
            stack.push(42);
            stack.push(58);

            assert_eq!(stack.len(), 3);
            assert_eq!(stack.values, vec![5, 42, 58]);
        }

        #[test]
        fn pop_works() {
            let mut stack = Stack::<isize>::new();
            stack.push(5);

            assert_eq!(stack.pop(), Some(5));
        }

        #[test]
        fn pop_empty_stack_returns_none() {
            let mut stack = Stack::<isize>::new();
            assert_eq!(stack.pop(), None);
        }

        #[test]
        fn dup_works() {
            let mut stack = Stack::new();
            stack.push(5);
            stack.push(42);

            let res = stack.dup();

            assert!(res.is_ok());
            assert_eq!(stack.values, vec![5, 42, 42]);
        }

        #[test]
        fn dup_with_empty_stack_fails() {
            let mut stack = Stack::<isize>::new();

            let res = stack.dup();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn drop_works() {
            let mut stack = Stack::new();
            stack.push(5);
            stack.push(42);

            let res = stack.drop();

            assert!(res.is_ok());
            assert_eq!(stack.values, vec![5]);
        }

        #[test]
        fn drop_with_empty_stack_fails() {
            let mut stack = Stack::<isize>::new();

            let res = stack.drop();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn switch_register_works() {
            let mut stack = Stack::new();
            stack.push(5);
            stack.push(42);
            stack.push(58);

            let res = stack.switch_register();

            assert!(res.is_ok());
            assert_eq!(stack.register, Some(58));
            assert_eq!(stack.values, vec![5, 42]);

            let res2 = stack.switch_register();

            assert!(res2.is_ok());
            assert_eq!(stack.register, None);
            assert_eq!(stack.values, vec![5, 42, 58]);
        }

        #[test]
        fn switch_empty_register_on_empty_stack_fails() {
            let mut stack = Stack::<isize>::new();

            let res = stack.switch_register();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn swap_works() {
            let mut stack = Stack::new();
            stack.push(1);
            stack.push(2);
            stack.push(3);

            let res = stack.swap();

            assert!(res.is_ok());
            assert_eq!(stack.values, vec![1, 3, 2]);
        }

        #[test]
        fn swap_with_empty_stack_fails() {
            let mut stack = Stack::<isize>::new();

            let res = stack.swap();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn swap_with_one_element_fails() {
            let mut stack = Stack::new();
            stack.push(1);

            let res = stack.swap();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn swap2_works() {
            let mut stack = Stack::new();
            stack.push(1);
            stack.push(2);
            stack.push(3);
            stack.push(4);

            let res = stack.swap2();

            assert!(res.is_ok());
            assert_eq!(stack.values, vec![1, 4, 2, 3]);
        }

        #[test]
        fn swap2_with_empty_stack_fails() {
            let mut stack = Stack::<isize>::new();

            let res = stack.swap2();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn swap2_with_one_element_fails() {
            let mut stack = Stack::new();
            stack.push(1);

            let res = stack.swap2();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn swap2_with_two_elements_fails() {
            let mut stack = Stack::new();
            stack.push(1);
            stack.push(2);

            let res = stack.swap2();

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn rshift_works() {
            let mut stack = Stack::new();
            stack.push(1);
            stack.push(2);
            stack.push(3);
            stack.push(4);

            stack.rshift();

            assert_eq!(stack.values, vec![4, 1, 2, 3]);
        }

        #[test]
        fn lshift_works() {
            let mut stack = Stack::new();
            stack.push(1);
            stack.push(2);
            stack.push(3);
            stack.push(4);

            stack.lshift();

            assert_eq!(stack.values, vec![2, 3, 4, 1]);
        }
    }

    mod stack_of_stacks {
        use super::super::*;

        #[test]
        fn new_works() {
            let s = StackOfStacks::<isize>::new();

            assert_eq!(s.additional_stacks.len(), 0);
            assert_eq!(s.initial_stack.len(), 0);
            assert_eq!(s.initial_stack.register, None);
        }

        #[test]
        fn push_stack_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let res = s.push_stack(2);

            assert!(res.is_ok());

            assert_eq!(s.additional_stacks.len(), 1);
            assert_eq!(s.initial_stack.values, vec![5]);
            assert_eq!(s.additional_stacks[0].values, vec![42, 58]);
            assert_eq!(s.additional_stacks[0].register, None);
        }

        #[test]
        fn push_stack_with_all_elements_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let res = s.push_stack(3);

            assert!(res.is_ok());

            assert_eq!(s.additional_stacks.len(), 1);
            assert_eq!(s.initial_stack.values, vec![0; 0]);
            assert_eq!(s.additional_stacks[0].values, vec![5, 42, 58]);
            assert_eq!(s.additional_stacks[0].register, None);
        }

        #[test]
        fn push_stack_with_zero_elements_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let res = s.push_stack(0);

            assert!(res.is_ok());

            assert_eq!(s.additional_stacks.len(), 1);
            assert_eq!(s.initial_stack.values, vec![5, 42, 58]);
            assert_eq!(s.additional_stacks[0].values, vec![0; 0]);
            assert_eq!(s.additional_stacks[0].register, None);
        }

        #[test]
        fn push_stack_with_too_many_values_fails() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);

            let res = s.push_stack(3);

            assert_eq!(res, Err(Error::StackUnderflow));
        }

        #[test]
        fn pop_stack_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let res = s.push_stack(2);

            assert!(res.is_ok());

            s.pop_stack();

            assert_eq!(s.additional_stacks.len(), 0);
            assert_eq!(s.initial_stack.values, vec![5, 42, 58]);
            assert_eq!(s.initial_stack.register, None);
        }

        #[test]
        fn pop_stack_with_base_register_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let _ = s.top().switch_register().unwrap();
            let _ = s.push_stack(1).unwrap();

            s.pop_stack();

            assert_eq!(s.additional_stacks.len(), 0);
            assert_eq!(s.initial_stack.values, vec![5, 42]);
            assert_eq!(s.initial_stack.register, Some(58));
        }

        #[test]
        fn pop_stack_with_top_register_works() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let _ = s.push_stack(2).unwrap();
            let _ = s.top().switch_register().unwrap();

            s.pop_stack();

            assert_eq!(s.additional_stacks.len(), 0);
            assert_eq!(s.initial_stack.values, vec![5, 42]);
            assert_eq!(s.initial_stack.register, None);
        }

        #[test]
        fn pop_initial_stack_makes_it_empty() {
            let mut s = StackOfStacks::new();
            s.top().push(5);
            s.top().push(42);
            s.top().push(58);

            let _ = s.top().switch_register().unwrap();

            s.pop_stack();

            assert_eq!(s.additional_stacks.len(), 0);
            assert_eq!(s.initial_stack.values, vec![0; 0]);
            assert_eq!(s.initial_stack.register, None);
        }
    }
}
<|endoftext|>


<commit_before>use rusqlite::{params, Connection};
use std::collections::HashMap;
use std::path::Path;
use std::result::Result as Result_;
use thiserror::Error;

use super::Query;

pub type Result<T, E = StoreError> = Result_<T, E>;

#[derive(Error, Debug)]
pub enum StoreError {
    #[error("database error")]
    Sqlite(#[from] rusqlite::Error),

    #[error("could not de/serialize object")]
    Serialization(#[from] serde_json::Error),
}

trait AsStoreResult<T> {
    fn as_store_result(self) -> Result<T>;
}

impl<T, E> AsStoreResult<T> for Result_<T, E>
where
    E: Into<StoreError>,
{
    fn as_store_result(self) -> Result<T> {
        self.map_err(|e| e.into())
    }
}

pub type Object = HashMap<String, serde_json::Value>;

pub struct Store {
    conn: Connection,
}

impl Store {
    pub fn open(path: impl AsRef<Path>) -> Result<Store> {
        let mut store = Store {
            conn: Connection::open(path)?,
        };

        // Make SQLite use a write-ahead instead of a delete-based journal; see
        // [the SQLite documentation](https://www.sqlite.org/wal.html) for more info.
        store.conn.pragma_update(None, "journal_mode", &"WAL")?;

        // Check that the JSON1 extension is working.
        store
            .conn
            .prepare("SELECT json(\"{}\")")?
            .query(params![])
            // Explicitly ignore the value.
            .map(|_| {})?;

        store.upgrade_if_needed()?;

        Ok(store)
    }

    fn upgrade_if_needed(&mut self) -> Result<()> {
        // We check the version of the database and upgrade it if necessary.
        // Conveniently, this starts at 0 in an empty database.
        let version = self
            .conn
            .prepare("SELECT user_version from pragma_user_version")?
            .query_row(params![], |row| row.get::<usize, i64>(0))? as usize;

        // We use `AUTOINCREMENT` on the objects table so that IDs are not reused.
        let updates = [
            "
                CREATE TABLE objects (
                    object_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    properties TEXT
                );
            ",
            "
                CREATE TABLE object_changes (
                    serial INTEGER PRIMARY KEY,
                    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    object_id INTEGER,
                    action TEXT,
                    previous TEXT
                );
                CREATE TABLE checkpoints (
                    checkpoint_id INTEGER PRIMARY KEY,
                    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    serial INTEGER
                );
            ",
        ];

        // We set the `user_version` after each update to ensure updates are not applied twice if one
        // in a sequence of updates fails.
        for (version, update) in updates.iter().enumerate().skip(version) {
            self.conn.execute_batch(update)?;
            self.conn
                .pragma_update(None, "user_version", &(version as i64))?;
        }

        Ok(())
    }

    pub fn all(&self) -> Collection {
        Collection {
            conn: &self.conn,
            query: Query::Empty,
        }
    }

    pub fn add(&mut self, object: Object) -> Result<()> {
        let object_serialized = serde_json::to_string(&object)?;

        self.conn
            .prepare("INSERT INTO objects(properties) VALUES(?)")?
            .execute(params![object_serialized])?;

        Ok(())
    }
}

pub struct Collection<'a> {
    conn: &'a Connection,
    query: Query,
}

impl<'a> Collection<'a> {
    pub fn len(&self) -> Result<usize> {
        Ok(self
            .conn
            .prepare("SELECT COUNT(*) FROM objects")?
            // This workaround can be removed when https://github.com/rusqlite/rusqlite/issues/700
            // is closed
            .query_row(params![], |row| row.get::<usize, i64>(0))? as usize)
    }

    pub fn iter(&self) -> Result<impl Iterator<Item = Object> + 'a> {
        Ok(self
            .conn
            .prepare("SELECT properties FROM objects")?
            .query_and_then(params![], |row| row.get::<usize, String>(0))?
            .map(|r| {
                r.as_store_result().and_then(|serialized_object| {
                    serde_json::from_str(&serialized_object).as_store_result()
                })
            })
            .collect::<Result<Vec<Object>>>()?
            .into_iter())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use tempdir::TempDir;

    fn open_store(tempdir: &TempDir, name: &str) -> Store {
        Store::open(tempdir.path().join(name)).unwrap()
    }

    fn test_dir() -> TempDir {
        TempDir::new("qualia-store").unwrap()
    }

    fn mkobject<'a>(proplist: &'a [(&'a str, &'a str)]) -> Object {
        proplist
            .iter()
            .cloned()
            .map(|(k, v)| (k.to_string(), serde_json::Value::String(v.to_string())))
            .collect()
    }

    fn sort_objects(objects: &mut Vec<Object>) {
        objects.sort_by_key(|o| {
            o.get("name")
                .and_then(|v| Some(v.as_str().unwrap_or("")))
                .unwrap_or("")
                .to_string()
        })
    }

    #[test]
    fn new_store_is_empty() {
        assert_eq!(
            open_store(&test_dir(), "store.qualia").all().len().unwrap(),
            0
        );
    }

    #[test]
    fn added_objects_can_be_found() {
        let test_dir = test_dir();
        let mut store = open_store(&test_dir, "store.qualia");

        store.add(mkobject(&[("name", "b"), ("c", "d")])).unwrap();
        store.add(mkobject(&[("name", "d"), ("c", "f")])).unwrap();
        store.add(mkobject(&[("name", "c"), ("c", "e")])).unwrap();

        let all = store.all();

        assert_eq!(all.len().unwrap(), 3);
        let mut all_objects = all.iter().unwrap().collect::<Vec<Object>>();
        sort_objects(&mut all_objects);
        assert_eq!(
            all_objects,
            vec![
                mkobject(&[("name", "b"), ("c", "d")]),
                mkobject(&[("name", "c"), ("c", "e")]),
                mkobject(&[("name", "d"), ("c", "f")])
            ],
        );
    }
}
<commit_msg>Add object-id to results<commit_after>//! A document store with a flexible query language and built-in undo support.

use rusqlite::{params, Connection};
use serde_json::value::Number;
use std::collections::HashMap;
use std::path::Path;
use std::result::Result as Result_;
use thiserror::Error;

use super::Query;

pub type Result<T, E = StoreError> = Result_<T, E>;

#[derive(Error, Debug)]
pub enum StoreError {
    #[error("database error")]
    Sqlite(#[from] rusqlite::Error),

    #[error("could not de/serialize object")]
    Serialization(#[from] serde_json::Error),
}

trait AsStoreResult<T> {
    fn as_store_result(self) -> Result<T>;
}

impl<T, E> AsStoreResult<T> for Result_<T, E>
where
    E: Into<StoreError>,
{
    fn as_store_result(self) -> Result<T> {
        self.map_err(|e| e.into())
    }
}

pub type Object = HashMap<String, serde_json::Value>;

pub struct Store {
    conn: Connection,
}

impl Store {
    pub fn open(path: impl AsRef<Path>) -> Result<Store> {
        let mut store = Store {
            conn: Connection::open(path)?,
        };

        // Make SQLite use a write-ahead instead of a delete-based journal; see
        // [the SQLite documentation](https://www.sqlite.org/wal.html) for more info.
        store.conn.pragma_update(None, "journal_mode", &"WAL")?;

        // Check that the JSON1 extension is working.
        store
            .conn
            .prepare("SELECT json(\"{}\")")?
            .query(params![])
            // Explicitly ignore the value.
            .map(|_| {})?;

        store.upgrade_if_needed()?;

        Ok(store)
    }

    fn upgrade_if_needed(&mut self) -> Result<()> {
        // We check the version of the database and upgrade it if necessary.
        // Conveniently, this starts at 0 in an empty database.
        let version = self
            .conn
            .prepare("SELECT user_version from pragma_user_version")?
            .query_row(params![], |row| row.get::<usize, i64>(0))? as usize;

        // We use `AUTOINCREMENT` on the objects table so that IDs are not reused.
        let updates = [
            "
                CREATE TABLE objects (
                    object_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    properties TEXT
                );
            ",
            "
                CREATE TABLE object_changes (
                    serial INTEGER PRIMARY KEY,
                    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    object_id INTEGER,
                    action TEXT,
                    previous TEXT
                );
                CREATE TABLE checkpoints (
                    checkpoint_id INTEGER PRIMARY KEY,
                    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    serial INTEGER
                );
            ",
        ];

        // We set the `user_version` after each update to ensure updates are not applied twice if one
        // in a sequence of updates fails.
        for (version, update) in updates.iter().enumerate().skip(version) {
            self.conn.execute_batch(update)?;
            self.conn
                .pragma_update(None, "user_version", &(version as i64))?;
        }

        Ok(())
    }

    pub fn all(&self) -> Collection {
        Collection {
            conn: &self.conn,
            query: Query::Empty,
        }
    }

    pub fn add(&mut self, object: Object) -> Result<()> {
        let object_serialized = serde_json::to_string(&object)?;

        self.conn
            .prepare("INSERT INTO objects(properties) VALUES(?)")?
            .execute(params![object_serialized])?;

        Ok(())
    }
}

pub struct Collection<'a> {
    conn: &'a Connection,
    query: Query,
}

impl<'a> Collection<'a> {
    pub fn len(&self) -> Result<usize> {
        Ok(self
            .conn
            .prepare("SELECT COUNT(*) FROM objects")?
            // This workaround can be removed when https://github.com/rusqlite/rusqlite/issues/700
            // is closed
            .query_row(params![], |row| row.get::<usize, i64>(0))? as usize)
    }

    pub fn iter(&self) -> Result<impl Iterator<Item = Object> + 'a> {
        Ok(self
            .conn
            .prepare("SELECT object_id, properties FROM objects")?
            .query_and_then(params![], |row| {
                Ok((row.get::<usize, i64>(0)?, row.get::<usize, String>(1)?))
            })?
            .map(|r: rusqlite::Result<(i64, String)>| {
                r.as_store_result()
                    .and_then(|(object_id, serialized_object)| {
                        let mut object =
                            serde_json::from_str::<Object>(&serialized_object).as_store_result()?;

                        // TODO: this is a clear cut sign that we cannot rely on JSON for our value
                        // semantics
                        object.insert(
                            "object-id".to_string(),
                            serde_json::Value::Number(Number::from(object_id)),
                        );
                        Ok(object)
                    })
            })
            .collect::<Result<Vec<Object>>>()?
            .into_iter())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json::json;
    use tempdir::TempDir;

    fn open_store(tempdir: &TempDir, name: &str) -> Store {
        Store::open(tempdir.path().join(name)).unwrap()
    }

    fn test_dir() -> TempDir {
        TempDir::new("qualia-store").unwrap()
    }

    fn mkobject_(proplist: serde_json::Value) -> Object {
        let proplist_map = proplist.as_object().unwrap();

        proplist_map
            .iter()
            .map(|(k, v)| (k.clone(), v.clone()))
            .collect()
    }

    macro_rules! mkobject {
        ( $($x:tt)* ) => {
            mkobject_(json!({ $($x)* }))
        };
    }

    fn sort_objects(objects: &mut Vec<Object>) {
        objects.sort_by_key(|o| {
            o.get("name")
                .and_then(|v| Some(v.as_str().unwrap_or("")))
                .unwrap_or("")
                .to_string()
        })
    }

    #[test]
    fn new_store_is_empty() {
        assert_eq!(
            open_store(&test_dir(), "store.qualia").all().len().unwrap(),
            0
        );
    }

    #[test]
    fn added_objects_can_be_found() {
        let test_dir = test_dir();
        let mut store = open_store(&test_dir, "store.qualia");

        store.add(mkobject!("name": "b", "c": "d")).unwrap();
        store.add(mkobject!("name": "d", "c": "f")).unwrap();
        store.add(mkobject!("name": "c", "c": "e")).unwrap();

        let all = store.all();

        assert_eq!(all.len().unwrap(), 3);
        let mut all_objects = all.iter().unwrap().collect::<Vec<Object>>();
        sort_objects(&mut all_objects);
        assert_eq!(
            all_objects,
            vec![
                mkobject!("name": "b", "c": "d", "object-id": 1),
                mkobject!("name": "c", "c": "e", "object-id": 3),
                mkobject!("name": "d", "c": "f", "object-id": 2)
            ],
        );
    }
}
<|endoftext|>


<commit_before>extern crate rand;
use table::rand::Rng;
use multi;

#[derive(Clone)]
pub struct Bucket {
    pointers: Vec<usize>,
    hash_sig: usize
}

impl Bucket {
    pub fn new(hash_sig: usize) -> Self {
        Bucket {
            pointers: Vec::new(),
            hash_sig: hash_sig
        }
    }
    pub fn push(&mut self, value: usize) {
        self.pointers.push(value);
    }
}

#[derive(Clone, Default)]
pub struct BucketChain {
    chain: Vec<Bucket>
}

impl BucketChain {
    pub fn new() -> Self {
        BucketChain{
            chain: Vec::new()
        }
    }
    pub fn get(&self, _index: usize) -> Option<&Bucket> {
        for bucket_ref in &self.chain {
            if bucket_ref.hash_sig == _index {
                return Some(bucket_ref);
            }
        }
        None
    }
    pub fn get_mut(&mut self, _index: usize) -> Option<&mut Bucket> {
        for bucket_ref in &mut self.chain {
            if bucket_ref.hash_sig == _index {
                return Some(bucket_ref);
            }
        }
        None
    }
    pub fn create_and_add_bucket(&mut self, bucket_sig: usize, value: usize) {
        let mut new_bucket = Bucket::new(bucket_sig);
        new_bucket.push(value);
        self.chain.push(new_bucket);
    }
}

const P: u64 = (0xFFFFFFFE as u64 - 4) as u64;
pub struct LSHTable<'a, T: 'a, Q: 'a+?Sized>  {
    buckets: Vec<BucketChain>,
    data: &'a [T],
    hash_functions: Vec<Box<Q>>,
    ri1: Vec<u32>,
    ri2: Vec<u32>,
    multiprobe_sequence: &'a [Vec<usize>]
}

impl<'a, T, Q: 'a+?Sized> LSHTable<'a, T, Q> where Q: Fn(&'a T) -> f32 {
    pub fn new(data: &'a [T], hashes: Vec<Box<Q>>, ms: &'a [Vec<usize>]) -> Self {
        let length_hash = hashes.len();
        LSHTable {
            buckets: vec![BucketChain::new(); data.len()],
            data: data,
            hash_functions: hashes,
            ri1: rand::thread_rng().gen_iter().take(length_hash).collect(),
            ri2: rand::thread_rng().gen_iter().take(length_hash).collect(),
            multiprobe_sequence: ms
        }
    }
    fn get_signature(&self, v: &'a T) -> Vec<f32> {
        self.hash_functions.iter().map(|x| {
            (*x)(v)
        }).collect()
    }

    fn get_quantized_signature(&self, v: &'a T) -> Vec<u32> {
        self.hash_functions.iter().map(|x| {
            (*x)(v) as u32
        }).collect()
    }
    pub fn new_build(data: &'a [T], hashes: Vec<Box<Q>>, ms: &'a [Vec<usize>]) -> Self {
        let mut x_to_build = LSHTable::new(data, hashes, ms);
        for (i, v) in x_to_build.data.iter().enumerate() {
            let hash_sig = x_to_build.get_quantized_signature(v);
            let bucket_ind = hash_func_t1(&hash_sig, &x_to_build.ri1, x_to_build.buckets.len());
            let mut bucket_chain = &mut (x_to_build.buckets[bucket_ind]);
            let chain_ind = hash_func_t2(&hash_sig, &x_to_build.ri2);
            let mut bad = false;
            {
                let bucket_opt = bucket_chain.get_mut(chain_ind);
                match bucket_opt {
                    Some(bucket_ref) => bucket_ref.push(i),
                    None => bad = true
                };
            }
            if bad {
                bucket_chain.create_and_add_bucket(chain_ind, i);
            }
        }
        x_to_build
    }

    pub fn query_vec(&self, v: &'a T) -> Vec<usize> {
        let sig = self.get_quantized_signature(v);
        let sig_ind = hash_func_t1(&sig, &self.ri1, self.buckets.len());
        let chain_ind = hash_func_t2(&sig, &self.ri2);
        match self.buckets[sig_ind].get(chain_ind) {
           Some(bucket) => bucket.pointers.iter().map(|bucket_ind| {
                *bucket_ind
           }).collect(),
            None => Vec::new()
        }
    }

    fn get_all_sigs(&self, sig: &[f32], multiprobe_limit: usize) -> Vec<Vec<u32>> {
        let qsig = self.quantize_signature(sig);
        let pi_map = multi::compute_pi_j(sig, &qsig, 1.0);
        let mut combined_output = Vec::new();
        for perturb_set in self.multiprobe_sequence.iter().take(multiprobe_limit) {
            let mut out_vec = qsig.clone();
            for &val in perturb_set {
                let (i, delta) = pi_map[val];
                if delta == -1 {
                    out_vec[i] -= 1;
                } else {
                    out_vec[i] += delta as u32;
                }
            }
            combined_output.push(out_vec);
        }
        combined_output
    }

    fn quantize_signature(&self, sig: &[f32]) -> Vec<u32> {
        sig.iter().map(|&x| {x as u32}).collect()
    }

    pub fn query_multiprobe(&self, v: &'a T, multiprobe_limit: usize) -> Vec<usize> {
        let sig = self.get_signature(v);
        let all_sigs = self.get_all_sigs(&sig, multiprobe_limit);
        let mut output_vec = Vec::new();
        for s in &all_sigs {
            let sig_ind = hash_func_t1(s, &self.ri1, self.buckets.len());
            let chain_ind = hash_func_t2(s, &self.ri2);
            output_vec.append(
                &mut match self.buckets[sig_ind].get(chain_ind) {
                    Some(bucket) => bucket.pointers.iter().map(|bucket_ind| {
                        *bucket_ind
                    }).collect(),
                    None => Vec::new()
                });
        }
        output_vec
    }
}

#[inline(never)]
fn hash_func_t1(signature: &[u32], rand_ints: &[u32], num_buckets: usize) -> usize {
    let total: usize = hash_func_t2(signature, rand_ints);
    total % num_buckets
}

const HIGH_ORDER: u64 = 0xFFFF0000;
const LOW_ORDER: u64 = 0x0000FFFF;
#[inline(never)]
fn hash_func_t2(signature: &[u32], rand_ints: &[u32]) -> usize {
    /*let mut counter = 0;
    for element in signature.iter().zip(rand_ints).map(|(a, b)| {(a * b)}) {
        counter = ((counter + element)) % primes;
    }
    counter as usize*/
    let mut total = 0 as u32;
    for (&i, &j) in signature.iter().zip(rand_ints) {
        let i_product = (i * j) as u64;
        let alpha = (i_product & HIGH_ORDER) + 5 * (i_product & LOW_ORDER);
        if alpha < P {
            total = total + (alpha as u32);
        } else {
            total = (alpha - P) as u32;
        }
    }
    total as usize
}
#[cfg(test)]
mod tests {
    use super::LSHTable;
    use multi;

    // fn to gen multiprobe sequence
    #[test]
    fn test_init() {

        let test_data = vec![
            vec![1.0,2.0,3.0,4.0,5.0],
            vec![0.0,0.0,0.0,0.0,0.0],
            vec![1.0,2.0,3.0,4.0,5.0]
        ];

        let val = |q: &Vec<f32>| {0.0 as f32};
        let funcs = vec![Box::new(val)];
        let ms = vec![vec![1,2,3]];
        // get actual multiprobe sequence into ms instead
        let x = LSHTable::new(&test_data, funcs, &ms);
    }
    #[test]
    fn test_new_build() {
        let test_data = vec![
            vec![1.0,2.0,3.0,4.0,5.0],
            vec![0.0,0.0,0.0,0.0,0.0],
            vec![1.0,2.0,3.0,4.0,5.0]
        ];

        let val = |q: &Vec<f32>| {0.0 as f32};
        let funcs = vec![Box::new(val)];
        let ms = vec![vec![1,2,3]];
        let x = LSHTable::new_build(&test_data, funcs, &ms);
    }

    #[test]
    fn test_query() {
        let test_data = vec![
            vec![1.0,2.0,3.0,4.0,5.0],
            vec![0.0,0.0,0.0,0.0,0.0],
            vec![1.0,2.0,3.0,4.0,5.0]
        ];

        let val = |q: &Vec<f32>| {0.0 as f32};
        let funcs = vec![Box::new(val)];
        let zjs = multi::get_expected_zj_vals(1,1.0);
        let sets: Vec<multi::PerturbationSet> = multi::gen_perturbation_sets(&zjs)
            .take(5)
            .collect();
        let ms: Vec<Vec<usize>> = sets.into_iter()
            .map(|x| {x.data})
            .collect();
        let x = LSHTable::new_build(&test_data, funcs, &ms);
        x.query_vec(&test_data[0]);
    }
    #[test]
    fn test_query_multiprobe() {
        let test_data = vec![
            vec![1.0,2.0,3.0,4.0,5.0],
            vec![0.0,0.0,0.0,0.0,0.0],
            vec![1.0,2.0,3.0,4.0,5.0]
        ];

        let val = |q: &Vec<f32>| {0.0 as f32};
        let funcs = vec![Box::new(val)];
        let zjs = multi::get_expected_zj_vals(1,1.0);
        let sets: Vec<multi::PerturbationSet> = multi::gen_perturbation_sets(&zjs)
            .take(5)
            .collect();
        let ms: Vec<Vec<usize>> = sets.into_iter()
            .map(|x| {x.data})
            .collect();
        let x = LSHTable::new_build(&test_data, funcs, &ms);
        x.query_multiprobe(&test_data[0], 3);
    }
}
<commit_msg>go back to inlining<commit_after>extern crate rand;
use table::rand::Rng;
use multi;

#[derive(Clone)]
pub struct Bucket {
    pointers: Vec<usize>,
    hash_sig: usize
}

impl Bucket {
    pub fn new(hash_sig: usize) -> Self {
        Bucket {
            pointers: Vec::new(),
            hash_sig: hash_sig
        }
    }
    pub fn push(&mut self, value: usize) {
        self.pointers.push(value);
    }
}

#[derive(Clone, Default)]
pub struct BucketChain {
    chain: Vec<Bucket>
}

impl BucketChain {
    pub fn new() -> Self {
        BucketChain{
            chain: Vec::new()
        }
    }
    pub fn get(&self, _index: usize) -> Option<&Bucket> {
        for bucket_ref in &self.chain {
            if bucket_ref.hash_sig == _index {
                return Some(bucket_ref);
            }
        }
        None
    }
    pub fn get_mut(&mut self, _index: usize) -> Option<&mut Bucket> {
        for bucket_ref in &mut self.chain {
            if bucket_ref.hash_sig == _index {
                return Some(bucket_ref);
            }
        }
        None
    }
    pub fn create_and_add_bucket(&mut self, bucket_sig: usize, value: usize) {
        let mut new_bucket = Bucket::new(bucket_sig);
        new_bucket.push(value);
        self.chain.push(new_bucket);
    }
}

const P: u64 = (0xFFFFFFFE as u64 - 4) as u64;
pub struct LSHTable<'a, T: 'a, Q: 'a+?Sized>  {
    buckets: Vec<BucketChain>,
    data: &'a [T],
    hash_functions: Vec<Box<Q>>,
    ri1: Vec<u32>,
    ri2: Vec<u32>,
    multiprobe_sequence: &'a [Vec<usize>]
}

impl<'a, T, Q: 'a+?Sized> LSHTable<'a, T, Q> where Q: Fn(&'a T) -> f32 {
    pub fn new(data: &'a [T], hashes: Vec<Box<Q>>, ms: &'a [Vec<usize>]) -> Self {
        let length_hash = hashes.len();
        LSHTable {
            buckets: vec![BucketChain::new(); data.len()],
            data: data,
            hash_functions: hashes,
            ri1: rand::thread_rng().gen_iter().take(length_hash).collect(),
            ri2: rand::thread_rng().gen_iter().take(length_hash).collect(),
            multiprobe_sequence: ms
        }
    }
    fn get_signature(&self, v: &'a T) -> Vec<f32> {
        self.hash_functions.iter().map(|x| {
            (*x)(v)
        }).collect()
    }

    fn get_quantized_signature(&self, v: &'a T) -> Vec<u32> {
        self.hash_functions.iter().map(|x| {
            (*x)(v) as u32
        }).collect()
    }
    pub fn new_build(data: &'a [T], hashes: Vec<Box<Q>>, ms: &'a [Vec<usize>]) -> Self {
        let mut x_to_build = LSHTable::new(data, hashes, ms);
        for (i, v) in x_to_build.data.iter().enumerate() {
            let hash_sig = x_to_build.get_quantized_signature(v);
            let bucket_ind = hash_func_t1(&hash_sig, &x_to_build.ri1, x_to_build.buckets.len());
            let mut bucket_chain = &mut (x_to_build.buckets[bucket_ind]);
            let chain_ind = hash_func_t2(&hash_sig, &x_to_build.ri2);
            let mut bad = false;
            {
                let bucket_opt = bucket_chain.get_mut(chain_ind);
                match bucket_opt {
                    Some(bucket_ref) => bucket_ref.push(i),
                    None => bad = true
                };
            }
            if bad {
                bucket_chain.create_and_add_bucket(chain_ind, i);
            }
        }
        x_to_build
    }

    pub fn query_vec(&self, v: &'a T) -> Vec<usize> {
        let sig = self.get_quantized_signature(v);
        let sig_ind = hash_func_t1(&sig, &self.ri1, self.buckets.len());
        let chain_ind = hash_func_t2(&sig, &self.ri2);
        match self.buckets[sig_ind].get(chain_ind) {
           Some(bucket) => bucket.pointers.iter().map(|bucket_ind| {
                *bucket_ind
           }).collect(),
            None => Vec::new()
        }
    }

    fn get_all_sigs(&self, sig: &[f32], multiprobe_limit: usize) -> Vec<Vec<u32>> {
        let qsig = self.quantize_signature(sig);
        let pi_map = multi::compute_pi_j(sig, &qsig, 1.0);
        let mut combined_output = Vec::new();
        for perturb_set in self.multiprobe_sequence.iter().take(multiprobe_limit) {
            let mut out_vec = qsig.clone();
            for &val in perturb_set {
                let (i, delta) = pi_map[val];
                if delta == -1 {
                    out_vec[i] -= 1;
                } else {
                    out_vec[i] += delta as u32;
                }
            }
            combined_output.push(out_vec);
        }
        combined_output
    }

    fn quantize_signature(&self, sig: &[f32]) -> Vec<u32> {
        sig.iter().map(|&x| {x as u32}).collect()
    }

    pub fn query_multiprobe(&self, v: &'a T, multiprobe_limit: usize) -> Vec<usize> {
        let sig = self.get_signature(v);
        let all_sigs = self.get_all_sigs(&sig, multiprobe_limit);
        let mut output_vec = Vec::new();
        for s in &all_sigs {
            let sig_ind = hash_func_t1(s, &self.ri1, self.buckets.len());
            let chain_ind = hash_func_t2(s, &self.ri2);
            output_vec.append(
                &mut match self.buckets[sig_ind].get(chain_ind) {
                    Some(bucket) => bucket.pointers.iter().map(|bucket_ind| {
                        *bucket_ind
                    }).collect(),
                    None => Vec::new()
                });
        }
        output_vec
    }
}

fn hash_func_t1(signature: &[u32], rand_ints: &[u32], num_buckets: usize) -> usize {
    let total: usize = hash_func_t2(signature, rand_ints);
    total % num_buckets
}

const HIGH_ORDER: u64 = 0xFFFF0000;
const LOW_ORDER: u64 = 0x0000FFFF;

fn hash_func_t2(signature: &[u32], rand_ints: &[u32]) -> usize {
    let mut total = 0 as u32;
    for (&i, &j) in signature.iter().zip(rand_ints) {
        let i_product = (i * j) as u64;
        let alpha = (i_product & HIGH_ORDER) + 5 * (i_product & LOW_ORDER);
        if alpha < P {
            total = total + (alpha as u32);
        } else {
            total = (total + ((alpha - P) as u32)) as u32;
        }
    }
    total as usize
}
#[cfg(test)]
mod tests {
    use super::LSHTable;
    use multi;

    // fn to gen multiprobe sequence
    #[test]
    fn test_init() {

        let test_data = vec![
            vec![1.0,2.0,3.0,4.0,5.0],
            vec![0.0,0.0,0.0,0.0,0.0],
            vec![1.0,2.0,3.0,4.0,5.0]
        ];

        let val = |q: &Vec<f32>| {0.0 as f32};
        let funcs = vec![Box::new(val)];
        let ms = vec![vec![1,2,3]];
        // get actual multiprobe sequence into ms instead
        let x = LSHTable::new(&test_data, funcs, &ms);
    }
    #[test]
    fn test_new_build() {
        let test_data = vec![
            vec![1.0,2.0,3.0,4.0,5.0],
            vec![0.0,0.0,0.0,0.0,0.0],
            vec![1.0,2.0,3.0,4.0,5.0]
        ];

        let val = |q: &Vec<f32>| {0.0 as f32};
        let funcs = vec![Box::new(val)];
        let ms = vec![vec![1,2,3]];
        let x = LSHTable::new_build(&test_data, funcs, &ms);
    }

    #[test]
    fn test_query() {
        let test_data = vec![
            vec![1.0,2.0,3.0,4.0,5.0],
            vec![0.0,0.0,0.0,0.0,0.0],
            vec![1.0,2.0,3.0,4.0,5.0]
        ];

        let val = |q: &Vec<f32>| {0.0 as f32};
        let funcs = vec![Box::new(val)];
        let zjs = multi::get_expected_zj_vals(1,1.0);
        let sets: Vec<multi::PerturbationSet> = multi::gen_perturbation_sets(&zjs)
            .take(5)
            .collect();
        let ms: Vec<Vec<usize>> = sets.into_iter()
            .map(|x| {x.data})
            .collect();
        let x = LSHTable::new_build(&test_data, funcs, &ms);
        x.query_vec(&test_data[0]);
    }
    #[test]
    fn test_query_multiprobe() {
        let test_data = vec![
            vec![1.0,2.0,3.0,4.0,5.0],
            vec![0.0,0.0,0.0,0.0,0.0],
            vec![1.0,2.0,3.0,4.0,5.0]
        ];

        let val = |q: &Vec<f32>| {0.0 as f32};
        let funcs = vec![Box::new(val)];
        let zjs = multi::get_expected_zj_vals(1,1.0);
        let sets: Vec<multi::PerturbationSet> = multi::gen_perturbation_sets(&zjs)
            .take(5)
            .collect();
        let ms: Vec<Vec<usize>> = sets.into_iter()
            .map(|x| {x.data})
            .collect();
        let x = LSHTable::new_build(&test_data, funcs, &ms);
        x.query_multiprobe(&test_data[0], 3);
    }
}
<|endoftext|>


<commit_before>use libc::{c_int, c_void};
use std::sync::mpsc;

use super::*;

pub enum StateEvent {
    PutGlyph(PutGlyphEvent),
    MoveCursor(MoveCursorEvent),
    ScrollRect(ScrollRectEvent),
    MoveRect(MoveRectEvent),
    Erase(EraseEvent),
    InitPen,
    CursorVisible(CursorVisibleEvent),
    CursorBlink(CursorBlinkEvent),
    AltScreen(AltScreenEvent),
    Title(TitleEvent),
    IconName(IconNameEvent),
    Reverse(ReverseEvent),
    CursorShape(CursorShapeEvent),
    Mouse(MouseEvent),
    Bell,
    Resize(ResizeEvent),
    SetLineInfo,
}

pub struct StateCallbacksConfig {
    pub put_glyph: bool,
    pub move_cursor: bool,
    pub scroll_rect: bool,
    pub move_rect: bool,
    pub erase: bool,
    pub init_pen: bool,
    pub set_pen_attr: bool,
    pub set_term_prop: bool,
    pub bell: bool,
    pub resize: bool,
    pub set_line_info: bool,
}

impl StateCallbacksConfig {
    pub fn all() -> StateCallbacksConfig {
        StateCallbacksConfig {
            put_glyph: true,
            move_cursor: true,
            scroll_rect: true,
            move_rect: true,
            erase: true,
            init_pen: true,
            set_pen_attr: true,
            set_term_prop: true,
            bell: true,
            resize: true,
            set_line_info: true,
        }
    }

    pub fn none() -> StateCallbacksConfig {
        StateCallbacksConfig {
            put_glyph: false,
            move_cursor: false,
            scroll_rect: false,
            move_rect: false,
            erase: false,
            init_pen: false,
            set_pen_attr: false,
            set_term_prop: false,
            bell: false,
            resize: false,
            set_line_info: false,
        }
    }
}

impl VTerm {
    pub fn state_get_default_colors(&self) -> (ColorRGB, ColorRGB) {
        let mut fg_rgb: ffi::VTermColor = Default::default();
        let mut bg_rgb: ffi::VTermColor = Default::default();
        unsafe {
            ffi::vterm_state_get_default_colors(self.state_ptr.get(), &mut fg_rgb, &mut bg_rgb)
        };

        (ColorRGB {
            red: fg_rgb.red,
            green: fg_rgb.green,
            blue: fg_rgb.blue,
        },
         ColorRGB {
            red: bg_rgb.red,
            green: bg_rgb.green,
            blue: bg_rgb.blue,
        })
    }

    pub fn state_set_default_colors(&mut self, default_fg: &ColorRGB, default_bg: &ColorRGB) {
        let fg_rgb = ffi::VTermColor {
            red: default_fg.red,
            green: default_fg.green,
            blue: default_fg.blue,
        };
        let bg_rgb = ffi::VTermColor {
            red: default_bg.red,
            green: default_bg.green,
            blue: default_bg.blue,
        };

        unsafe {
            ffi::vterm_state_set_default_colors(self.state_ptr.get_mut(), &fg_rgb, &bg_rgb);
        };
    }

    pub fn state_get_rgb_color_from_palette(&self, index: usize) -> ColorRGB {
        let mut ffi_color: ffi::VTermColor = Default::default();
        unsafe {
            ffi::vterm_state_get_palette_color(self.state_ptr.get(),
                                               index as c_int,
                                               &mut ffi_color);
        }
        ColorRGB {
            red: ffi_color.red,
            green: ffi_color.green,
            blue: ffi_color.blue,
        }
    }

    pub fn state_get_palette_color_from_rgb(&self, target: &ColorRGB) -> usize {
        for i in 0..256 {
            let color = self.state_get_rgb_color_from_palette(i);
            if color.red == target.red && color.green == target.green && color.blue == target.blue {
                return i as usize;
            }
        }
        0
    }

    /// move this to ffi classes since it deals with the ffi color type
    pub fn state_get_palette_color_from_c_rgb(&self, target: &ffi::VTermColor) -> usize {
        for i in 0..256 {
            let color = self.state_get_rgb_color_from_palette(i);
            if color.red == target.red && color.green == target.green && color.blue == target.blue {
                return i as usize;
            }
        }
        0
    }

    pub fn state_reset(&mut self, hard: bool) {
        unsafe {
            ffi::vterm_state_reset(self.state_ptr.get_mut(), ::bool_to_int(hard));
        }
    }

    pub fn state_receive_events(&mut self, config: &StateCallbacksConfig) {
        let mut callbacks: ffi::VTermStateCallbacks = Default::default();

        // Note: Some of these seem to be required or libvterm will segfault
        callbacks.put_glyph = if config.put_glyph { Some(::state_callbacks::put_glyph) } else { None };
        callbacks.move_cursor = if config.move_cursor { Some(::state_callbacks::move_cursor) } else { None };
        callbacks.scroll_rect = if config.scroll_rect { Some(::state_callbacks::scroll_rect) } else { None };
        callbacks.move_rect = if config.move_rect { Some(::state_callbacks::move_rect) } else { None };
        callbacks.erase = if config.erase { Some(::state_callbacks::erase) } else { None };
        callbacks.init_pen = if config.init_pen { Some(::state_callbacks::init_pen) } else { None };
        callbacks.set_pen_attr = if config.set_pen_attr { Some(::state_callbacks::set_pen_attr) } else { None };
        callbacks.set_term_prop = if config.set_term_prop { Some(::state_callbacks::set_term_prop) } else { None };
        callbacks.bell = if config.bell { Some(::state_callbacks::bell) } else { None };
        callbacks.resize = if config.resize { Some(::state_callbacks::resize) } else { None };
        callbacks.set_line_info = if config.set_line_info { Some(::state_callbacks::set_line_info) } else { None };

        self.state_callbacks = Some(callbacks);

        if self.state_event_tx.is_none() {
            let (tx, rx) = mpsc::channel();
            self.state_event_tx = Some(tx);
            self.state_event_rx = Some(rx);
        }

        unsafe {
            let self_ptr: *mut c_void = self as *mut _ as *mut c_void;
            ffi::vterm_state_set_callbacks(self.state_ptr.get_mut(),
                                            self.state_callbacks.as_ref().unwrap(),
                                            self_ptr);
        }
    }
}

mod tests {
    #![allow(unused_imports)]
    use super::super::*;
    use std::io::prelude::*;

    #[test]
    fn state_can_get_and_set_default_colors() {
        let mut vterm: VTerm = VTerm::new(&Size {
            height: 2,
            width: 2,
        });
        vterm.state_set_default_colors(&ColorRGB {
                                           red: 200,
                                           green: 201,
                                           blue: 202,
                                       },
                                       &ColorRGB {
                                           red: 0,
                                           green: 1,
                                           blue: 2,
                                       });
        let (fg_rgb, bg_rgb) = vterm.state_get_default_colors();

        assert_eq!(fg_rgb.red, 200);
        assert_eq!(fg_rgb.green, 201);
        assert_eq!(fg_rgb.blue, 202);

        assert_eq!(bg_rgb.red, 0);
        assert_eq!(bg_rgb.green, 1);
        assert_eq!(bg_rgb.blue, 2);
    }
}
<commit_msg>Add comment<commit_after>use libc::{c_int, c_void};
use std::sync::mpsc;

use super::*;

pub enum StateEvent {
    PutGlyph(PutGlyphEvent),
    MoveCursor(MoveCursorEvent),
    ScrollRect(ScrollRectEvent),
    MoveRect(MoveRectEvent),
    Erase(EraseEvent),
    InitPen,
    CursorVisible(CursorVisibleEvent),
    CursorBlink(CursorBlinkEvent),
    AltScreen(AltScreenEvent),
    Title(TitleEvent),
    IconName(IconNameEvent),
    Reverse(ReverseEvent),
    CursorShape(CursorShapeEvent),
    Mouse(MouseEvent),
    Bell,
    Resize(ResizeEvent),
    SetLineInfo,
}

pub struct StateCallbacksConfig {
    pub put_glyph: bool,
    pub move_cursor: bool,
    pub scroll_rect: bool,
    /// Seems move_rect only gets called if scroll_rect is `false`
    pub move_rect: bool,
    pub erase: bool,
    pub init_pen: bool,
    pub set_pen_attr: bool,
    pub set_term_prop: bool,
    pub bell: bool,
    pub resize: bool,
    pub set_line_info: bool,
}

impl StateCallbacksConfig {
    pub fn all() -> StateCallbacksConfig {
        StateCallbacksConfig {
            put_glyph: true,
            move_cursor: true,
            scroll_rect: true,
            move_rect: true,
            erase: true,
            init_pen: true,
            set_pen_attr: true,
            set_term_prop: true,
            bell: true,
            resize: true,
            set_line_info: true,
        }
    }

    pub fn none() -> StateCallbacksConfig {
        StateCallbacksConfig {
            put_glyph: false,
            move_cursor: false,
            scroll_rect: false,
            move_rect: false,
            erase: false,
            init_pen: false,
            set_pen_attr: false,
            set_term_prop: false,
            bell: false,
            resize: false,
            set_line_info: false,
        }
    }
}

impl VTerm {
    pub fn state_get_default_colors(&self) -> (ColorRGB, ColorRGB) {
        let mut fg_rgb: ffi::VTermColor = Default::default();
        let mut bg_rgb: ffi::VTermColor = Default::default();
        unsafe {
            ffi::vterm_state_get_default_colors(self.state_ptr.get(), &mut fg_rgb, &mut bg_rgb)
        };

        (ColorRGB {
            red: fg_rgb.red,
            green: fg_rgb.green,
            blue: fg_rgb.blue,
        },
         ColorRGB {
            red: bg_rgb.red,
            green: bg_rgb.green,
            blue: bg_rgb.blue,
        })
    }

    pub fn state_set_default_colors(&mut self, default_fg: &ColorRGB, default_bg: &ColorRGB) {
        let fg_rgb = ffi::VTermColor {
            red: default_fg.red,
            green: default_fg.green,
            blue: default_fg.blue,
        };
        let bg_rgb = ffi::VTermColor {
            red: default_bg.red,
            green: default_bg.green,
            blue: default_bg.blue,
        };

        unsafe {
            ffi::vterm_state_set_default_colors(self.state_ptr.get_mut(), &fg_rgb, &bg_rgb);
        };
    }

    pub fn state_get_rgb_color_from_palette(&self, index: usize) -> ColorRGB {
        let mut ffi_color: ffi::VTermColor = Default::default();
        unsafe {
            ffi::vterm_state_get_palette_color(self.state_ptr.get(),
                                               index as c_int,
                                               &mut ffi_color);
        }
        ColorRGB {
            red: ffi_color.red,
            green: ffi_color.green,
            blue: ffi_color.blue,
        }
    }

    pub fn state_get_palette_color_from_rgb(&self, target: &ColorRGB) -> usize {
        for i in 0..256 {
            let color = self.state_get_rgb_color_from_palette(i);
            if color.red == target.red && color.green == target.green && color.blue == target.blue {
                return i as usize;
            }
        }
        0
    }

    /// move this to ffi classes since it deals with the ffi color type
    pub fn state_get_palette_color_from_c_rgb(&self, target: &ffi::VTermColor) -> usize {
        for i in 0..256 {
            let color = self.state_get_rgb_color_from_palette(i);
            if color.red == target.red && color.green == target.green && color.blue == target.blue {
                return i as usize;
            }
        }
        0
    }

    pub fn state_reset(&mut self, hard: bool) {
        unsafe {
            ffi::vterm_state_reset(self.state_ptr.get_mut(), ::bool_to_int(hard));
        }
    }

    pub fn state_receive_events(&mut self, config: &StateCallbacksConfig) {
        let mut callbacks: ffi::VTermStateCallbacks = Default::default();

        // Note: Some of these seem to be required or libvterm will segfault
        callbacks.put_glyph = if config.put_glyph { Some(::state_callbacks::put_glyph) } else { None };
        callbacks.move_cursor = if config.move_cursor { Some(::state_callbacks::move_cursor) } else { None };
        callbacks.scroll_rect = if config.scroll_rect { Some(::state_callbacks::scroll_rect) } else { None };
        callbacks.move_rect = if config.move_rect { Some(::state_callbacks::move_rect) } else { None };
        callbacks.erase = if config.erase { Some(::state_callbacks::erase) } else { None };
        callbacks.init_pen = if config.init_pen { Some(::state_callbacks::init_pen) } else { None };
        callbacks.set_pen_attr = if config.set_pen_attr { Some(::state_callbacks::set_pen_attr) } else { None };
        callbacks.set_term_prop = if config.set_term_prop { Some(::state_callbacks::set_term_prop) } else { None };
        callbacks.bell = if config.bell { Some(::state_callbacks::bell) } else { None };
        callbacks.resize = if config.resize { Some(::state_callbacks::resize) } else { None };
        callbacks.set_line_info = if config.set_line_info { Some(::state_callbacks::set_line_info) } else { None };

        self.state_callbacks = Some(callbacks);

        if self.state_event_tx.is_none() {
            let (tx, rx) = mpsc::channel();
            self.state_event_tx = Some(tx);
            self.state_event_rx = Some(rx);
        }

        unsafe {
            let self_ptr: *mut c_void = self as *mut _ as *mut c_void;
            ffi::vterm_state_set_callbacks(self.state_ptr.get_mut(),
                                            self.state_callbacks.as_ref().unwrap(),
                                            self_ptr);
        }
    }
}

mod tests {
    #![allow(unused_imports)]
    use super::super::*;
    use std::io::prelude::*;

    #[test]
    fn state_can_get_and_set_default_colors() {
        let mut vterm: VTerm = VTerm::new(&Size {
            height: 2,
            width: 2,
        });
        vterm.state_set_default_colors(&ColorRGB {
                                           red: 200,
                                           green: 201,
                                           blue: 202,
                                       },
                                       &ColorRGB {
                                           red: 0,
                                           green: 1,
                                           blue: 2,
                                       });
        let (fg_rgb, bg_rgb) = vterm.state_get_default_colors();

        assert_eq!(fg_rgb.red, 200);
        assert_eq!(fg_rgb.green, 201);
        assert_eq!(fg_rgb.blue, 202);

        assert_eq!(bg_rgb.red, 0);
        assert_eq!(bg_rgb.green, 1);
        assert_eq!(bg_rgb.blue, 2);
    }
}
<|endoftext|>


<commit_before>use std::char;
use std::collections::HashMap;
use std::convert::AsRef;
use std::fs::File;
use std::io;
use std::io::BufReader;
use std::io::BufRead;
use std::io::Result;
use std::path::Path;
use std::vec::Vec;

use state::Direction::*;
use util;

extern crate rand;

// Location represents a specific place in the execution space
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Location {
    x: usize,
    y: usize,
}

impl Location {
    //step takes the location and moves in given a direction
    pub fn step(&self, direction: Direction) -> Location {
        let y = match direction {
            Up => self.y.wrapping_sub(1),
            Down => self.y.wrapping_add(1),
            _ => self.y,
        };

        let x = match direction {
            Right => self.x.wrapping_add(1),
            Left => self.x.wrapping_sub(1),
            _ => self.x,
        };

        Location { x: x, y: y }
    }

    //step_mut destructively moves this location in the given direction
    pub fn step_mut(&mut self, direction: Direction) -> Location {
        let next = self.step(direction);
        self.x = next.x;
        self.y = next.y;
        *self

    }

    // new creates a new Location object
    pub fn new(x: usize, y: usize) -> Location {
        Location { x: x, y: y }
    }
}

// Direction represents a specific direction for the interpreter to go
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl Direction {
    pub fn opposite(&self) -> Direction {
        match *self {
            Up => Down,
            Left => Right,
            Right => Left,
            Down => Up,
        }
    }

}

impl Default for Direction {
    fn default() -> Direction {
        Direction::Right
    }
}

impl rand::Rand for Direction {
    fn rand<R: rand::Rng>(rng: &mut R) -> Self {
        let choices = [Up, Down, Left, Right];
        rng.choose(&choices).unwrap().clone()

    }
}
// The current execution mode of this InterpreterState
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Mode {
    Normal, // This intepreter is in the middle of normal execution
    Exited, // This interpreter has reached a terminus for execution
    Quoted, // This interpreter is reading a quoted string
}

impl Default for Mode {
    fn default() -> Mode {
        Mode::Normal
    }
}

// A covenience wrapper around a Vec to produce a stack
#[derive(Default)]
struct Stack {
    stack: Vec<i64>,
}

impl Stack {
    // pop gets the top-most value from the stack, or 0
    pub fn pop(&mut self) -> i64 {
        self.stack.pop().unwrap_or(0)
    }

    // push adds a new number to the top of the stack
    pub fn push(&mut self, item: i64) {
        self.stack.push(item);
    }

    // duplicate_top takes the top most item on the stack (or 0) or pushes it on the stack
    pub fn duplicate_top(&mut self) {
        let value = self.pop();
        self.push(value);
        self.push(value);
    }

    // swap_top takes the top two elements from the stack and reverses them
    pub fn swap_top(&mut self) {
        let a = self.pop();
        let b = self.pop();
        self.push(a);
        self.push(b);
    }
}

// State represents the current state of the map
#[derive(Default)]
pub struct State {
    initial_grid: Vec<Vec<char>>, // the state of the grid when loaded from the file
    grid_updates: HashMap<Location, char>, // any updates to the grid from runtime
    stack: Stack, // the current stack of values pushed from execution
    cursor: Location, // the instruction pointer that shows where we are in the grid
    direction: Direction, // the direction in which the cursor is moving
    execution_mode: Mode, // what execution mode is the interpreter currently in
}

impl State {
    //empty state produces a fresh, empty state object
    pub fn empty_state() -> State {
        Default::default()
    }

    //new_from_file produces a state containing the contents of the file
    pub fn new_from_file<P: AsRef<Path>>(path: P) -> Result<State> {
        let file = File::open(path)?;
        let buf_reader = BufReader::new(file);
        let mut state = State::empty_state();
        let mut i = 0;
        for line in buf_reader.lines() {
            let l = line.unwrap_or_default();
            let mut vec = Vec::new();
            for ch in l.chars() {
                vec.push(ch);
            }
            state.initial_grid.push(vec)
        }
        Ok(state)
    }

    // value_at - returns the value at a given location
    fn value_at(&self, loc: Location) -> Option<char> {
        if self.execution_mode == Mode::Exited {
            return None
        }

        if self.grid_updates.contains_key(&loc) {
            return Some(self.grid_updates[&loc]);
        }
        let ydim = self.initial_grid.len();
        if ydim <= loc.y {
            return None;
        }

        let xdim = self.initial_grid[loc.y].len();
        if xdim <= loc.x {
            return None;
        }

        Some(self.initial_grid[loc.y][loc.x])
    }

    // current_value - gets the value at the current position
    fn current_value(&self) -> Option<char> {
        self.value_at(self.cursor.clone())
    }

    // set_value - sets the value at a given location
    fn set_value(&mut self, loc: Location, ch: char) {
        self.grid_updates.insert(loc, ch);
    }

    // increment_cursor moves our cursor to the next position - does not wrap
    fn increment_cursor(&mut self) -> Location {
        self.cursor.step_mut(self.direction)
    }

    // run evaluates the befunge program to completion
    pub fn run(&mut self) {
        while let Some(ch) = self.next_instruction() {
            match self.execution_mode {
                Mode::Normal => self.process_normal(ch),
                Mode::Quoted => self.process_quoted(ch),
                _ => panic!("Unknown State!")
            };
           self.increment_cursor();

        }
    }

    // next_instruction retrieves the next instruction from the program
    fn next_instruction(&mut self) -> Option<char> {
        if self.execution_mode == Mode::Exited {
            return None;
        }

        let start = self.cursor;
        let mut value = self.current_value();
        while value.is_none() {
            if start == self.cursor {
                self.execution_mode = Mode::Exited;
                return None;
            }
            self.increment_cursor();
            value = self.current_value();
        }

        value.clone()
    }

    // process_quoted reads the current character and pushes it onto the stack if needed
    fn process_quoted(&mut self, ch: char) {
        if ch == '"' {
            self.execution_mode = Mode::Normal;
            return;
        }
        self.stack.push(util::char_to_i64(ch));
    }

    // process_normal reads the current character and process it according to normal rules
    fn process_normal(&mut self, ch: char) {
        match ch {
            // push digits to the stack
            '0'...'9' | 'a'...'f' => push_digit(self, ch),

            // modal operators
            '"' => self.execution_mode = Mode::Quoted,
            '#' => {self.increment_cursor();},

            // arithmetic operators
            '+' => addition(self),
            '-' => subtraction(self),
            '*' => multiply(self),
            '/' => divide(self),
            '%' => modulo(self),

            // logical operators
            '!' => logical_negation(self),
            '`' => greater_than(self),

            // directional operations
            '>' => self.direction = Right,
            '<' => self.direction = Left,
            '^' => self.direction = Up,
            'v' => self.direction = Down,
            '?' => self.direction = rand::random::<Direction>(),

            // branching operators
            '|' => veritical_if(self),
            '_' => horizontal_if(self),

            // stack manipulation operators
            '$' => {self.stack.pop();},
            ':' => self.stack.duplicate_top(),
            '\\' => self.stack.swap_top(),

            // input operators
            '&' => read_integer(self),
            '~' => read_char(self),

            // output operators
            '.' => print_digit(self),
            ',' => print_char(self),

            // load/store operations
            'p' => put(self),
            'g' => get(self),

            // end the program
            '@' => end_program(self),
            _ => (),
        };

    }
}

// read_char reads a character from the user
fn read_char(state : &mut State) {
    let mut input = String::new();
    let mut ch : char = 0 as char;
    if let Ok(_) = io::stdin().read_line(&mut input) {
        if let Some(c) = input.chars().next(){
            ch = c;
        }
    }
    state.stack.push(util::char_to_i64(ch));
}

// read_integer reads a number from the commandline
fn read_integer(state : &mut State) {
    let mut input = String::new();
    if let Ok(_) = io::stdin().read_line(&mut input) {
        if let Ok(value) = input.trim().parse::<i64>() {
            state.stack.push(value);
            return;
        }
    }
    state.stack.push(0);
}

// put pops the values y, x, and v and stores value v at location {x,y}
fn put(state: &mut State) {
    let y = state.stack.pop();
    let x = state.stack.pop();
    let v = state.stack.pop();
    state.set_value(Location{x : x as usize, y : y as usize }, util::i64_to_char(v));
}

// get puts the value at {x, y} onto the stack
fn get(state: &mut State) {
    let y = state.stack.pop();
    let x = state.stack.pop();
    let v = util::char_to_i64(state.value_at(Location{x : x as usize, y : y as usize}).unwrap_or(0 as char));
    state.stack.push(v);
}

// greater_than tests if b > a
fn greater_than(state : &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    let mut result = 0;
    if b > a {
        result = 1;
    }
    state.stack.push(result);
}

// logical_negation tests if the top most value is 0
fn logical_negation(state : &mut State) {
    let mut negation = 0;
    if state.stack.pop() == 0 {
        negation = 1;
    }
    state.stack.push(negation);
}

// print_digit prints a number from the stack
fn print_digit(state: &mut State) {
    print!("{}", state.stack.pop());
}

// print_char prints the top value on the stack as a char
fn print_char(state: &mut State) {
    print!("{}", util::i64_to_char(state.stack.pop()));
}

// push_digit takes a character and pushs it onto the stack as a digit
fn push_digit(state: &mut State, ch: char) {
    if let Some(v) = ch.to_digit(16) {
        state.stack.push(v as i64);
    }
}

// addition performs addition on the two top values from the stack
fn addition(state: &mut State) {
    let sum = state.stack.pop() + state.stack.pop();
    state.stack.push(sum);
}

// subtraction performs b - a where a is popped from the stack before b
fn subtraction(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b - a);
}

// multiply performs a * b by popping two values from the stack
fn multiply(state: &mut State) {
    let product = state.stack.pop() * state.stack.pop();
    state.stack.push(product);
}

// divide performs b / a => does NOT user prompt
fn divide(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b / a);
}

// modulo performs b % a
fn modulo(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b % a);
}

// end_program sets the program to a terminated state
fn end_program(state: &mut State) {
    state.execution_mode = Mode::Exited;
}

// horizontal_if calculates a vertical branch
fn horizontal_if(state: &mut State) {
    state.direction = Left;
    if state.stack.pop() == 0 {
        state.direction = Right;
    }
}

// veritical_if calculates a horizontal branch
fn veritical_if(state: &mut State) {
    state.direction = Up;
    if state.stack.pop() == 0 {
        state.direction = Down;
    }
}
<commit_msg>Removing a bunch of dead code<commit_after>use std::char;
use std::collections::HashMap;
use std::convert::AsRef;
use std::fs::File;
use std::io;
use std::io::BufReader;
use std::io::BufRead;
use std::io::Result;
use std::path::Path;
use std::vec::Vec;

use state::Direction::*;
use util;

extern crate rand;

// Location represents a specific place in the execution space
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Location {
    x: usize,
    y: usize,
}

impl Location {
    //step takes the location and moves in given a direction
    pub fn step(&self, direction: Direction) -> Location {
        let y = match direction {
            Up => self.y.wrapping_sub(1),
            Down => self.y.wrapping_add(1),
            _ => self.y,
        };

        let x = match direction {
            Right => self.x.wrapping_add(1),
            Left => self.x.wrapping_sub(1),
            _ => self.x,
        };

        Location { x: x, y: y }
    }

    //step_mut destructively moves this location in the given direction
    pub fn step_mut(&mut self, direction: Direction) -> Location {
        let next = self.step(direction);
        self.x = next.x;
        self.y = next.y;
        *self

    }
}

// Direction represents a specific direction for the interpreter to go
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl Direction {
    pub fn opposite(&self) -> Direction {
        match *self {
            Up => Down,
            Left => Right,
            Right => Left,
            Down => Up,
        }
    }

}

impl Default for Direction {
    fn default() -> Direction {
        Direction::Right
    }
}

impl rand::Rand for Direction {
    fn rand<R: rand::Rng>(rng: &mut R) -> Self {
        let choices = [Up, Down, Left, Right];
        rng.choose(&choices).unwrap().clone()

    }
}
// The current execution mode of this InterpreterState
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Mode {
    Normal, // This intepreter is in the middle of normal execution
    Exited, // This interpreter has reached a terminus for execution
    Quoted, // This interpreter is reading a quoted string
}

impl Default for Mode {
    fn default() -> Mode {
        Mode::Normal
    }
}

// A covenience wrapper around a Vec to produce a stack
#[derive(Default)]
struct Stack {
    stack: Vec<i64>,
}

impl Stack {
    // pop gets the top-most value from the stack, or 0
    pub fn pop(&mut self) -> i64 {
        self.stack.pop().unwrap_or(0)
    }

    // push adds a new number to the top of the stack
    pub fn push(&mut self, item: i64) {
        self.stack.push(item);
    }

    // duplicate_top takes the top most item on the stack (or 0) or pushes it on the stack
    pub fn duplicate_top(&mut self) {
        let value = self.pop();
        self.push(value);
        self.push(value);
    }

    // swap_top takes the top two elements from the stack and reverses them
    pub fn swap_top(&mut self) {
        let a = self.pop();
        let b = self.pop();
        self.push(a);
        self.push(b);
    }
}

// State represents the current state of the map
#[derive(Default)]
pub struct State {
    initial_grid: Vec<Vec<char>>, // the state of the grid when loaded from the file
    grid_updates: HashMap<Location, char>, // any updates to the grid from runtime
    stack: Stack, // the current stack of values pushed from execution
    cursor: Location, // the instruction pointer that shows where we are in the grid
    direction: Direction, // the direction in which the cursor is moving
    execution_mode: Mode, // what execution mode is the interpreter currently in
}

impl State {
    //empty state produces a fresh, empty state object
    pub fn empty_state() -> State {
        Default::default()
    }

    //new_from_file produces a state containing the contents of the file
    pub fn new_from_file<P: AsRef<Path>>(path: P) -> Result<State> {
        let file = File::open(path)?;
        let buf_reader = BufReader::new(file);
        let mut state = State::empty_state();
        for line in buf_reader.lines() {
            let l = line.unwrap_or_default();
            let mut vec = Vec::new();
            for ch in l.chars() {
                vec.push(ch);
            }
            state.initial_grid.push(vec)
        }
        Ok(state)
    }

    // value_at - returns the value at a given location
    fn value_at(&self, loc: Location) -> Option<char> {
        if self.execution_mode == Mode::Exited {
            return None
        }

        if self.grid_updates.contains_key(&loc) {
            return Some(self.grid_updates[&loc]);
        }
        let ydim = self.initial_grid.len();
        if ydim <= loc.y {
            return None;
        }

        let xdim = self.initial_grid[loc.y].len();
        if xdim <= loc.x {
            return None;
        }

        Some(self.initial_grid[loc.y][loc.x])
    }

    // current_value - gets the value at the current position
    fn current_value(&self) -> Option<char> {
        self.value_at(self.cursor.clone())
    }

    // set_value - sets the value at a given location
    fn set_value(&mut self, loc: Location, ch: char) {
        self.grid_updates.insert(loc, ch);
    }

    // increment_cursor moves our cursor to the next position - does not wrap
    fn increment_cursor(&mut self) -> Location {
        self.cursor.step_mut(self.direction)
    }

    // run evaluates the befunge program to completion
    pub fn run(&mut self) {
        while let Some(ch) = self.next_instruction() {
            match self.execution_mode {
                Mode::Normal => self.process_normal(ch),
                Mode::Quoted => self.process_quoted(ch),
                _ => panic!("Unknown State!")
            };
           self.increment_cursor();

        }
    }

    // next_instruction retrieves the next instruction from the program
    fn next_instruction(&mut self) -> Option<char> {
        if self.execution_mode == Mode::Exited {
            return None;
        }

        let start = self.cursor;
        let mut value = self.current_value();
        while value.is_none() {
            if start == self.cursor {
                self.execution_mode = Mode::Exited;
                return None;
            }
            self.increment_cursor();
            value = self.current_value();
        }

        value.clone()
    }

    // process_quoted reads the current character and pushes it onto the stack if needed
    fn process_quoted(&mut self, ch: char) {
        if ch == '"' {
            self.execution_mode = Mode::Normal;
            return;
        }
        self.stack.push(util::char_to_i64(ch));
    }

    // process_normal reads the current character and process it according to normal rules
    fn process_normal(&mut self, ch: char) {
        match ch {
            // push digits to the stack
            '0'...'9' | 'a'...'f' => push_digit(self, ch),

            // modal operators
            '"' => self.execution_mode = Mode::Quoted,
            '#' => {self.increment_cursor();},

            // arithmetic operators
            '+' => addition(self),
            '-' => subtraction(self),
            '*' => multiply(self),
            '/' => divide(self),
            '%' => modulo(self),

            // logical operators
            '!' => logical_negation(self),
            '`' => greater_than(self),

            // directional operations
            '>' => self.direction = Right,
            '<' => self.direction = Left,
            '^' => self.direction = Up,
            'v' => self.direction = Down,
            '?' => self.direction = rand::random::<Direction>(),

            // branching operators
            '|' => veritical_if(self),
            '_' => horizontal_if(self),

            // stack manipulation operators
            '$' => {self.stack.pop();},
            ':' => self.stack.duplicate_top(),
            '\\' => self.stack.swap_top(),

            // input operators
            '&' => read_integer(self),
            '~' => read_char(self),

            // output operators
            '.' => print_digit(self),
            ',' => print_char(self),

            // load/store operations
            'p' => put(self),
            'g' => get(self),

            // end the program
            '@' => end_program(self),
            _ => (),
        };

    }
}

// read_char reads a character from the user
fn read_char(state : &mut State) {
    let mut input = String::new();
    let mut ch : char = 0 as char;
    if let Ok(_) = io::stdin().read_line(&mut input) {
        if let Some(c) = input.chars().next(){
            ch = c;
        }
    }
    state.stack.push(util::char_to_i64(ch));
}

// read_integer reads a number from the commandline
fn read_integer(state : &mut State) {
    let mut input = String::new();
    if let Ok(_) = io::stdin().read_line(&mut input) {
        if let Ok(value) = input.trim().parse::<i64>() {
            state.stack.push(value);
            return;
        }
    }
    state.stack.push(0);
}

// put pops the values y, x, and v and stores value v at location {x,y}
fn put(state: &mut State) {
    let y = state.stack.pop();
    let x = state.stack.pop();
    let v = state.stack.pop();
    state.set_value(Location{x : x as usize, y : y as usize }, util::i64_to_char(v));
}

// get puts the value at {x, y} onto the stack
fn get(state: &mut State) {
    let y = state.stack.pop();
    let x = state.stack.pop();
    let v = util::char_to_i64(state.value_at(Location{x : x as usize, y : y as usize}).unwrap_or(0 as char));
    state.stack.push(v);
}

// greater_than tests if b > a
fn greater_than(state : &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    let mut result = 0;
    if b > a {
        result = 1;
    }
    state.stack.push(result);
}

// logical_negation tests if the top most value is 0
fn logical_negation(state : &mut State) {
    let mut negation = 0;
    if state.stack.pop() == 0 {
        negation = 1;
    }
    state.stack.push(negation);
}

// print_digit prints a number from the stack
fn print_digit(state: &mut State) {
    print!("{}", state.stack.pop());
}

// print_char prints the top value on the stack as a char
fn print_char(state: &mut State) {
    print!("{}", util::i64_to_char(state.stack.pop()));
}

// push_digit takes a character and pushs it onto the stack as a digit
fn push_digit(state: &mut State, ch: char) {
    if let Some(v) = ch.to_digit(16) {
        state.stack.push(v as i64);
    }
}

// addition performs addition on the two top values from the stack
fn addition(state: &mut State) {
    let sum = state.stack.pop() + state.stack.pop();
    state.stack.push(sum);
}

// subtraction performs b - a where a is popped from the stack before b
fn subtraction(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b - a);
}

// multiply performs a * b by popping two values from the stack
fn multiply(state: &mut State) {
    let product = state.stack.pop() * state.stack.pop();
    state.stack.push(product);
}

// divide performs b / a => does NOT user prompt
fn divide(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b / a);
}

// modulo performs b % a
fn modulo(state: &mut State) {
    let a = state.stack.pop();
    let b = state.stack.pop();
    state.stack.push(b % a);
}

// end_program sets the program to a terminated state
fn end_program(state: &mut State) {
    state.execution_mode = Mode::Exited;
}

// horizontal_if calculates a vertical branch
fn horizontal_if(state: &mut State) {
    state.direction = Left;
    if state.stack.pop() == 0 {
        state.direction = Right;
    }
}

// veritical_if calculates a horizontal branch
fn veritical_if(state: &mut State) {
    state.direction = Up;
    if state.stack.pop() == 0 {
        state.direction = Down;
    }
}
<|endoftext|>


<commit_before>use super::Checked;

macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
        }
    };
}

macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
        }
    };
}

test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
// Strictly speaking the macro requires all the ints to be the same type
test_binop! (shl u32: 10 << 3 == 80);
test_binop! (shr u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));
<commit_msg>Add tests for operations with references<commit_after>use super::Checked;

macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
            assert_eq!($op &x, y);
        }
    };
}

macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };
}

test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
// Strictly speaking the macro requires all the ints to be the same type, so we have to use u32.
test_binop! (shl u32: 10 << 3 == 80);
test_binop! (shr u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));
<|endoftext|>