ai_descriptor_trait/
lib.rs

1use std::borrow::Cow;
2
3pub trait ItemFeature {
4    fn text(&self) -> Cow<'_,str>;
5}
6
7pub trait ItemWithFeatures {
8    fn header(&self) -> Cow<'_,str>;
9    fn features(&self) -> Vec<Cow<'_, str>>;
10}
11
12pub trait AIDescriptor {
13    fn ai(&self) -> Cow<'_,str>;
14    fn ai_alt(&self) -> Cow<'_,str> {
15        unimplemented!("can implement this function for ai_alt() function")
16    }
17}
18
19impl<T: ItemWithFeatures> AIDescriptor for T {
20
21    fn ai(&self) -> Cow<'_,str> {
22        let mut lines: Vec<String> = vec![];
23        lines.push(self.header().into());
24        lines.push("It has the following features:".into());
25
26        for feature in self.features() {
27            lines.push(format!("- {}", feature));
28        }
29        Cow::Owned(lines.join("\n"))
30    }
31
32    fn ai_alt(&self) -> Cow<'_,str> {
33        let mut lines: Vec<String> = vec![];
34
35        for feature in self.features() {
36            lines.push(feature.into());
37        }
38        Cow::Owned(lines.join(" "))
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    struct TestItem {
47        header:   String,
48        features: Vec<Cow<'static, str>>,
49    }
50
51    impl ItemWithFeatures for TestItem {
52        fn header(&self) -> Cow<'_, str> {
53            Cow::Borrowed(&self.header)
54        }
55
56        fn features(&self) -> Vec<Cow<'_, str>> {
57            self.features.clone()
58        }
59    }
60
61    #[test]
62    fn test_ai_descriptor() {
63        let item = TestItem {
64            header: "An Item.".to_string(),
65            features: vec![
66                Cow::Borrowed("Feature 1"),
67                Cow::Borrowed("Feature 2"),
68                Cow::Borrowed("Feature 3"),
69            ],
70        };
71
72        let expected_output = "\
73An Item.
74It has the following features:
75- Feature 1
76- Feature 2
77- Feature 3";
78
79        assert_eq!(item.ai(), expected_output);
80    }
81}