mod_installer/
weidu_parser.rs1use std::{
2 sync::{
3 atomic::{AtomicUsize, Ordering},
4 mpsc::{Receiver, Sender, TryRecvError},
5 Arc, RwLock,
6 },
7 thread,
8};
9
10use crate::{config::parser_config::ParserConfig, state::State, utils::sleep};
11
12#[derive(Debug)]
13enum ParserState {
14 CollectingQuestion,
15 WaitingForMoreQuestionContent,
16 LookingForInterestingOutput,
17}
18
19pub(crate) fn parse_raw_output(
20 sender: Sender<State>,
21 receiver: Receiver<String>,
22 parser_config: Arc<ParserConfig>,
23 wait_count: Arc<AtomicUsize>,
24 log: Arc<RwLock<String>>,
25 timeout: usize,
26) {
27 let mut current_state = ParserState::LookingForInterestingOutput;
28 let mut question = String::new();
29 sender
30 .send(State::InProgress)
31 .expect("Failed to send process start event");
32 thread::spawn(move || loop {
33 match receiver.try_recv() {
34 Ok(string) => match current_state {
35 ParserState::CollectingQuestion | ParserState::WaitingForMoreQuestionContent => {
36 if let Ok(mut writer) = log.write() {
37 writer.push_str(&string);
38 }
39 if parser_config.useful_status_words.contains(&string) {
40 log::debug!(
41 "Weidu seems to know an answer for the last question, ignoring it"
42 );
43 current_state = ParserState::LookingForInterestingOutput;
44 question.clear();
45 } else {
46 log::debug!("Appending line '{}' to user question", string);
47 question.push_str(&string);
48 current_state = ParserState::CollectingQuestion;
49 }
50 }
51 ParserState::LookingForInterestingOutput => {
52 if let Ok(mut writer) = log.write() {
53 writer.push_str(&string);
54 }
55 if let Some(weidu_finished_state) =
56 parser_config.detect_weidu_finished_state(&string)
57 {
58 sender
59 .send(weidu_finished_state)
60 .expect("Failed to send process error event");
61 break;
62 } else if parser_config.string_looks_like_question(&string) {
63 log::debug!(
64 "Changing parser state to '{:?}' due to line {}",
65 ParserState::CollectingQuestion,
66 string
67 );
68 current_state = ParserState::CollectingQuestion;
69 question.push_str(string.as_str());
70 }
71 if !string.trim().is_empty() {
72 log::trace!("{}", string);
73 }
74 }
75 },
76 Err(TryRecvError::Empty) => {
77 match current_state {
78 ParserState::CollectingQuestion => {
79 log::debug!(
80 "Changing parser state to '{:?}'",
81 ParserState::WaitingForMoreQuestionContent
82 );
83 current_state = ParserState::WaitingForMoreQuestionContent;
84 }
85 ParserState::WaitingForMoreQuestionContent => {
86 log::debug!("No new weidu output, sending question to user");
87 sender
88 .send(State::RequiresInput { question })
89 .expect("Failed to send question");
90 current_state = ParserState::LookingForInterestingOutput;
91 question = String::new();
92 }
93 _ => {
94 if wait_count.load(Ordering::Relaxed) >= timeout {
95 sender
96 .send(State::TimedOut)
97 .expect("Could send timeout error");
98 }
99 }
101 }
102 sleep(100);
103 }
104 Err(TryRecvError::Disconnected) => {
105 sender
106 .send(State::Completed)
107 .expect("Failed to send provess end event");
108 break;
109 }
110 }
111 });
112}