1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! This crate implements a collection with data structures like we have in our browser history

#![feature(const_fn)]
#![feature(test)]
extern crate test;

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

    #[test]
    fn test_history_order() {
        let mut history: History<&str> = History::new();
        history.push("Element 1");
        history.push("Element 2");
        history.push("Element 3");
        history.go_backward();
        assert_eq!(*history.get_current(), "Element 2");
    }

    #[test]
    fn test_multi_back_for_switch() {
        let mut history: History<usize> = History::new();
        history.push(3);
        history.push(6);
        history.push(7);
        history.go_backward();
        history.push(1);
        history.push(9);
        history.go_backward();
        assert_eq!(*history.get_current(), 1usize); // Why does this fail (left side: 3, right side: 1)
    }

    #[bench]
    fn bench_new(b: &mut Bencher) {
        b.iter(|| History::<&str>::new());
    }

    #[bench]
    fn bench_push(b: &mut Bencher) {
        let mut history: History<&str> = History::new();
        b.iter(|| history.push("Pink fluffy unicorn"));
    }
}

use std::ops::{Index, IndexMut};

/// History is a vector with support for go forward and go back
pub struct History<T> {
    vec: Vec<T>,
    pub index: usize,
}

impl<T> History<T> {
    /// Creates a new history
    pub const fn new() -> History<T> {
        History {
            vec: Vec::new(),
            index: 0usize,
        }
    }

    /// Returns whether you can go backwards
    #[inline]
    pub const fn can_go_backward(&self) -> bool {
        self.index > 0usize
    }

    /// Returns whether you can go forwards
    #[inline]
    pub fn can_go_forward(&self) -> bool {
        0usize < self.vec.len()
    }

    /// Go forward
    pub fn go_forward(&mut self) {
        self.go_multi_forward(1);
    }

    /// Go `count` times forward
    #[inline]
    pub fn go_multi_forward(&mut self, count: usize) {
        self.index += count;
    }

    /// Go backwards
    pub fn go_backward(&mut self) {
        self.go_multi_backward(1);
    }

    /// Go `count` times backwards
    #[inline]
    pub fn go_multi_backward(&mut self, count: usize) {
        self.index -= count;
    }

    /// Pushes a new element to history
    pub fn push(&mut self, element: T) {
        let vec_i = self.vec.len();
        if self.index != vec_i {
            let diff: usize = vec_i - self.index;
            for _ in 0..diff {
                self.pop();
            }
        }
        self.vec.push(element);
        self.index += 1;
    }

    /// Removes the last element from a vector and returns it, or `None` if it is empty
    pub fn pop(&mut self) -> Option<T> {
        self.index -= 1;
        self.vec.pop()
    }

    /// Returns the current element
    pub fn get_current(&self) -> &T {
        &self.vec[self.index - 1]
    }

    /// Returns the length of the history
    pub fn len(&self) -> usize {
        self.vec.len()
    }
}

impl<T> Index<usize> for History<T> {
    type Output = T;
    fn index(&self, index: usize) -> &Self::Output {
        &self.vec[index]
    }
}

impl<T> IndexMut<usize> for History<T> {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        &mut self.vec[index]
    }
}