ai_descriptor_trait/
lib.rs1use std::borrow::Cow;
3
4#[allow(unused_imports)]
5use str_shorthand::lowercase_first_letter;
6
7pub trait ItemFeature {
8 fn text(&self) -> Cow<'_,str>;
9}
10
11pub trait ItemWithFeatures {
12 fn header(&self) -> Cow<'_,str>;
13 fn features(&self) -> Vec<Cow<'_, str>>;
14}
15
16impl<T> ItemFeature for T where T: ItemWithFeatures {
17
18 fn text(&self) -> Cow<'_,str> {
19
20 let mut lines: Vec<String> = vec![];
21
22 lines.push(self.header().to_string());
25
26 let unique = unique_items(&self.features());
27
28 for feature in unique {
29 lines.push(feature.to_string());
30 }
31
32 Cow::Owned(lines.join(" "))
33 }
34}
35
36impl<T: ItemWithFeatures> AIDescriptor for T {
37
38 fn ai(&self) -> Cow<'_,str> {
39
40 let mut lines: Vec<String> = vec![];
41
42 lines.push(self.header().into());
43
44 let unique = unique_items(&self.features());
45
46 if unique.len() > 0 {
47 lines.push("It has the following features:".into());
48 }
49
50 for feature in unique {
51 lines.push(format!("- {}", feature));
52 }
53
54 Cow::Owned(lines.join("\n"))
55 }
56
57 fn ai_alt(&self) -> Cow<'_,str> {
58
59 let mut lines: Vec<String> = vec![];
60
61 let unique = unique_items(&self.features());
62
63 for feature in unique {
64 lines.push(feature.into());
65 }
66
67 Cow::Owned(lines.join(" "))
68 }
69}
70
71pub trait AIDescriptor {
72
73 fn ai(&self) -> Cow<'_,str>;
74
75 fn ai_alt(&self) -> Cow<'_,str> {
76 unimplemented!("can implement this function for ai_alt() function")
77 }
78}
79
80pub fn unique_items<T>(items: &[T]) -> Vec<T>
83where
84 T: Clone + Eq + std::hash::Hash,
85{
86 let mut seen = std::collections::HashSet::new();
87 let mut unique = Vec::with_capacity(items.len());
88
89 for item in items.iter() {
90 if seen.insert(item) {
91 unique.push(item.clone());
92 }
93 }
94
95 unique
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 struct TestItem {
103 header: String,
104 features: Vec<Cow<'static, str>>,
105 }
106
107 impl ItemWithFeatures for TestItem {
108 fn header(&self) -> Cow<'_, str> {
109 Cow::Borrowed(&self.header)
110 }
111
112 fn features(&self) -> Vec<Cow<'_, str>> {
113 self.features.clone()
114 }
115 }
116
117 #[test]
118 fn test_ai_descriptor() {
119 let item = TestItem {
120 header: "An Item.".to_string(),
121 features: vec![
122 Cow::Borrowed("Feature 1"),
123 Cow::Borrowed("Feature 2"),
124 Cow::Borrowed("Feature 3"),
125 ],
126 };
127
128 let expected_output = "\
129An Item.
130It has the following features:
131- Feature 1
132- Feature 2
133- Feature 3";
134
135 assert_eq!(item.ai(), expected_output);
136 }
137}