alith_client/primitives/
exact_string.rs

1use super::PrimitiveTrait;
2use crate::components::grammar::{ExactStringGrammar, Grammar};
3use crate::workflows::reason::ReasonTrait;
4use anyhow::Result;
5
6#[derive(Default, Debug, Clone)]
7pub struct ExactStringPrimitive {
8    pub allowed_strings: Vec<String>,
9}
10
11impl ExactStringPrimitive {
12    pub fn add_strings_to_allowed<T: AsRef<str>>(&mut self, words: &[T]) -> &mut Self {
13        words.iter().for_each(|word| {
14            self.add_string_to_allowed(word);
15        });
16        self
17    }
18
19    pub fn add_string_to_allowed<T: AsRef<str>>(&mut self, word: T) -> &mut Self {
20        if !self.allowed_strings.is_empty()
21            && self
22                .allowed_strings
23                .iter()
24                .any(|text| text == word.as_ref())
25        {
26            return self;
27        }
28        self.allowed_strings.push(word.as_ref().to_owned());
29        self
30    }
31
32    pub fn remove_string_from_allowed<T: AsRef<str>>(&mut self, word: T) -> &mut Self {
33        self.allowed_strings.retain(|w| w != word.as_ref());
34        self
35    }
36
37    fn grammar_inner(&self) -> ExactStringGrammar {
38        Grammar::exact_string().add_exact_strings(&self.allowed_strings)
39    }
40}
41
42impl PrimitiveTrait for ExactStringPrimitive {
43    type PrimitiveResult = String;
44
45    fn clear_primitive(&mut self) {
46        self.allowed_strings.clear();
47    }
48
49    fn type_description(&self, result_can_be_none: bool) -> &str {
50        if result_can_be_none {
51            "string or 'None of the above.'"
52        } else {
53            "string"
54        }
55    }
56
57    fn solution_description(&self, result_can_be_none: bool) -> String {
58        if result_can_be_none {
59            format!(
60                "one of the the following strings: {}, or, possibly, 'None of the above.'",
61                self.allowed_strings.join(", ")
62            )
63        } else {
64            format!(
65                "one of the the following strings: {}",
66                self.allowed_strings.join(", ")
67            )
68        }
69    }
70
71    fn stop_word_result_is_none(&self, result_can_be_none: bool) -> Option<String> {
72        if result_can_be_none {
73            Some("None of the above.".to_string())
74        } else {
75            None
76        }
77    }
78
79    fn grammar(&self) -> Grammar {
80        self.grammar_inner().wrap()
81    }
82
83    fn parse_to_primitive(&self, content: &str) -> Result<Self::PrimitiveResult> {
84        let parsed: Self::PrimitiveResult = self.grammar_inner().grammar_parse(content)?;
85        Ok(parsed)
86    }
87}
88
89impl ReasonTrait for ExactStringPrimitive {
90    fn primitive_to_result_index(&self, content: &str) -> u32 {
91        let output = self.parse_to_primitive(content).unwrap();
92        if let Some(index) = self.allowed_strings.iter().position(|s| s == &output) {
93            index as u32
94        } else {
95            panic!("This shouldn't happen.")
96        }
97    }
98
99    fn result_index_to_primitive(&self, result_index: Option<u32>) -> Result<Option<String>> {
100        if let Some(result_index) = result_index {
101            if let Some(result) = self.allowed_strings.get(result_index as usize) {
102                Ok(Some(result.clone()))
103            } else {
104                panic!("This shouldn't happen.")
105            }
106        } else {
107            Ok(None)
108        }
109    }
110}