Skip to main content

rust_lstar/knowledge_base/
fake.rs

1use super::active::ActiveKnowledgeBase;
2use super::base::{KnowledgeBase, KnowledgeBaseTrait};
3use crate::automata::Automata;
4use crate::letter::Letter;
5use crate::query::OutputQuery;
6/// Fake active knowledge base implementation
7/// Uses a preset automata to simulate target behavior
8use crate::word::Word;
9
10/// A test implementation of an active knowledge base that uses a preset automata
11pub struct FakeActiveKnowledgeBase {
12    base: KnowledgeBase,
13    automata: Option<Automata>,
14    target_running: bool,
15}
16
17impl FakeActiveKnowledgeBase {
18    /// Creates a new fake active knowledge base with the given automata
19    pub fn new(automata: Automata) -> Self {
20        FakeActiveKnowledgeBase {
21            base: KnowledgeBase::new(),
22            automata: Some(automata),
23            target_running: false,
24        }
25    }
26
27    /// Gets a reference to the automata
28    pub fn automata(&self) -> Option<&Automata> {
29        self.automata.as_ref()
30    }
31
32    /// Sets a new automata
33    pub fn set_automata(&mut self, automata: Automata) {
34        self.automata = Some(automata);
35    }
36}
37
38impl ActiveKnowledgeBase for FakeActiveKnowledgeBase {
39    fn start_target(&mut self) -> Result<(), String> {
40        self.target_running = true;
41        Ok(())
42    }
43
44    fn stop_target(&mut self) -> Result<(), String> {
45        self.target_running = false;
46        Ok(())
47    }
48
49    fn submit_word(&mut self, word: &Word) -> Result<Word, String> {
50        if self.automata.is_none() {
51            return Err("Automata cannot be None".to_string());
52        }
53
54        let automata = self.automata.as_ref().unwrap();
55        let mut current_state = automata.initial_state.clone();
56        let mut output_letters = Vec::new();
57
58        for letter in word.letters() {
59            match current_state.visit(letter) {
60                Some((output_letter, next_state)) => {
61                    output_letters.push(output_letter.clone());
62                    current_state = next_state.clone();
63                }
64                None => {
65                    output_letters.push(Letter::new(""));
66                }
67            }
68        }
69
70        Ok(Word::from_letters(output_letters))
71    }
72
73    fn is_target_running(&self) -> bool {
74        self.target_running
75    }
76}
77
78impl KnowledgeBaseTrait for FakeActiveKnowledgeBase {
79    fn resolve_query(&mut self, query: &mut OutputQuery) -> Result<(), String> {
80        match self.base.resolve_query(query) {
81            Ok(_) => Ok(()),
82            Err(_) => {
83                self.start_target()?;
84                let submit_result = self.submit_word(&query.input_word);
85                let stop_result = self.stop_target();
86
87                let output = submit_result?;
88                stop_result?;
89
90                self.base.add_word(&query.input_word, &output)?;
91                query.set_result(output);
92                Ok(())
93            }
94        }
95    }
96
97    fn add_word(&mut self, input_word: &Word, output_word: &Word) -> Result<(), String> {
98        self.base.add_word(input_word, output_word)
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105
106    #[test]
107    fn test_creation() {
108        let automata = Automata::new(
109            crate::automata::State::new("S0".to_string()),
110            "test".to_string(),
111        );
112        let kb = FakeActiveKnowledgeBase::new(automata);
113        assert!(!kb.is_target_running());
114    }
115
116    #[test]
117    fn test_start_stop() {
118        let automata = Automata::new(
119            crate::automata::State::new("S0".to_string()),
120            "test".to_string(),
121        );
122        let mut kb = FakeActiveKnowledgeBase::new(automata);
123
124        assert!(!kb.is_target_running());
125        kb.start_target().unwrap();
126        assert!(kb.is_target_running());
127        kb.stop_target().unwrap();
128        assert!(!kb.is_target_running());
129    }
130}