<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 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 { stacks: vec![Stack::<T>::new()] /* there is always at least one stack */ }
    }

    pub fn push_stack(&mut self, moved_items: usize) -> Result<(), Error> {
        let vals: Vec<_> = {
            let stack = self.top();
            match stack.len().checked_sub(moved_items) {
                Some(v) => stack.values.split_off(v),
                None => return Err(Error::StackUnderflow),
            }
        };

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

        Ok(())
    }

    pub fn pop_stack(&mut self) {
        if self.stacks.len() > 1 {
            let v = self.stacks.pop().unwrap().values;
            self.top().values.extend(v);
        } else {
            let s = self.top();
            s.values.clear();
            s.register = None;
        }
    }

    pub fn top(&mut self) -> &mut Stack<T> {
        debug_assert!(!self.stacks.is_empty());
        self.stacks.last_mut().unwrap()
    }
}

#[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.stacks.len(), 1);
            assert_eq!(s.stacks[0].len(), 0);
            assert_eq!(s.stacks[0].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.stacks.len(), 2);
            assert_eq!(s.stacks[0].values, vec![5]);
            assert_eq!(s.stacks[1].values, vec![42, 58]);
            assert_eq!(s.stacks[1].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.stacks.len(), 2);
            assert_eq!(s.stacks[0].values, vec![0; 0]);
            assert_eq!(s.stacks[1].values, vec![5, 42, 58]);
            assert_eq!(s.stacks[1].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.stacks.len(), 2);
            assert_eq!(s.stacks[0].values, vec![5, 42, 58]);
            assert_eq!(s.stacks[1].values, vec![0; 0]);
            assert_eq!(s.stacks[1].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.stacks.len(), 1);
            assert_eq!(s.stacks[0].values, vec![5, 42, 58]);
            assert_eq!(s.stacks[0].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.stacks.len(), 1);
            assert_eq!(s.stacks[0].values, vec![5, 42]);
            assert_eq!(s.stacks[0].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.stacks.len(), 1);
            assert_eq!(s.stacks[0].values, vec![5, 42]);
            assert_eq!(s.stacks[0].register, None);
        }

        #[test]
        fn pop_last_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.stacks.len(), 1);
            assert_eq!(s.stacks[0].values, vec![0; 0]);
            assert_eq!(s.stacks[0].register, None);
        }
    }
}
<commit_msg>Refactor StackOfStacks<commit_after>#[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);
        }
    }
}
<|endoftext|>


<commit_before>use crate::config::Config;
use crate::stack::Stack;
use crate::workspace::{Workspace, WorkspaceConfig};
use crate::xlib_window_system::XlibWindowSystem;
use crate::layout::Rect;
use crate::ewmh;
use std::cmp;
use std::fs::{File, remove_file};
use std::path::Path;
use std::default::Default;
use serde::{Serialize, Deserialize};
use x11::xlib::Window;
use anyhow::{Context, Result};

#[derive(Serialize, Deserialize)]
pub struct WmState {
    workspaces: Vec<Workspace>,
    struts: Vec<Window>,
    cur: usize,
    screens: Vec<Rect>
}

impl WmState {
    pub fn new(ws_cfg_list: Vec<WorkspaceConfig>, xws: &XlibWindowSystem) -> Result<WmState> {
        let state_file_path = Path::new(&Config::get_dir()?).join(".state.tmp");
        if state_file_path.exists() {
            match WmState::from_file(state_file_path) {
                Ok(state) => {
                    state.all_ws().iter().for_each(|workspace| {
                        workspace.all().iter().for_each(|&window| {
                            xws.request_window_events(window);
                        })
                    });

                    return Ok(state);
                },
                Err(e) => error!("failed to restore previous state: {}", e)
            }
        }

        debug!("creating default WmState");
        Ok(WmState {
            workspaces: ws_cfg_list
                .into_iter()
                .enumerate()
                .map(|(idx,c)| {
                    Workspace {
                        tag: c.tag.clone(),
                        screen: c.screen,
                        managed: Stack::new(Some(c.layout)),
                        focus: idx == 0,
                        ..Default::default()
                    }
                })
                .collect(),
            struts: Vec::new(),
            cur: 0,
            screens: Vec::new(),
        })
    }

    fn from_file<P: AsRef<Path>>(path: P) -> Result<WmState> {
        let file = File::open(&path)
            .context("failed to open wm state serialization file")?;

        debug!("loading previous wm state");
        let ws: WmState = serde_json::from_reader(file)
            .context("failed to deserialize wm state")?;

        remove_file(path).ok();

        Ok(ws)
    }

    pub fn get_ws(&self, index: usize) -> Option<&Workspace> {
        self.workspaces.get(index)
    }

    pub fn get_ws_mut(&mut self, index: usize) -> Option<&mut Workspace> {
        self.workspaces.get_mut(index)
    }

    pub fn current_ws(&self) -> &Workspace {
        self.workspaces.get(self.cur).unwrap()
    }

    pub fn current_ws_mut(&mut self) -> &mut Workspace {
        self.workspaces.get_mut(self.cur).unwrap()
    }

    pub fn all_ws(&self) -> &Vec<Workspace> {
        &self.workspaces
    }

    pub fn all_visible_ws(&self) -> Vec<&Workspace> {
        self.workspaces
            .iter()
            .filter(|ws| ws.is_visible())
            .collect()
    }

    pub fn get_ws_index(&self) -> usize {
        self.cur
    }

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

    pub fn get_screens(&self) -> &Vec<Rect> {
        &self.screens
    }

    pub fn contains(&self, window: Window) -> bool {
        self.workspaces.iter().any(|ws| ws.contains(window))
    }

    pub fn is_unmanaged(&self, window: Window) -> bool {
        self.workspaces.iter().any(|ws| ws.is_unmanaged(window))
    }

    pub fn add_window(&mut self, index: Option<usize>, xws: &XlibWindowSystem, config: &Config, window: Window) {
        if !self.contains(window) {
            let screens = self.screens.clone();

            let parent = xws.transient_for(window)
                .and_then(|x| self.find_window(x));

            let workspace = parent
                .or_else(|| index.or_else(|| Some(self.get_ws_index())))
                .and_then(|idx| self.get_ws_mut(idx))
                .expect("valid workspace");

            workspace.add_window(xws, window);

            if parent.is_some() {
                workspace.focus_window(xws, window);
            }

            if !workspace.is_visible() {
                workspace.set_urgency(true, window);
            } else {
                workspace.redraw(xws, config, &screens);
                xws.show_window(window);
            }

            ewmh::set_client_list(xws, &self.workspaces);
        }
    }

    pub fn focus_window(&mut self, xws: &XlibWindowSystem, config: &Config, window: Window) {
        if xws.get_wm_hints(window).map(|x| x.input != 0).unwrap_or(true) {
            if let Some(index) = self.find_window(window) {
                if self.cur != index {
                    let workspace = self.get_ws_mut(index)
                        .expect("valid workspace");

                    workspace.focus_window(xws, window);

                    if workspace.is_visible() {
                        self.switch_to_ws(xws, config, index, false);
                    }
                } else {
                    self.current_ws_mut().focus_window(xws, window);
                }
            }
        }
    }

    pub fn switch_to_ws(&mut self, xws: &XlibWindowSystem, config: &Config, index: usize, center_pointer: bool) {
        if self.cur == index || index >= self.workspaces.len() {
            return
        }

        // implies that the target workspace is on another screen
        if self.workspaces[index].visible {
            if config.greedy_view {
                self.switch_screens(xws, index);
                self.workspaces[self.cur].redraw(xws, config, &self.screens);
                self.workspaces[self.cur].show(xws);
            } else if center_pointer {
                self.workspaces[index].center_pointer(xws);
            }
        } else {
            self.workspaces[index].screen = self.workspaces[self.cur].screen;
            self.workspaces[index].redraw(xws, config, &self.screens);
            self.workspaces[index].show(xws);
            self.workspaces[self.cur].hide(xws);
        }

        self.workspaces[self.cur].unfocus(xws, config);
        self.workspaces[index].focus(xws);

        self.cur = index;

        ewmh::set_current_desktop(xws, index);
        ewmh::set_desktop_viewport(xws, self.all_ws());
    }

    pub fn switch_to_ws_at(&mut self, xws: &XlibWindowSystem, config: &Config, x: u32, y: u32, center_pointer: bool) {
        let ws_idx = self.workspaces
            .iter()
            .enumerate()
            .find(|(_,ws)| {
                let screen = self.screens[ws.get_screen()];
                x >= screen.x && x < screen.x + screen.width &&
                y >= screen.y && y < screen.y + screen.height &&
                ws.is_visible()
            })
            .map(|(idx,_)| idx);

        if let Some(idx) = ws_idx {
            self.switch_to_ws(xws, config, idx, center_pointer);
        }
    }

    pub fn switch_to_screen(&mut self, xws: &XlibWindowSystem, config: &Config, screen: usize) {
        if screen > self.screens.len() - 1 {
            return;
        }

        let idx_workspace = self.workspaces.iter()
            .enumerate()
            .filter(|&(i, workspace)| workspace.screen == screen && workspace.visible && i != self.cur)
            .map(|(i, _)| i)
            .last();

        if let Some(index) = idx_workspace {
            self.workspaces[self.cur].unfocus(xws, config);
            self.workspaces[index].focus(xws);

            self.workspaces[index].center_pointer(xws);
            self.cur = index;

            ewmh::set_current_desktop(xws, index);
        }
    }

    pub fn move_window_to_ws(&mut self, xws: &XlibWindowSystem, config: &Config, index: usize) {
        if index == self.cur || index >= self.ws_count() {
            return;
        }

        if let Some(window) = self.current_ws().focused_window() {
            self.remove_window(xws, config, window);

            let ws = &mut self.workspaces[index];
            ws.add_window(xws, window);
            ws.focus_window(xws, window);
            ws.redraw(xws, config, &self.screens);
        }

    }

    pub fn move_window_to_screen(&mut self, xws: &XlibWindowSystem, config: &Config, screen: usize) {
        if let Some((index,_)) = self.all_ws()
            .iter()
            .enumerate()
            .find(|&(_, ws)| ws.is_visible() && ws.screen == screen)
        {
            self.move_window_to_ws(xws, config, index);
        }
    }

    pub fn remove_window(&mut self, xws: &XlibWindowSystem, config: &Config, window: Window) {
        let screens = self.screens.clone();

        if let Some(workspace) = self.get_parent_mut(window) {
            workspace.remove_window(xws, window);

            if workspace.is_visible() {
                workspace.redraw(xws, config, &screens);
            }

            ewmh::set_client_list(xws, &self.workspaces);
        }
    }
/*
    pub fn hide_window(&mut self, window: Window) {
        if let Some(idx) = self.find_window(window) {
            self.list.get_mut(idx)
                .expect("valid workspace")
                .hide_window(window);
        }
    }
*/
    pub fn rescreen(&mut self, xws: &XlibWindowSystem, config: &Config) {
        let n_old_screens = self.screens.len();

        let screens = xws.get_screen_infos();
        trace!("xinerama screens: {:?}", screens);

        let mut new_screens: Vec<Rect> = Vec::new();

        for screen in screens {
            if let Some(old_screen) = new_screens.iter_mut()
                .find(|s| s.x == screen.x && s.y == screen.y)
            {
                    old_screen.width = cmp::min(old_screen.width, screen.width);
                    old_screen.height = cmp::min(old_screen.height, screen.height)
            } else {
                new_screens.push(screen);
            }
        }

        let n_new_screens = new_screens.len();

        // move and hide workspaces if their screens got removed
        if n_new_screens < n_old_screens {
            for workspace in self.workspaces.iter_mut().filter(|x| x.screen > n_new_screens - 1) {
                workspace.screen = 0;
                workspace.hide(xws);
            }
        } else {
            trace!("finding workspace to rescreen");
            // assign the first hidden workspace to the new screen
            for screen in n_old_screens..n_new_screens {
                trace!("rescreen for screen {}", screen);
                if let Some(workspace) = self.workspaces.iter_mut().find(|ws| !ws.is_visible()) {
                    trace!("moving workspace {}", workspace.tag);
                    workspace.screen = screen;
                    workspace.redraw(xws, config, &new_screens);
                    workspace.show(xws);
                }
            }
        }

        self.screens = new_screens;
        debug!("rescreen: {:?}", self.screens);

        ewmh::set_desktop_viewport(xws, self.all_ws());
    }

    pub fn find_window(&self, window: Window) -> Option<usize> {
        self.workspaces.iter().enumerate().find(|(_, workspace)| workspace.contains(window)).map(|(idx, _)| idx)
    }

    pub fn get_parent_mut(&mut self, window: Window) -> Option<&mut Workspace> {
        self.workspaces.iter_mut().find(|workspace| workspace.contains(window))
    }

    fn switch_screens(&mut self, xws: &XlibWindowSystem, dest: usize) {
        let screen = self.current_ws().get_screen();
        self.workspaces[self.cur].screen = self.workspaces[dest].screen;
        self.workspaces[dest].screen = screen;

        ewmh::set_desktop_viewport(xws, self.all_ws());
    }

    pub fn redraw(&self, xws: &XlibWindowSystem, config: &Config) {
        self.all_visible_ws()
            .iter()
            .for_each(|ws| {
                ws.redraw(xws, config, &self.screens);
            });

    }

    pub fn add_strut(&mut self, window: Window) {
        if !self.struts.contains(&window) {
            self.struts.push(window);
        }
    }

    pub fn try_remove_strut(&mut self, window: Window) -> bool {
        if let Some((idx,_)) = self.struts.iter()
            .enumerate()
            .find(|(_,&x)| x == window)
        {
            self.struts.swap_remove(idx);
            true
        } else {
            false
        }
    }
}
<commit_msg>Fix incorrect input focus after window deletion<commit_after>use crate::config::Config;
use crate::stack::Stack;
use crate::workspace::{Workspace, WorkspaceConfig};
use crate::xlib_window_system::XlibWindowSystem;
use crate::layout::Rect;
use crate::ewmh;
use std::cmp;
use std::fs::{File, remove_file};
use std::path::Path;
use std::default::Default;
use serde::{Serialize, Deserialize};
use x11::xlib::Window;
use anyhow::{Context, Result};

#[derive(Serialize, Deserialize)]
pub struct WmState {
    workspaces: Vec<Workspace>,
    struts: Vec<Window>,
    cur: usize,
    screens: Vec<Rect>
}

impl WmState {
    pub fn new(ws_cfg_list: Vec<WorkspaceConfig>, xws: &XlibWindowSystem) -> Result<WmState> {
        let state_file_path = Path::new(&Config::get_dir()?).join(".state.tmp");
        if state_file_path.exists() {
            match WmState::from_file(state_file_path) {
                Ok(state) => {
                    state.all_ws().iter().for_each(|workspace| {
                        workspace.all().iter().for_each(|&window| {
                            xws.request_window_events(window);
                        })
                    });

                    return Ok(state);
                },
                Err(e) => error!("failed to restore previous state: {}", e)
            }
        }

        debug!("creating default WmState");
        Ok(WmState {
            workspaces: ws_cfg_list
                .into_iter()
                .enumerate()
                .map(|(idx,c)| {
                    Workspace {
                        tag: c.tag.clone(),
                        screen: c.screen,
                        managed: Stack::new(Some(c.layout)),
                        focus: idx == 0,
                        ..Default::default()
                    }
                })
                .collect(),
            struts: Vec::new(),
            cur: 0,
            screens: Vec::new(),
        })
    }

    fn from_file<P: AsRef<Path>>(path: P) -> Result<WmState> {
        let file = File::open(&path)
            .context("failed to open wm state serialization file")?;

        debug!("loading previous wm state");
        let ws: WmState = serde_json::from_reader(file)
            .context("failed to deserialize wm state")?;

        remove_file(path).ok();

        Ok(ws)
    }

    pub fn get_ws(&self, index: usize) -> Option<&Workspace> {
        self.workspaces.get(index)
    }

    pub fn get_ws_mut(&mut self, index: usize) -> Option<&mut Workspace> {
        self.workspaces.get_mut(index)
    }

    pub fn current_ws(&self) -> &Workspace {
        self.workspaces.get(self.cur).unwrap()
    }

    pub fn current_ws_mut(&mut self) -> &mut Workspace {
        self.workspaces.get_mut(self.cur).unwrap()
    }

    pub fn all_ws(&self) -> &Vec<Workspace> {
        &self.workspaces
    }

    pub fn all_visible_ws(&self) -> Vec<&Workspace> {
        self.workspaces
            .iter()
            .filter(|ws| ws.is_visible())
            .collect()
    }

    pub fn get_ws_index(&self) -> usize {
        self.cur
    }

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

    pub fn get_screens(&self) -> &Vec<Rect> {
        &self.screens
    }

    pub fn contains(&self, window: Window) -> bool {
        self.workspaces.iter().any(|ws| ws.contains(window))
    }

    pub fn is_unmanaged(&self, window: Window) -> bool {
        self.workspaces.iter().any(|ws| ws.is_unmanaged(window))
    }

    pub fn add_window(&mut self, index: Option<usize>, xws: &XlibWindowSystem, config: &Config, window: Window) {
        if !self.contains(window) {
            let screens = self.screens.clone();

            let parent = xws.transient_for(window)
                .and_then(|x| self.find_window(x));

            let workspace = parent
                .or_else(|| index.or_else(|| Some(self.get_ws_index())))
                .and_then(|idx| self.get_ws_mut(idx))
                .expect("valid workspace");

            workspace.add_window(xws, window);

            if parent.is_some() {
                workspace.focus_window(xws, window);
            }

            if !workspace.is_visible() {
                workspace.set_urgency(true, window);
            } else {
                workspace.redraw(xws, config, &screens);
                xws.show_window(window);
            }

            ewmh::set_client_list(xws, &self.workspaces);
        }
    }

    pub fn focus_window(&mut self, xws: &XlibWindowSystem, config: &Config, window: Window) {
        if xws.get_wm_hints(window).map(|x| x.input != 0).unwrap_or(true) {
            if let Some(index) = self.find_window(window) {
                if self.cur != index {
                    let workspace = self.get_ws_mut(index)
                        .expect("valid workspace");

                    workspace.focus_window(xws, window);

                    if workspace.is_visible() {
                        self.switch_to_ws(xws, config, index, false);
                    }
                } else {
                    self.current_ws_mut().focus_window(xws, window);
                }
            }
        }
    }

    pub fn switch_to_ws(&mut self, xws: &XlibWindowSystem, config: &Config, index: usize, center_pointer: bool) {
        if self.cur == index || index >= self.workspaces.len() {
            return
        }

        // implies that the target workspace is on another screen
        if self.workspaces[index].visible {
            if config.greedy_view {
                self.switch_screens(xws, index);
                self.workspaces[self.cur].redraw(xws, config, &self.screens);
                self.workspaces[self.cur].show(xws);
            } else if center_pointer {
                self.workspaces[index].center_pointer(xws);
            }
        } else {
            self.workspaces[index].screen = self.workspaces[self.cur].screen;
            self.workspaces[index].redraw(xws, config, &self.screens);
            self.workspaces[index].show(xws);
            self.workspaces[self.cur].hide(xws);
        }

        self.workspaces[self.cur].unfocus(xws, config);
        self.workspaces[index].focus(xws);

        self.cur = index;

        ewmh::set_current_desktop(xws, index);
        ewmh::set_desktop_viewport(xws, self.all_ws());
    }

    pub fn switch_to_ws_at(&mut self, xws: &XlibWindowSystem, config: &Config, x: u32, y: u32, center_pointer: bool) {
        let ws_idx = self.workspaces
            .iter()
            .enumerate()
            .find(|(_,ws)| {
                let screen = self.screens[ws.get_screen()];
                x >= screen.x && x < screen.x + screen.width &&
                y >= screen.y && y < screen.y + screen.height &&
                ws.is_visible()
            })
            .map(|(idx,_)| idx);

        if let Some(idx) = ws_idx {
            self.switch_to_ws(xws, config, idx, center_pointer);
        }
    }

    pub fn switch_to_screen(&mut self, xws: &XlibWindowSystem, config: &Config, screen: usize) {
        if screen > self.screens.len() - 1 {
            return;
        }

        let idx_workspace = self.workspaces.iter()
            .enumerate()
            .filter(|&(i, workspace)| workspace.screen == screen && workspace.visible && i != self.cur)
            .map(|(i, _)| i)
            .last();

        if let Some(index) = idx_workspace {
            self.workspaces[self.cur].unfocus(xws, config);
            self.workspaces[index].focus(xws);

            self.workspaces[index].center_pointer(xws);
            self.cur = index;

            ewmh::set_current_desktop(xws, index);
        }
    }

    pub fn move_window_to_ws(&mut self, xws: &XlibWindowSystem, config: &Config, index: usize) {
        if index == self.cur || index >= self.ws_count() {
            return;
        }

        if let Some(window) = self.current_ws().focused_window() {
            self.remove_window(xws, config, window);

            let ws = &mut self.workspaces[index];
            ws.add_window(xws, window);
            ws.focus_window(xws, window);
            ws.redraw(xws, config, &self.screens);
        }

    }

    pub fn move_window_to_screen(&mut self, xws: &XlibWindowSystem, config: &Config, screen: usize) {
        if let Some((index,_)) = self.all_ws()
            .iter()
            .enumerate()
            .find(|&(_, ws)| ws.is_visible() && ws.screen == screen)
        {
            self.move_window_to_ws(xws, config, index);
        }
    }

    pub fn remove_window(&mut self, xws: &XlibWindowSystem, config: &Config, window: Window) {
        let screens = self.screens.clone();

        if let Some(workspace) = self.get_parent_mut(window) {
            workspace.remove_window(xws, window);

            if workspace.is_visible() {
                if let Some(w) = workspace.focused_window() {
                    xws.focus_window(w);
                }
                workspace.redraw(xws, config, &screens);
            }

            ewmh::set_client_list(xws, &self.workspaces);
        }
    }
/*
    pub fn hide_window(&mut self, window: Window) {
        if let Some(idx) = self.find_window(window) {
            self.list.get_mut(idx)
                .expect("valid workspace")
                .hide_window(window);
        }
    }
*/
    pub fn rescreen(&mut self, xws: &XlibWindowSystem, config: &Config) {
        let n_old_screens = self.screens.len();

        let screens = xws.get_screen_infos();
        trace!("xinerama screens: {:?}", screens);

        let mut new_screens: Vec<Rect> = Vec::new();

        for screen in screens {
            if let Some(old_screen) = new_screens.iter_mut()
                .find(|s| s.x == screen.x && s.y == screen.y)
            {
                    old_screen.width = cmp::min(old_screen.width, screen.width);
                    old_screen.height = cmp::min(old_screen.height, screen.height)
            } else {
                new_screens.push(screen);
            }
        }

        let n_new_screens = new_screens.len();

        // move and hide workspaces if their screens got removed
        if n_new_screens < n_old_screens {
            for workspace in self.workspaces.iter_mut().filter(|x| x.screen > n_new_screens - 1) {
                workspace.screen = 0;
                workspace.hide(xws);
            }
        } else {
            trace!("finding workspace to rescreen");
            // assign the first hidden workspace to the new screen
            for screen in n_old_screens..n_new_screens {
                trace!("rescreen for screen {}", screen);
                if let Some(workspace) = self.workspaces.iter_mut().find(|ws| !ws.is_visible()) {
                    trace!("moving workspace {}", workspace.tag);
                    workspace.screen = screen;
                    workspace.redraw(xws, config, &new_screens);
                    workspace.show(xws);
                }
            }
        }

        self.screens = new_screens;
        debug!("rescreen: {:?}", self.screens);

        ewmh::set_desktop_viewport(xws, self.all_ws());
    }

    pub fn find_window(&self, window: Window) -> Option<usize> {
        self.workspaces.iter().enumerate().find(|(_, workspace)| workspace.contains(window)).map(|(idx, _)| idx)
    }

    pub fn get_parent_mut(&mut self, window: Window) -> Option<&mut Workspace> {
        self.workspaces.iter_mut().find(|workspace| workspace.contains(window))
    }

    fn switch_screens(&mut self, xws: &XlibWindowSystem, dest: usize) {
        let screen = self.current_ws().get_screen();
        self.workspaces[self.cur].screen = self.workspaces[dest].screen;
        self.workspaces[dest].screen = screen;

        ewmh::set_desktop_viewport(xws, self.all_ws());
    }

    pub fn redraw(&self, xws: &XlibWindowSystem, config: &Config) {
        self.all_visible_ws()
            .iter()
            .for_each(|ws| {
                ws.redraw(xws, config, &self.screens);
            });

    }

    pub fn add_strut(&mut self, window: Window) {
        if !self.struts.contains(&window) {
            self.struts.push(window);
        }
    }

    pub fn try_remove_strut(&mut self, window: Window) -> bool {
        if let Some((idx,_)) = self.struts.iter()
            .enumerate()
            .find(|(_,&x)| x == window)
        {
            self.struts.swap_remove(idx);
            true
        } else {
            false
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use super::error::{BrokerResult, BrokerError};
use super::redis::{self, Commands};

#[derive(Clone)]
pub struct Store {
    pub client: redis::Client,
    pub expire_keys: u64, // Redis key TTL, in seconds
}

impl Store {
    pub fn new(url: &str, expire_keys: u64) -> Result<Store, &'static str> {
        let res = redis::Client::open(url);
        if res.is_err() {
            return Err("error opening store connection");
        }
        Ok(Store { client: res.unwrap(), expire_keys: expire_keys })
    }

    pub fn store_session(&self, session_id: &str, data: &[(&str, &str)])
                         -> BrokerResult<()> {
        let key = Self::format_session_key(session_id);
        try!(self.client.hset_multiple(&key, data));
        try!(self.client.expire(&key, self.expire_keys as usize));
        Ok(())
    }

    pub fn get_session(&self, session_id: &str)
                       -> BrokerResult<HashMap<String, String>> {
        let key = Self::format_session_key(session_id);
        let stored: HashMap<String, String> = try!(self.client.hgetall(&key));
        if stored.is_empty() {
            return Err(BrokerError::Custom("session not found".to_string()));
        }
        Ok(stored)
    }

    fn format_session_key(session_id: &str) -> String {
        format!("session:{}", session_id)
    }
}
<commit_msg>Wrap session save in a transaction.<commit_after>use std::collections::HashMap;
use super::error::{BrokerResult, BrokerError};
use super::redis::{self, Commands, PipelineCommands};

#[derive(Clone)]
pub struct Store {
    pub client: redis::Client,
    pub expire_keys: u64, // Redis key TTL, in seconds
}

impl Store {
    pub fn new(url: &str, expire_keys: u64) -> Result<Store, &'static str> {
        let res = redis::Client::open(url);
        if res.is_err() {
            return Err("error opening store connection");
        }
        Ok(Store { client: res.unwrap(), expire_keys: expire_keys })
    }

    pub fn store_session(&self, session_id: &str, data: &[(&str, &str)])
                         -> BrokerResult<()> {
        let key = Self::format_session_key(session_id);
        try!(redis::pipe()
                .atomic()
                .hset_multiple(&key, data).ignore()
                .expire(&key, self.expire_keys as usize).ignore()
                .query(&self.client));
        Ok(())
    }

    pub fn get_session(&self, session_id: &str)
                       -> BrokerResult<HashMap<String, String>> {
        let key = Self::format_session_key(session_id);
        let stored: HashMap<String, String> = try!(self.client.hgetall(&key));
        if stored.is_empty() {
            return Err(BrokerError::Custom("session not found".to_string()));
        }
        Ok(stored)
    }

    fn format_session_key(session_id: &str) -> String {
        format!("session:{}", session_id)
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]
#[macro_use]
extern crate clap;

extern crate svgbob;
extern crate svg;

use svgbob::Grid;
use svgbob::Settings;

use clap::ArgMatches;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::error::Error;
use std::io::Read;
use std::process::exit;

fn main() {
    use clap::{Arg, App, SubCommand};

    let args = App::new("svgbob")
        .version(crate_version!())
        .about("SvgBobRus is an ascii to svg converter")
        .arg(Arg::with_name("inline").short("s").help("parse an inline string"))
        .arg(Arg::with_name("input").index(1).help("svgbob text file or inline string to parse [default: STDIN]"))
        .arg(Arg::with_name("output")
            .short("o")
            .long("output")
            .takes_value(true)
            .help("where to write svg output [default: STDOUT]"))
        .arg(Arg::with_name("font-family")
             .long("font-family")
             .takes_value(true)
             .help("text will be rendered with this font (default: 'arial')"))
        .arg(Arg::with_name("font-size")
             .long("font-size")
             .takes_value(true)
             .help("text will be rendered with this font size (default: 14)"))
        .arg(Arg::with_name("stroke-width")
             .long("stroke-width")
             .takes_value(true)
             .help("stroke width for all lines (default: 2)"))
        .arg(Arg::with_name("scale")
             .long("scale")
             .takes_value(true)
             .help("scale the entire svg (dimensions, font size, stroke width) by this factor (default: 1)"))
        .subcommand(SubCommand::with_name("build")
            .about("Batch convert files to svg.")
            .version("0.0.1")
            .arg(Arg::with_name("input")
                .short("i")
                .long("input")
                .takes_value(true)
                .help("set input file pattern like: *.bob or dir/*.bob"))
            .arg(Arg::with_name("outdir")
                .short("o")
                .long("outdir")
                .takes_value(true)
                .help("set dir of svg files")))
        .get_matches();

    if let Some(sub_build) = args.subcommand_matches("build") {
        match build(sub_build) {
            Ok(_) => {}
            Err(e) => println!("{}", e),
        };
        exit(1);
    }

    let mut bob = String::new();

    if args.is_present("inline") {
        bob = args.value_of("input").unwrap().replace("\\n","\n").to_string();
    } else {
        if let Some(file) = args.value_of("input") {
            match File::open(file) {
                Ok(mut f) => {
                    f.read_to_string(&mut bob).unwrap();
                }
                Err(e) => {
                    use std::io::Write;
                    use std::process::exit;

                    writeln!(&mut std::io::stderr(),
                            "Failed to open input file {}: {}",
                            file,
                            e)
                        .unwrap();
                    exit(1);
                }
            }
        } else {
            use std::io;
            io::stdin().read_to_string(&mut bob).unwrap();
        }
    }

    let mut settings = Settings::compact();

    if let Some(font_family) = args.value_of("font-family") {
        settings.font_family = font_family.to_string();
    }

    if let Some(font_size) = args.value_of("font-size") {
        match font_size.parse() {
            Ok(fs) => {
                settings.font_size = fs;
            }
            Err(e) => {
                use std::io::Write;
                use std::process::exit;

                writeln!(&mut std::io::stderr(),
                         "Wrong font size: {}",
                         e)
                    .unwrap();
                exit(1);
            }
        }
    }

    if let Some(stroke_width) = args.value_of("stroke-width") {
        match stroke_width.parse() {
            Ok(sw) => {
                settings.stroke_width = sw;
            }
            Err(e) => {
                use std::io::Write;
                use std::process::exit;

                writeln!(&mut std::io::stderr(),
                         "Wrong stroke width: {}",
                         e)
                    .unwrap();
                exit(1);
            }
        }
    }

    if let Some(scale) = args.value_of("scale") {
        match scale.parse() {
            Ok(s) => {
                settings.scale(s);
            }
            Err(e) => {
                use std::io::Write;
                use std::process::exit;

                writeln!(&mut std::io::stderr(),
                         "Wrong scale: {}",
                         e)
                    .unwrap();
                exit(1);
            }
        }
    }

    let g = Grid::from_str(&*bob, &settings);
    let svg = g.get_svg();

    if let Some(file) = args.value_of("output") {
        if let Err(e) = svg::save(file, &svg) {
            use std::io::Write;
            use std::process::exit;

            writeln!(&mut std::io::stderr(),
                     "Failed to write to output file {}: {}",
                     file,
                     e)
                .unwrap();
            exit(2);
        }
    } else {
        println!("{}", svg);
    }
}

// Batch convert files to svg
// use svgbob build -i inputdir/*.bob -o outdir/
fn build(args: &ArgMatches) -> Result<(), Box<Error>> {

    let files_pattern = args.value_of("input").unwrap_or("*.bob");
    let outdir = args.value_of("outdir").unwrap_or("");
    let input_path = Path::new(files_pattern);
    let ext = input_path.extension().unwrap_or(&"bob".as_ref()).to_str().unwrap();

    let input_dir = if input_path.is_dir() {
        input_path.clone()
    } else {
        input_path.parent().unwrap()
    };

    if !input_dir.is_dir() {
        return Err(Box::from(format!("[Error]: No such dir name is {} !",
                                     input_dir.to_string_lossy())));
    }

    let mut out_path = PathBuf::new();
    if outdir == "" {
        out_path = input_dir.to_path_buf();
    } else {
        out_path.push(outdir)
    }

    if !out_path.is_dir() {
        try!(fs::create_dir_all(out_path.clone()));
    }

    let paths = fs::read_dir(input_dir).unwrap();
    for path in paths {
        let tmp_path = path.unwrap().path();
        if tmp_path.is_file() {
            let tmp_ext = tmp_path.extension().unwrap_or(&"".as_ref()).to_str().unwrap();
            if tmp_ext == ext {
                let name = tmp_path.file_stem().unwrap().to_str().unwrap();
                let mut tmp = out_path.clone();
                tmp.push(format!("{}.svg", name));
                println!("{} => {}", tmp_path.display(), tmp.display());
                match convert_file(tmp_path.clone(), tmp) {
                    Ok(_) => {}
                    Err(e) => {
                        println!("{}", e);
                    }
                }
            }
        }
    }

    Ok(())
}

fn convert_file(input: PathBuf, output: PathBuf) -> Result<(), Box<Error>> {
    let mut bob = String::new();
    let mut f = try!(File::open(&input));
    f.read_to_string(&mut bob).unwrap();
    let g = Grid::from_str(&*bob,&Settings::compact());
    let svg = g.get_svg();
    try!(svg::save(&output, &svg));
    Ok(())
}
<commit_msg>Extract method<commit_after>#![deny(warnings)]
#[macro_use]
extern crate clap;

extern crate svgbob;
extern crate svg;

use svgbob::Grid;
use svgbob::Settings;

use clap::ArgMatches;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::error::Error;
use std::io::Read;
use std::process::exit;
use std::str::FromStr;

fn main() {
    use clap::{Arg, App, SubCommand};

    let args = App::new("svgbob")
        .version(crate_version!())
        .about("SvgBobRus is an ascii to svg converter")
        .arg(Arg::with_name("inline").short("s").help("parse an inline string"))
        .arg(Arg::with_name("input").index(1).help("svgbob text file or inline string to parse [default: STDIN]"))
        .arg(Arg::with_name("output")
            .short("o")
            .long("output")
            .takes_value(true)
            .help("where to write svg output [default: STDOUT]"))
        .arg(Arg::with_name("font-family")
             .long("font-family")
             .takes_value(true)
             .help("text will be rendered with this font (default: 'arial')"))
        .arg(Arg::with_name("font-size")
             .long("font-size")
             .takes_value(true)
             .help("text will be rendered with this font size (default: 14)"))
        .arg(Arg::with_name("stroke-width")
             .long("stroke-width")
             .takes_value(true)
             .help("stroke width for all lines (default: 2)"))
        .arg(Arg::with_name("scale")
             .long("scale")
             .takes_value(true)
             .help("scale the entire svg (dimensions, font size, stroke width) by this factor (default: 1)"))
        .subcommand(SubCommand::with_name("build")
            .about("Batch convert files to svg.")
            .version("0.0.1")
            .arg(Arg::with_name("input")
                .short("i")
                .long("input")
                .takes_value(true)
                .help("set input file pattern like: *.bob or dir/*.bob"))
            .arg(Arg::with_name("outdir")
                .short("o")
                .long("outdir")
                .takes_value(true)
                .help("set dir of svg files")))
        .get_matches();

    if let Some(sub_build) = args.subcommand_matches("build") {
        match build(sub_build) {
            Ok(_) => {}
            Err(e) => println!("{}", e),
        };
        exit(1);
    }

    let mut bob = String::new();

    if args.is_present("inline") {
        bob = args.value_of("input").unwrap().replace("\\n","\n").to_string();
    } else {
        if let Some(file) = args.value_of("input") {
            match File::open(file) {
                Ok(mut f) => {
                    f.read_to_string(&mut bob).unwrap();
                }
                Err(e) => {
                    use std::io::Write;
                    use std::process::exit;

                    writeln!(&mut std::io::stderr(),
                            "Failed to open input file {}: {}",
                            file,
                            e)
                        .unwrap();
                    exit(1);
                }
            }
        } else {
            use std::io;
            io::stdin().read_to_string(&mut bob).unwrap();
        }
    }

    let mut settings = Settings::compact();

    if let Some(font_family) = args.value_of("font-family") {
        settings.font_family = font_family.to_string();
    }

    if let Some(font_size) = parse_value_of(&args, "font-size") {
        settings.font_size = font_size;
    }

    if let Some(stroke_width) = parse_value_of(&args, "stroke-width") {
        settings.stroke_width = stroke_width;
    }

    if let Some(scale) = parse_value_of(&args, "scale") {
        settings.scale(scale);
    }

    let g = Grid::from_str(&*bob, &settings);
    let svg = g.get_svg();

    if let Some(file) = args.value_of("output") {
        if let Err(e) = svg::save(file, &svg) {
            use std::io::Write;
            use std::process::exit;

            writeln!(&mut std::io::stderr(),
                     "Failed to write to output file {}: {}",
                     file,
                     e)
                .unwrap();
            exit(2);
        }
    } else {
        println!("{}", svg);
    }
}

fn parse_value_of<T: FromStr>(args: &ArgMatches, arg_name: &str) -> Option<T> where <T as std::str::FromStr>::Err: std::fmt::Display {
    return args.value_of(arg_name).and_then(|arg| match arg.parse::<T>() {
        Ok(a) => Some(a),
        Err(e) => {
            use std::io::Write;
            use std::process::exit;

            writeln!(&mut std::io::stderr(),
                        "Illegal value for argument {}: {}",
                        arg_name,
                        e)
                .unwrap();
            exit(1);
        }
    });
}

// Batch convert files to svg
// use svgbob build -i inputdir/*.bob -o outdir/
fn build(args: &ArgMatches) -> Result<(), Box<Error>> {

    let files_pattern = args.value_of("input").unwrap_or("*.bob");
    let outdir = args.value_of("outdir").unwrap_or("");
    let input_path = Path::new(files_pattern);
    let ext = input_path.extension().unwrap_or(&"bob".as_ref()).to_str().unwrap();

    let input_dir = if input_path.is_dir() {
        input_path.clone()
    } else {
        input_path.parent().unwrap()
    };

    if !input_dir.is_dir() {
        return Err(Box::from(format!("[Error]: No such dir name is {} !",
                                     input_dir.to_string_lossy())));
    }

    let mut out_path = PathBuf::new();
    if outdir == "" {
        out_path = input_dir.to_path_buf();
    } else {
        out_path.push(outdir)
    }

    if !out_path.is_dir() {
        try!(fs::create_dir_all(out_path.clone()));
    }

    let paths = fs::read_dir(input_dir).unwrap();
    for path in paths {
        let tmp_path = path.unwrap().path();
        if tmp_path.is_file() {
            let tmp_ext = tmp_path.extension().unwrap_or(&"".as_ref()).to_str().unwrap();
            if tmp_ext == ext {
                let name = tmp_path.file_stem().unwrap().to_str().unwrap();
                let mut tmp = out_path.clone();
                tmp.push(format!("{}.svg", name));
                println!("{} => {}", tmp_path.display(), tmp.display());
                match convert_file(tmp_path.clone(), tmp) {
                    Ok(_) => {}
                    Err(e) => {
                        println!("{}", e);
                    }
                }
            }
        }
    }

    Ok(())
}

fn convert_file(input: PathBuf, output: PathBuf) -> Result<(), Box<Error>> {
    let mut bob = String::new();
    let mut f = try!(File::open(&input));
    f.read_to_string(&mut bob).unwrap();
    let g = Grid::from_str(&*bob,&Settings::compact());
    let svg = g.get_svg();
    try!(svg::save(&output, &svg));
    Ok(())
}
<|endoftext|>


<commit_before>use std::iter::{repeat, IntoIterator};
use std::ops::{Index, IndexMut};
use std::slice::{Iter, IterMut};
use std::vec::{Vec, IntoIter};

#[derive(Debug)]
pub struct Table<T> {
    dimensions: (usize, usize),
    data: Vec<T>
}

impl<T: Clone> Table<T> {
    #[inline]
    pub fn from_elem(dimensions: (usize, usize), value: T) -> Table<T> {
        let (width, height) = dimensions;

        Table {
            dimensions: dimensions,
            data: repeat(value).take(width * height).collect()
        }
    }
}

impl<T> Table<T> {
    #[inline]
    fn get_vec_index(&self, index: (usize, usize)) -> usize {
        let (row, column) = index;
        let (width, height) = self.dimensions;

        if row >= height {
            panic!("Table::get_index: `row` overflow ({} >= {})", row, height)
        }
        if column >= width {
            panic!("Table::get_index: `column` overflow ({} >= {})", column, width)
        }

        row * width + column
    }

    #[inline]
    pub fn get_dimensions(&self) -> (usize, usize) {
        self.dimensions
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> TableIter<Iter<'a, T>> {
        self.data.iter().as_table(self.dimensions)
    }

    #[inline]
    pub fn iter_mut<'a>(&'a mut self) -> TableIter<IterMut<'a, T>> {
        self.data.iter_mut().as_table(self.dimensions)
    }

    #[inline]
    pub fn into_iter<'a>(self) -> TableIter<IntoIter<T>> {
        self.data.into_iter().as_table(self.dimensions)
    }
}

impl<T> Index<(usize, usize)> for Table<T> {
    type Output = T;

    #[inline]
    fn index<'a>(&'a self, index: &(usize, usize)) -> &'a T {
        let vec_index = self.get_vec_index(*index);
        self.data.index(&vec_index)
    }
}

impl<T> IndexMut<(usize, usize)> for Table<T> {
    #[inline]
    fn index_mut<'a>(&'a mut self, index: &(usize, usize)) -> &'a mut T {
        let vec_index = self.get_vec_index(*index);
        self.data.index_mut(&vec_index)
    }
}

impl<'a, T> IntoIterator for &'a Table<T> {
    type Item = &'a T;
    type IntoIter = TableIter<Iter<'a, T>>;

    fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
        self.iter()
    }
}

impl<'a, T> IntoIterator for &'a mut Table<T> {
    type Item = &'a mut T;
    type IntoIter = TableIter<IterMut<'a, T>>;

    fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
        self.iter_mut()
    }
}

impl<T> IntoIterator for Table<T> {
    type Item = T;
    type IntoIter = TableIter<IntoIter<T>>;

    fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
        self.into_iter()
    }
}

#[derive(Debug)]
pub struct TableIter<T: Iterator> {
    iter: T,
    dimensions: (usize, usize)
}

impl<T: Iterator> Iterator for TableIter<T> {
    type Item = T::Item;

    #[inline]
    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        self.iter.next()
    }
}

pub trait AsTable {
    fn as_table(self, dimensions: (usize, usize)) -> TableIter<Self>;
}

impl<'a, T: Iterator> AsTable for T {
    #[inline]
    fn as_table(self, dimensions: (usize, usize)) -> TableIter<Self> {
        TableIter {
            iter: self,
            dimensions: dimensions
        }
    }
}

#[derive(Debug)]
pub struct TableEnumerate<T> {
    iter: T,
    row_count: usize,
    column_count: usize
}

impl<T: Iterator> Iterator for TableEnumerate<TableIter<T>> {
    type Item = ((usize, usize), T::Item);

    #[inline]
    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        let (width, _) = self.iter.dimensions;

        match self.iter.next() {
            Some(value) => {
                let ret = Some(((self.row_count, self.column_count), value));

                self.column_count += 1;
                if self.column_count == width {
                    self.row_count += 1;
                    self.column_count = 0;
                }
                ret
            },
            None => None
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<T: Iterator> TableIter<T> {
    #[inline]
    pub fn enumerate_2d(self) -> TableEnumerate<TableIter<T>> {
        TableEnumerate {
            iter: self,
            row_count: 0,
            column_count: 0
        }
    }

    #[inline]
    pub fn enumerate_2d_from(self, start: (usize, usize)) -> TableEnumerate<TableIter<T>> {
        let (row_start, column_start) = start;

        TableEnumerate {
            iter: self,
            row_count: row_start,
            column_count: column_start
        }
    }

    #[inline]
    pub fn enumerate_2d_from_index(self, index: usize) -> TableEnumerate<TableIter<T>> {
        let (width, _) = self.dimensions;
        let row_start = index / width;
        let column_start = index % width;

        TableEnumerate {
            iter: self,
            row_count: row_start,
            column_count: column_start
        }
    }
}
<commit_msg>Updates indexing traits to take the index by value.<commit_after>use std::iter::{repeat, IntoIterator};
use std::ops::{Index, IndexMut};
use std::slice::{Iter, IterMut};
use std::vec::{Vec, IntoIter};

#[derive(Debug)]
pub struct Table<T> {
    dimensions: (usize, usize),
    data: Vec<T>
}

impl<T: Clone> Table<T> {
    #[inline]
    pub fn from_elem(dimensions: (usize, usize), value: T) -> Table<T> {
        let (width, height) = dimensions;

        Table {
            dimensions: dimensions,
            data: repeat(value).take(width * height).collect()
        }
    }
}

impl<T> Table<T> {
    #[inline]
    fn get_vec_index(&self, index: (usize, usize)) -> usize {
        let (row, column) = index;
        let (width, height) = self.dimensions;

        if row >= height {
            panic!("Table::get_index: `row` overflow ({} >= {})", row, height)
        }
        if column >= width {
            panic!("Table::get_index: `column` overflow ({} >= {})", column, width)
        }

        row * width + column
    }

    #[inline]
    pub fn get_dimensions(&self) -> (usize, usize) {
        self.dimensions
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> TableIter<Iter<'a, T>> {
        self.data.iter().as_table(self.dimensions)
    }

    #[inline]
    pub fn iter_mut<'a>(&'a mut self) -> TableIter<IterMut<'a, T>> {
        self.data.iter_mut().as_table(self.dimensions)
    }

    #[inline]
    pub fn into_iter<'a>(self) -> TableIter<IntoIter<T>> {
        self.data.into_iter().as_table(self.dimensions)
    }
}

impl<T> Index<(usize, usize)> for Table<T> {
    type Output = T;

    #[inline]
    fn index<'a>(&'a self, index: (usize, usize)) -> &'a T {
        let vec_index = self.get_vec_index(index);
        self.data.index(vec_index)
    }
}

impl<T> IndexMut<(usize, usize)> for Table<T> {
    #[inline]
    fn index_mut<'a>(&'a mut self, index: (usize, usize)) -> &'a mut T {
        let vec_index = self.get_vec_index(index);
        self.data.index_mut(vec_index)
    }
}

impl<'a, T> IntoIterator for &'a Table<T> {
    type Item = &'a T;
    type IntoIter = TableIter<Iter<'a, T>>;

    fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
        self.iter()
    }
}

impl<'a, T> IntoIterator for &'a mut Table<T> {
    type Item = &'a mut T;
    type IntoIter = TableIter<IterMut<'a, T>>;

    fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
        self.iter_mut()
    }
}

impl<T> IntoIterator for Table<T> {
    type Item = T;
    type IntoIter = TableIter<IntoIter<T>>;

    fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
        self.into_iter()
    }
}

#[derive(Debug)]
pub struct TableIter<T: Iterator> {
    iter: T,
    dimensions: (usize, usize)
}

impl<T: Iterator> Iterator for TableIter<T> {
    type Item = T::Item;

    #[inline]
    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        self.iter.next()
    }
}

pub trait AsTable {
    fn as_table(self, dimensions: (usize, usize)) -> TableIter<Self>;
}

impl<'a, T: Iterator> AsTable for T {
    #[inline]
    fn as_table(self, dimensions: (usize, usize)) -> TableIter<Self> {
        TableIter {
            iter: self,
            dimensions: dimensions
        }
    }
}

#[derive(Debug)]
pub struct TableEnumerate<T> {
    iter: T,
    row_count: usize,
    column_count: usize
}

impl<T: Iterator> Iterator for TableEnumerate<TableIter<T>> {
    type Item = ((usize, usize), T::Item);

    #[inline]
    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        let (width, _) = self.iter.dimensions;

        match self.iter.next() {
            Some(value) => {
                let ret = Some(((self.row_count, self.column_count), value));

                self.column_count += 1;
                if self.column_count == width {
                    self.row_count += 1;
                    self.column_count = 0;
                }
                ret
            },
            None => None
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<T: Iterator> TableIter<T> {
    #[inline]
    pub fn enumerate_2d(self) -> TableEnumerate<TableIter<T>> {
        TableEnumerate {
            iter: self,
            row_count: 0,
            column_count: 0
        }
    }

    #[inline]
    pub fn enumerate_2d_from(self, start: (usize, usize)) -> TableEnumerate<TableIter<T>> {
        let (row_start, column_start) = start;

        TableEnumerate {
            iter: self,
            row_count: row_start,
            column_count: column_start
        }
    }

    #[inline]
    pub fn enumerate_2d_from_index(self, index: usize) -> TableEnumerate<TableIter<T>> {
        let (width, _) = self.dimensions;
        let row_start = index / width;
        let column_start = index % width;

        TableEnumerate {
            iter: self,
            row_count: row_start,
            column_count: column_start
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;
use table::rand::Rng;
type Bucket = Vec<usize>; // later this will have chaining, for now just blob
 // everything together
const P: f64 = (0xFFFFFFFE as usize - 4) as f64;
pub struct LSHTable<'a, T: 'a, Q: 'a+?Sized>  {
    buckets: Vec<Bucket>,
    data: &'a [T],
    hash_functions: &'a [Box<Q>],
    ri1: Vec<f64>,
}

impl<'a, T, Q: 'a+?Sized> LSHTable<'a, T, Q> where Q: Fn(&'a T) -> f64 {
    pub fn new(data: &'a [T], hashes: &'a [Box<Q>]) -> Self {
        LSHTable {
            buckets: vec![Vec::new(); data.len()],
            data: data,
            hash_functions: hashes,
            ri1: rand::thread_rng().gen_iter().take(hashes.len()).collect(),
        }
    }
    fn get_signature(&self, v: &'a T) -> Vec<f64> {
        self.hash_functions.iter().map(|x| {
            (*x)(v)
        }).collect()
    }
    pub fn new_build(data: &'a [T], hashes: &'a [Box<Q>]) -> Self {
        let mut x_to_build = LSHTable::new(data, hashes);
        for (i, v) in x_to_build.data.iter().enumerate() {
            let hash_sig = x_to_build.get_signature(v);
            let bucket_ind = hash_func_t1(&hash_sig, &x_to_build.ri1, P, x_to_build.buckets.len());
            x_to_build.buckets[bucket_ind].push(i);
        }
        x_to_build
    }

    pub fn query_vec(&self, v: &'a T) -> Vec<&T> {
        let sig = self.get_signature(v);
        let sig_ind = hash_func_t1(&sig, &self.ri1, P, self.buckets.len());
        self.buckets[sig_ind].iter().map(|bucket_ind| {
            &self.data[*bucket_ind]
        }).collect()
    }
}

fn hash_func_t1(signature: &[f64], rand_ints: &[f64], primes: f64, num_buckets: usize) -> usize {
    let total: usize = {
        let mut counter: f64 = 0.0;
        for element in signature.iter().zip(rand_ints).map(|(a, b)| {(a * b)}) {
            counter = ((counter + element)) % primes;
        }
        counter as usize
    };
    total % num_buckets
}

#[cfg(test)]
mod tests {
    use super::LSHTable;
    #[test]
    fn test_init() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

        let val = |q: &Vec<i32>| {0.0 as f64};
        let funcs = vec![Box::new(val)];
        let x = LSHTable::new(&test_data, &funcs);
    }
    #[test]
    fn test_new_build() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

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

    #[test]
    fn test_query() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

        let val = |q: &Vec<i32>| {0.0 as f64};
        let funcs = vec![Box::new(val)];
        let x = LSHTable::new_build(&test_data, &funcs);
        x.query_vec(&test_data[0]);
    }
}
<commit_msg>buckets and chains of buckets as vectors<commit_after>extern crate rand;
use std::ops::Index;
use table::rand::Rng;

#[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)]
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.iter() {
            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 self.chain.iter_mut() {
            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);
    }
}

 // later this will have chaining, for now just blob
 // everything together
const P: f64 = (0xFFFFFFFE as usize - 4) as f64;
pub struct LSHTable<'a, T: 'a, Q: 'a+?Sized>  {
    buckets: Vec<BucketChain>,
    data: &'a [T],
    hash_functions: &'a [Box<Q>],
    ri1: Vec<f64>,
    ri2: Vec<f64>,
}

impl<'a, T, Q: 'a+?Sized> LSHTable<'a, T, Q> where Q: Fn(&'a T) -> f64 {
    pub fn new(data: &'a [T], hashes: &'a [Box<Q>]) -> Self {
        LSHTable {
            buckets: vec![BucketChain::new(); data.len()],
            data: data,
            hash_functions: hashes,
            ri1: rand::thread_rng().gen_iter().take(hashes.len()).collect(),
            ri2: rand::thread_rng().gen_iter().take(hashes.len()).collect(),
        }
    }
    fn get_signature(&self, v: &'a T) -> Vec<f64> {
        self.hash_functions.iter().map(|x| {
            (*x)(v)
        }).collect()
    }
    pub fn new_build(data: &'a [T], hashes: &'a [Box<Q>]) -> Self {
        let mut x_to_build = LSHTable::new(data, hashes);
        for (i, v) in x_to_build.data.iter().enumerate() {
            let hash_sig = x_to_build.get_signature(v);
            let bucket_ind = hash_func_t1(&hash_sig, &x_to_build.ri1, P, x_to_build.buckets.len());
            let ref mut bucket_chain = x_to_build.buckets[bucket_ind];
            let chain_ind = hash_func_t2(&hash_sig, &x_to_build.ri2, P );
            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<&T> {
        let sig = self.get_signature(v);
        let sig_ind = hash_func_t1(&sig, &self.ri1, P, self.buckets.len());
        let chain_ind = hash_func_t2(&sig, &self.ri2, P );
        match self.buckets[sig_ind].get(chain_ind) {
           Some(bucket) => bucket.pointers.iter().map(|bucket_ind| {
                &self.data[*bucket_ind]
           }).collect(),
            None => Vec::new()
        }
    }
}

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

fn hash_func_t2(signature: &[f64], rand_ints: &[f64], primes: f64) -> usize {
    let mut counter: f64 = 0.0;
    for element in signature.iter().zip(rand_ints).map(|(a, b)| {(a * b)}) {
        counter = ((counter + element)) % primes;
    }
    counter as usize
}
#[cfg(test)]
mod tests {
    use super::LSHTable;
    #[test]
    fn test_init() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

        let val = |q: &Vec<i32>| {0.0 as f64};
        let funcs = vec![Box::new(val)];
        let x = LSHTable::new(&test_data, &funcs);
    }
    #[test]
    fn test_new_build() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

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

    #[test]
    fn test_query() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

        let val = |q: &Vec<i32>| {0.0 as f64};
        let funcs = vec![Box::new(val)];
        let x = LSHTable::new_build(&test_data, &funcs);
        x.query_vec(&test_data[0]);
    }
}
<|endoftext|>


<commit_before>use super::*;

#[test]
fn sliding_windows_1() {
    fn test_window_correctness_with_storage(mut storage: Storage<u32>) {
        let expected: &[&[u32]] = &[&[0,1,2], &[1,2,3], &[2,3,4]];

        {
            let windowed_iter = Adaptor::new(0..5, &mut storage);
            let output: Vec<Vec<u32>> = windowed_iter.map(|x| From::from(&x[..])).collect();
            assert_eq!(output, expected);
        }
    }

    let auto_alloc:   Storage<u32> = Storage::optimized(&(0..5), 3);
    let middle_alloc: Storage<u32> = Storage::new(3);
    let small_alloc:  Storage<u32> = Storage::from_vec(vec![1u32;   1], 3);
    let exact_alloc:  Storage<u32> = Storage::from_vec(vec![1u32;   3], 3);
    let big_alloc:    Storage<u32> = Storage::from_vec(vec![1u32, 100], 3);

    test_window_correctness_with_storage(auto_alloc);
    test_window_correctness_with_storage(middle_alloc);
    test_window_correctness_with_storage(small_alloc);
    test_window_correctness_with_storage(exact_alloc);
    test_window_correctness_with_storage(big_alloc);
}

#[test]
fn sliding_windows_2() {
    let it = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&it, 3);
    let windowed_iter = Adaptor::new(it, &mut storage);

    for mut x in windowed_iter {
        x[1] = 0u32;
        assert_eq!(x[0], 0);
    }
}

#[test]
#[should_panic]
fn sliding_windows_3() {
    let it = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&it, 3);
    let mut windowed_iter = Adaptor::new(it, &mut storage);

    let _a = windowed_iter.next();
    let _b = windowed_iter.next();
}

#[test]
fn sliding_windows_4() {
    let mut storage1: Storage<u32> = Storage::new(3);
    let iter1 = Adaptor::new(0..5, &mut storage1);

    let mut storage2: Storage<u32> = Storage::new(5);
    let iter2 = Adaptor::new(0..5, &mut storage2);

    let mut storage3: Storage<u32> = Storage::new(6);
    let iter3 = Adaptor::new(0..5, &mut storage3);

    let mut storage4: Storage<u32> = Storage::new(6);
    let iter4 = Adaptor::new(0..0, &mut storage4);

    let mut storage5: Storage<u32> = Storage::new(6);
    let iter5 = Adaptor::new(0.., &mut storage5);

    assert_eq!(iter1.size_hint(), (3, Some(3)));
    assert_eq!(iter2.size_hint(), (1, Some(1)));
    assert_eq!(iter3.size_hint(), (1, Some(1)));
    assert_eq!(iter4.size_hint(), (0, Some(0)));
    assert_eq!(iter5.size_hint(), (0, None));
}

#[test]
fn sliding_windows_5() {
    let range = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&range, 0);
    let mut iter = Adaptor::new(range, &mut storage);

    assert!(iter.next().is_none());
    assert!(iter.next().is_none());
}

#[test]
fn sliding_windows_6() {
    let range0 = 0..0;
    let range1 = 0..1;
    let range2 = 0..2;

    let storage0: Storage<u32> = Storage::optimized(&range0, 1);
    let storage0: Vec<u32> = storage0.into();
    assert_eq!(storage0.capacity(), 2);

    let storage1: Storage<u32> = Storage::optimized(&range1, 1);
    let storage1: Vec<u32> = storage1.into();
    assert_eq!(storage1.capacity(), 1);

    let storage2: Storage<u32> = Storage::optimized(&range2, 1);
    let storage2: Vec<u32> = storage2.into();
    assert_eq!(storage2.capacity(), 2);

    let storage3: Storage<u32> = Storage::optimized(&range2, 3);
    let storage3: Vec<u32> = storage3.into();
    assert_eq!(storage3.capacity(), 2);
}
<commit_msg>remove silly test that relied on RangeFrom::size_hint returning 0 instead of usize::MAX<commit_after>use super::*;

#[test]
fn sliding_windows_1() {
    fn test_window_correctness_with_storage(mut storage: Storage<u32>) {
        let expected: &[&[u32]] = &[&[0,1,2], &[1,2,3], &[2,3,4]];

        {
            let windowed_iter = Adaptor::new(0..5, &mut storage);
            let output: Vec<Vec<u32>> = windowed_iter.map(|x| From::from(&x[..])).collect();
            assert_eq!(output, expected);
        }
    }

    let auto_alloc:   Storage<u32> = Storage::optimized(&(0..5), 3);
    let middle_alloc: Storage<u32> = Storage::new(3);
    let small_alloc:  Storage<u32> = Storage::from_vec(vec![1u32;   1], 3);
    let exact_alloc:  Storage<u32> = Storage::from_vec(vec![1u32;   3], 3);
    let big_alloc:    Storage<u32> = Storage::from_vec(vec![1u32, 100], 3);

    test_window_correctness_with_storage(auto_alloc);
    test_window_correctness_with_storage(middle_alloc);
    test_window_correctness_with_storage(small_alloc);
    test_window_correctness_with_storage(exact_alloc);
    test_window_correctness_with_storage(big_alloc);
}

#[test]
fn sliding_windows_2() {
    let it = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&it, 3);
    let windowed_iter = Adaptor::new(it, &mut storage);

    for mut x in windowed_iter {
        x[1] = 0u32;
        assert_eq!(x[0], 0);
    }
}

#[test]
#[should_panic]
fn sliding_windows_3() {
    let it = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&it, 3);
    let mut windowed_iter = Adaptor::new(it, &mut storage);

    let _a = windowed_iter.next();
    let _b = windowed_iter.next();
}

#[test]
fn sliding_windows_4() {
    let mut storage1: Storage<u32> = Storage::new(3);
    let iter1 = Adaptor::new(0..5, &mut storage1);

    let mut storage2: Storage<u32> = Storage::new(5);
    let iter2 = Adaptor::new(0..5, &mut storage2);

    let mut storage3: Storage<u32> = Storage::new(6);
    let iter3 = Adaptor::new(0..5, &mut storage3);

    let mut storage4: Storage<u32> = Storage::new(6);
    let iter4 = Adaptor::new(42..42, &mut storage4);

    assert_eq!(iter1.size_hint(), (3, Some(3)));
    assert_eq!(iter2.size_hint(), (1, Some(1)));
    assert_eq!(iter3.size_hint(), (1, Some(1)));
    assert_eq!(iter4.size_hint(), (0, Some(0)));
}

#[test]
fn sliding_windows_5() {
    let range = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&range, 0);
    let mut iter = Adaptor::new(range, &mut storage);

    assert!(iter.next().is_none());
    assert!(iter.next().is_none());
}

#[test]
fn sliding_windows_6() {
    let range0 = 0..0;
    let range1 = 0..1;
    let range2 = 0..2;

    let storage0: Storage<u32> = Storage::optimized(&range0, 1);
    let storage0: Vec<u32> = storage0.into();
    assert_eq!(storage0.capacity(), 2);

    let storage1: Storage<u32> = Storage::optimized(&range1, 1);
    let storage1: Vec<u32> = storage1.into();
    assert_eq!(storage1.capacity(), 1);

    let storage2: Storage<u32> = Storage::optimized(&range2, 1);
    let storage2: Vec<u32> = storage2.into();
    assert_eq!(storage2.capacity(), 2);

    let storage3: Storage<u32> = Storage::optimized(&range2, 3);
    let storage3: Vec<u32> = storage3.into();
    assert_eq!(storage3.capacity(), 2);
}
<|endoftext|>