gradient_string/
lib.rs

1#![doc(issue_tracker_base_url = "https://github.com/gabrielfalcao/unique-pointer/issues/")]
2//! # Gradient String
3//!
4//! gradient-string is a safe crate to iterate over a gradient of
5//! permutations of string slices
6//!
7//! ## Example
8//!
9//! ```
10//! use gradient_string::Gradient;
11//! let result = Gradient::new(" abc ")
12//!     .collect::<Vec<String>>();
13//! assert_eq!(
14//!     result,
15//!     vec![
16//!         " ", "a", "b", "c", " ", " a", "ab", "bc", "c ", " ab", "abc", "bc ", " abc",
17//!         "abc ", " abc "
18//!     ]
19//! );
20//! ```
21use std::fmt::Display;
22use gradient_slice::Gradient as Slicer;
23
24
25/// ```
26/// use gradient_string::Gradient;
27/// let result = Gradient::new(" abc ")
28///     .collect::<Vec<String>>();
29/// assert_eq!(
30///     result,
31///     vec![
32///         " ", "a", "b", "c", " ", " a", "ab", "bc", "c ", " ab", "abc", "bc ", " abc",
33///         "abc ", " abc "
34///     ]
35/// );
36/// ```
37#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
38pub struct Gradient<'a> {
39    input: &'a str,
40    slice: Slicer<'a, char>,
41}
42impl<'a> Iterator for Gradient<'a> {
43    type Item = String;
44
45    fn next(&mut self) -> Option<String> {
46        self.slice.next().map(|slice| {
47            slice
48                .iter()
49                .map(Clone::clone)
50                .map(String::from)
51                .collect::<String>()
52        })
53    }
54}
55impl<'a> Gradient<'a> {
56    pub fn input(&self) -> &'a str {
57        self.input
58    }
59}
60impl<'a> Gradient<'a> {
61    pub fn window(&self) -> String {
62        self.slice.window().iter().map(Clone::clone).map(String::from).collect()
63    }
64
65    pub fn finished(&self) -> bool {
66        self.slice.finished()
67    }
68
69    pub fn width(&self) -> usize {
70        self.slice.width()
71    }
72
73    pub fn start(&self) -> usize {
74        self.slice.start()
75    }
76
77    pub fn end(&self) -> usize {
78        self.slice.end()
79    }
80
81    pub fn range(&self) -> core::ops::Range<usize> {
82        self.slice.range()
83    }
84
85    pub fn len(&self) -> usize {
86        self.slice.len()
87    }
88
89    pub fn new<T: Display>(s: T) -> Gradient<'a> {
90        Gradient {
91            input: s.to_string().leak(),
92            slice: Slicer::new(s.to_string().chars().collect::<Vec<char>>()),
93        }
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    #[test]
102    fn gradient() {
103        let result = Gradient::new(" abc ").collect::<Vec<String>>();
104        assert_eq!(
105            result,
106            vec![
107                " ", "a", "b", "c", " ", " a", "ab", "bc", "c ", " ab", "abc", "bc ", " abc",
108                "abc ", " abc "
109            ]
110        );
111    }
112    #[test]
113    fn empty() {
114        assert_eq!(
115            Gradient::new("").collect::<Vec<_>>().len(),
116            0
117        );
118    }
119}