gradient_slice/
lib.rs

1#![doc(issue_tracker_base_url = "https://github.com/gabrielfalcao/unique-pointer/issues/")]
2//! # Gradient Slice
3//!
4//! gradient-slice is a safe crate to iterate over a gradient of
5//! permutations of slices of a Vec
6//!
7//! ## Example
8//!
9//! ```
10//! use gradient_slice::Gradient;
11//! let result = Gradient::new(" abc ".chars().collect::<Vec<char>>())
12//!     .map(Vec::from)
13//!     .map(|vec| {
14//!         vec.iter()
15//!             .map(Clone::clone)
16//!             .map(String::from)
17//!             .collect::<String>()
18//!     })
19//!     .collect::<Vec<String>>();
20//! assert_eq!(
21//!     result,
22//!     vec![
23//!         " ", "a", "b", "c", " ", " a", "ab", "bc", "c ", " ab", "abc", "bc ", " abc",
24//!         "abc ", " abc "
25//!     ]
26//! );
27//! ```
28
29use core::iter::Iterator;
30use core::marker::PhantomData;
31
32/// ```
33/// use gradient_slice::Gradient;
34/// let result = Gradient::new(0x1BADB002u32.to_be_bytes().to_vec())
35///     .map(Vec::from)
36///     .collect::<Vec<Vec<u8>>>();
37/// assert_eq!(
38///     result,
39///     vec![
40///         vec![27], vec![173], vec![176], vec![2],
41///         vec![27, 173], vec![173, 176], vec![176, 2],
42///         vec![27, 173, 176], vec![173, 176, 2],
43///         vec![27, 173, 176, 2]
44///     ]
45/// );
46/// ```
47#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
48pub struct Gradient<'a, G> {
49    input: Vec<G>,
50    start: usize,
51    end: usize,
52    width: usize,
53    wide: bool,
54
55    _marker: PhantomData<&'a G>,
56}
57impl<'a, G: 'a> Iterator for Gradient<'a, G> {
58    type Item = &'a [G];
59
60    fn next(&mut self) -> Option<&'a [G]> {
61        if self.finished() {
62            return None;
63        }
64        self.end += 1;
65        if !self.wide {
66            self.wide = true;
67            self.width += 1;
68            self.start = 0;
69            self.end = self.width;
70        }
71
72        self.start = self.end - self.width;
73        if self.end == self.len() {
74            self.wide = false;
75        }
76        Some(self.window())
77    }
78}
79impl<'a, G: Clone + 'a> Gradient<'a, G> {
80    pub fn input(&self) -> Vec<G> {
81        self.input.clone()
82    }
83}
84impl<'a, G: 'a> Gradient<'a, G> {
85    pub fn window(&self) -> &'a [G] {
86        unsafe { core::mem::transmute::<&[G], &'a [G]>(&self.input[self.range()]) }
87    }
88
89    pub fn finished(&self) -> bool {
90        if self.len() == 0 {
91            return true;
92        }
93        if self.end == self.len() {
94            if self.width == self.len() {
95                return true;
96            }
97        }
98        false
99    }
100
101    pub fn width(&self) -> usize {
102        self.width
103    }
104
105    pub fn start(&self) -> usize {
106        self.start
107    }
108
109    pub fn end(&self) -> usize {
110        self.end
111    }
112
113    pub fn range(&self) -> core::ops::Range<usize> {
114        self.start()..self.end()
115    }
116
117    pub fn len(&self) -> usize {
118        self.input.len()
119    }
120
121    pub fn new(s: Vec<G>) -> Gradient<'a, G> {
122        Gradient {
123            input: s,
124            start: 0,
125            end: 0,
126            width: 1,
127            wide: true,
128            _marker: PhantomData,
129        }
130    }
131}
132
133#[cfg(test)]
134mod tests {
135    use super::*;
136
137    #[test]
138    fn gradient() {
139        let result = Gradient::new(" abc ".chars().collect())
140            .map(Vec::from)
141            .map(|vec| {
142                vec.iter()
143                    .map(Clone::clone)
144                    .map(String::from)
145                    .collect::<String>()
146            })
147            .collect::<Vec<String>>();
148        assert_eq!(
149            result,
150            vec![
151                " ", "a", "b", "c", " ", " a", "ab", "bc", "c ", " ab", "abc", "bc ", " abc",
152                "abc ", " abc "
153            ]
154        );
155    }
156    #[test]
157    fn empty() {
158        assert_eq!(Gradient::new(Vec::<char>::new()).collect::<Vec<_>>().len(), 0);
159    }
160}