ai_descriptor_trait/
lib.rs

1// ---------------- [ File: ai-descriptor-trait/src/lib.rs ]
2use 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("It is".to_string());
23        //lines.push(lowercase_first_letter(&self.header()));
24        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
80/// Extract unique items from a vector, maintaining their original order.
81/// Items after the first occurrence are discarded.
82pub 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}