alith_client/primitives/
exact_string.rs1use 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}