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