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 max_width: Option<usize>,
55
56 _marker: PhantomData<&'a G>,
57}
58impl<'a, G: 'a> Iterator for Gradient<'a, G> {
59 type Item = &'a [G];
60
61 fn next(&mut self) -> Option<&'a [G]> {
62 if self.finished() {
63 return None;
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 if let Some(max_width) = self.max_width {
78 if self.width > max_width {
79 return None;
80 }
81 }
82 Some(self.window())
83 }
84}
85impl<'a, G: Clone + 'a> Gradient<'a, G> {
86 pub fn input(&self) -> Vec<G> {
87 self.input.clone()
88 }
89
90 pub fn with_max_width(self, width: usize) -> Gradient<'a, G> {
105 let mut gradient = self.clone();
106 gradient.max_width = Some(width);
107 gradient
108 }
109}
110impl<'a, G: 'a> Gradient<'a, G> {
111 pub fn window(&self) -> &'a [G] {
112 unsafe { core::mem::transmute::<&[G], &'a [G]>(&self.input[self.range()]) }
113 }
114
115 pub fn finished(&self) -> bool {
116 if self.len() == 0 {
117 return true;
118 }
119 if self.end == self.len() {
120 if self.width == self.len() {
121 return true;
122 }
123 }
124 false
125 }
126
127 pub fn width(&self) -> usize {
128 self.width
129 }
130
131 pub fn start(&self) -> usize {
132 self.start
133 }
134
135 pub fn end(&self) -> usize {
136 self.end
137 }
138
139 pub fn range(&self) -> core::ops::Range<usize> {
140 self.start()..self.end()
141 }
142
143 pub fn len(&self) -> usize {
144 self.input.len()
145 }
146
147 pub fn new(s: Vec<G>) -> Gradient<'a, G> {
148 Gradient {
149 input: s,
150 start: 0,
151 end: 0,
152 width: 1,
153 wide: true,
154 max_width: None,
155 _marker: PhantomData,
156 }
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn gradient() {
166 let result = Gradient::new(" abc ".chars().collect())
167 .map(Vec::from)
168 .map(|vec| {
169 vec.iter()
170 .map(Clone::clone)
171 .map(String::from)
172 .collect::<String>()
173 })
174 .collect::<Vec<String>>();
175 assert_eq!(
176 result,
177 vec![
178 " ", "a", "b", "c", " ", " a", "ab", "bc", "c ", " ab", "abc", "bc ", " abc",
179 "abc ", " abc "
180 ]
181 );
182 }
183 #[test]
184 fn empty() {
185 assert_eq!(
186 Gradient::new(Vec::<char>::new()).collect::<Vec<_>>().len(),
187 0
188 );
189 }
190
191 #[test]
192 fn max_width() {
193 let result = Gradient::new(" abc ".chars().collect())
194 .with_max_width(2)
195 .map(Vec::from)
196 .map(|vec| {
197 vec.iter()
198 .map(Clone::clone)
199 .map(String::from)
200 .collect::<String>()
201 })
202 .collect::<Vec<String>>();
203 assert_eq!(
204 result,
205 vec![" ", "a", "b", "c", " ", " a", "ab", "bc", "c "]
206 );
207 }
208}