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
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}