alith_client/primitives/
text_list.rs

1use super::PrimitiveTrait;
2use crate::components::grammar::{Grammar, text::text_list::TextListGrammar};
3use anyhow::Result;
4use std::slice::{Iter, IterMut};
5use std::vec::IntoIter;
6
7#[derive(Debug, Clone)]
8pub struct TextListPrimitive {
9    pub min_count: u8,
10    pub max_count: u8,
11    pub text_token_length: u32,
12    pub item_prefix: Option<String>,
13    pub disallowed_chars: Vec<char>,
14}
15
16impl Default for TextListPrimitive {
17    fn default() -> Self {
18        TextListPrimitive {
19            min_count: 1,
20            max_count: 5,
21            text_token_length: 50,
22            item_prefix: None,
23            disallowed_chars: vec![],
24        }
25    }
26}
27
28impl TextListPrimitive {
29    pub fn text_token_length(&mut self, text_token_length: u32) -> &mut Self {
30        self.text_token_length = text_token_length;
31        self
32    }
33
34    /// Set the lower bound of the integer range. Default is 0.
35    pub fn min_count(&mut self, min_count: u8) -> &mut Self {
36        if self.min_count != min_count {
37            self.min_count = min_count;
38        }
39        self
40    }
41
42    /// Set the upper bound of the integer range. Default is 9.
43    pub fn max_count(&mut self, max_count: u8) -> &mut Self {
44        if self.max_count != max_count {
45            self.max_count = max_count;
46        }
47        self
48    }
49
50    pub fn item_prefix<S: Into<String>>(&mut self, item_prefix: S) -> &mut Self {
51        self.item_prefix = Some(item_prefix.into());
52        self
53    }
54
55    pub fn disallowed_char(&mut self, disallowed_char: char) -> &mut Self {
56        self.disallowed_chars.push(disallowed_char);
57        self
58    }
59
60    pub fn disallowed_chars(&mut self, disallowed_chars: Vec<char>) -> &mut Self {
61        self.disallowed_chars.extend(disallowed_chars);
62        self
63    }
64
65    fn grammar_inner(&self) -> TextListGrammar {
66        Grammar::text_list()
67            .item_token_length(self.text_token_length)
68            .min_count(self.min_count)
69            .max_count(self.max_count)
70            .item_prefix_option(self.item_prefix.clone())
71            .disallowed_chars(self.disallowed_chars.clone())
72    }
73}
74
75pub struct TextListType(Vec<String>);
76
77impl std::fmt::Display for TextListType {
78    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
79        write!(f, "{}", self.0.join(", "))
80    }
81}
82impl IntoIterator for TextListType {
83    type Item = String;
84    type IntoIter = IntoIter<String>;
85
86    fn into_iter(self) -> Self::IntoIter {
87        self.0.into_iter()
88    }
89}
90
91impl<'a> IntoIterator for &'a TextListType {
92    type Item = &'a String;
93    type IntoIter = Iter<'a, String>;
94
95    fn into_iter(self) -> Self::IntoIter {
96        self.0.iter()
97    }
98}
99
100impl<'a> IntoIterator for &'a mut TextListType {
101    type Item = &'a mut String;
102    type IntoIter = IterMut<'a, String>;
103
104    fn into_iter(self) -> Self::IntoIter {
105        self.0.iter_mut()
106    }
107}
108
109impl PrimitiveTrait for TextListPrimitive {
110    type PrimitiveResult = TextListType;
111
112    fn clear_primitive(&mut self) {}
113
114    fn type_description(&self, result_can_be_none: bool) -> &str {
115        if result_can_be_none {
116            "list items or 'None.'"
117        } else {
118            "list items"
119        }
120    }
121
122    fn solution_description(&self, result_can_be_none: bool) -> String {
123        if result_can_be_none {
124            format!(
125                "between {}-{} list items, or, possibly, 'None.'",
126                self.min_count, self.max_count
127            )
128        } else {
129            format!("between {}-{} list items", self.min_count, self.max_count)
130        }
131    }
132
133    fn stop_word_result_is_none(&self, result_can_be_none: bool) -> Option<String> {
134        if result_can_be_none {
135            Some("None.".to_string())
136        } else {
137            None
138        }
139    }
140
141    fn grammar(&self) -> Grammar {
142        self.grammar_inner().wrap()
143    }
144
145    fn parse_to_primitive(&self, content: &str) -> Result<Self::PrimitiveResult> {
146        let parsed: Self::PrimitiveResult =
147            TextListType(self.grammar_inner().grammar_parse(content)?);
148        Ok(parsed)
149    }
150}