1#![doc(issue_tracker_base_url = "https://github.com/gabrielfalcao/unique-pointer/issues/")]
2use core::iter::Iterator;
30use core::marker::PhantomData;
31
32#[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 _marker: PhantomData<&'a G>,
55}
56impl<'a, G: 'a> Iterator for Gradient<'a, G> {
57 type Item = &'a [G];
58
59 fn next(&mut self) -> Option<&'a [G]> {
60 if self.end == self.input.len() {
61 if self.width == self.len() {
62 return None;
63 }
64 }
65 self.end += 1;
66 if !self.wide {
67 self.wide = true;
68 self.width += 1;
69 self.start = 0;
70 self.end = self.width;
71 }
72
73 self.start = self.end - self.width;
74 if self.end == self.len() {
75 self.wide = false;
76 }
77 Some(self.window())
78 }
79}
80impl<'a, G: 'a> Gradient<'a, G> {
81 fn window(&self) -> &'a [G] {
82 unsafe { core::mem::transmute::<&[G], &'a [G]>(&self.input[self.range()]) }
83 }
84
85 fn start(&self) -> usize {
86 self.start
87 }
88
89 fn end(&self) -> usize {
90 self.end
91 }
92
93 fn range(&self) -> core::ops::Range<usize> {
94 self.start()..self.end()
95 }
96
97 fn len(&self) -> usize {
98 self.input.len()
99 }
100
101 pub fn new(s: Vec<G>) -> Gradient<'a, G> {
102 Gradient {
103 input: s,
104 start: 0,
105 end: 0,
106 width: 1,
107 wide: true,
108 _marker: PhantomData,
109 }
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn gradient() {
119 let result = Gradient::new(" abc ".chars().collect())
120 .map(Vec::from)
121 .map(|vec| {
122 vec.iter()
123 .map(Clone::clone)
124 .map(String::from)
125 .collect::<String>()
126 })
127 .collect::<Vec<String>>();
128 assert_eq!(
129 result,
130 vec![
131 " ", "a", "b", "c", " ", " a", "ab", "bc", "c ", " ab", "abc", "bc ", " abc",
132 "abc ", " abc "
133 ]
134 );
135 }
136}