1#![doc(issue_tracker_base_url = "https://github.com/gabrielfalcao/unique-pointer/issues/")]
2use std::fmt::Display;
22
23#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
36pub struct Gradient {
37 input: String,
38 start: usize,
39 end: usize,
40 width: usize,
41 wide: bool,
42 max_width: Option<usize>,
43}
44impl Iterator for Gradient {
45 type Item = String;
46
47 fn next(&mut self) -> Option<String> {
48 if self.finished() {
49 return None;
50 }
51 self.end += 1;
52 if !self.wide {
53 self.wide = true;
54 self.width += 1;
55 self.start = 0;
56 self.end = self.width;
57 }
58
59 self.start = self.end - self.width;
60 if self.end == self.len() {
61 self.wide = false;
62 }
63 if let Some(max_width) = self.max_width {
64 if self.width > max_width {
65 return None;
66 }
67 }
68 Some(self.window())
69 }
70}
71impl<'a> Gradient {
72 pub fn input(&self) -> &'a str {
73 unsafe { core::mem::transmute::<&str, &'a str>(&self.input[self.range()]) }
74 }
75}
76impl Gradient {
77 pub fn window(&self) -> String {
78 self.input[self.range()].to_string()
79 }
80
81 pub fn finished(&self) -> bool {
82 if self.len() == 0 {
83 return true;
84 }
85 if self.end == self.len() {
86 if self.width == self.len() {
87 return true;
88 }
89 }
90 false
91 }
92
93 pub fn width(&self) -> usize {
94 self.width
95 }
96
97 pub fn start(&self) -> usize {
98 self.start
99 }
100
101 pub fn end(&self) -> usize {
102 self.end
103 }
104
105 pub fn range(&self) -> core::ops::Range<usize> {
106 self.start()..self.end()
107 }
108
109 pub fn len(&self) -> usize {
110 self.input.len()
111 }
112
113 pub fn new<T: Display>(s: T) -> Gradient {
114 Gradient::with_max_width(s, None)
115 }
116
117 pub fn with_max_width<T: Display>(s: T, max_width: Option<usize>) -> Gradient {
132 Gradient {
133 input: s.to_string(),
134 start: 0,
135 end: 0,
136 width: 1,
137 wide: true,
138 max_width,
139 }
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn gradient() {
149 let result = Gradient::new(" abc ").collect::<Vec<String>>();
150 assert_eq!(
151 result,
152 vec![
153 " ", "a", "b", "c", " ", " a", "ab", "bc", "c ", " ab", "abc", "bc ", " abc",
154 "abc ", " abc "
155 ]
156 );
157 }
158 #[test]
159 fn empty() {
160 assert_eq!(Gradient::new("").collect::<Vec<_>>().len(), 0);
161 }
162
163 #[test]
164 fn max_width() {
165 let result = Gradient::with_max_width(" abc ", Some(2)).collect::<Vec<String>>();
166 assert_eq!(
167 result,
168 vec![" ", "a", "b", "c", " ", " a", "ab", "bc", "c "]
169 );
170 }
171}