ephemeris_forge/
name_set.rs1use std::vec;
4
5const PATTERN_SEPARATOR: &str = ";";
6
7#[derive(Clone, Debug, Default, Eq, PartialEq)]
9pub struct NameSet(Vec<String>);
10
11impl NameSet {
12 #[must_use]
14 pub fn new<V: IntoIterator<Item = String>>(values: V) -> Self {
15 let mut values: Vec<String> = values.into_iter().collect();
16 values.sort_unstable();
17 values.dedup();
18 Self(values)
19 }
20
21 #[must_use]
23 pub fn from_patterns(patterns: &str) -> Self {
24 Self::new(
25 patterns
26 .split(PATTERN_SEPARATOR)
27 .filter(|pattern| !pattern.is_empty())
28 .map(str::to_owned),
29 )
30 }
31
32 #[must_use]
34 pub fn to_patterns(&self) -> String {
35 self.0.join(PATTERN_SEPARATOR)
36 }
37
38 #[must_use]
40 pub fn as_slice(&self) -> &[String] {
41 &self.0
42 }
43
44 #[must_use]
46 pub fn into_vec(self) -> Vec<String> {
47 self.0
48 }
49}
50
51impl IntoIterator for NameSet {
52 type IntoIter = vec::IntoIter<String>;
53 type Item = String;
54
55 fn into_iter(self) -> Self::IntoIter {
56 self.0.into_iter()
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::NameSet;
63
64 #[test]
65 fn construction_sorts_and_deduplicates() {
66 let names = NameSet::new(["b".to_owned(), "a".to_owned(), "a".to_owned()]);
67 assert_eq!(names.as_slice(), ["a", "b"]);
68 }
69
70 #[test]
71 fn patterns_split_and_join_as_a_set() {
72 let names = NameSet::from_patterns("b;;a;a;");
73 assert_eq!(names.as_slice(), ["a", "b"]);
74 assert_eq!(names.to_patterns(), "a;b");
75 }
76}