darklua_core/frontend/
work_item.rs

1use std::path::{Path, PathBuf};
2
3use crate::{nodes::Block, utils::Timer};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub(crate) struct Progress {
7    block: Block,
8    next_rule: usize,
9    required: Vec<PathBuf>,
10    duration: Timer,
11}
12
13impl Progress {
14    pub fn new(block: Block) -> Self {
15        Self {
16            block,
17            next_rule: 0,
18            required: Vec::new(),
19            duration: Timer::now(),
20        }
21    }
22
23    pub fn with_content(self, content: String) -> WorkProgress {
24        WorkProgress {
25            content,
26            work: self,
27        }
28    }
29
30    pub fn at_rule(mut self, rule_index: usize) -> Self {
31        self.next_rule = rule_index;
32        self
33    }
34
35    pub fn with_required_content(mut self, required_content: Vec<PathBuf>) -> Self {
36        self.required = required_content;
37        self
38    }
39
40    pub fn next_rule(&self) -> usize {
41        self.next_rule
42    }
43
44    pub fn block(&self) -> &Block {
45        &self.block
46    }
47
48    pub fn mutate_block(&mut self) -> &mut Block {
49        &mut self.block
50    }
51
52    pub fn duration(&mut self) -> &mut Timer {
53        &mut self.duration
54    }
55}
56
57#[derive(Debug, Clone, PartialEq, Eq)]
58pub(crate) struct WorkProgress {
59    content: String,
60    work: Progress,
61}
62
63impl WorkProgress {
64    pub fn new(content: String, block: Block) -> Self {
65        Self {
66            content,
67            work: Progress::new(block),
68        }
69    }
70
71    pub fn required_content(&self) -> impl Iterator<Item = &Path> {
72        self.work.required.iter().map(AsRef::as_ref)
73    }
74
75    pub fn extract(self) -> (String, Progress) {
76        (self.content, self.work)
77    }
78}
79
80#[derive(Debug, Clone, PartialEq, Eq)]
81pub(crate) enum WorkStatus {
82    NotStarted,
83    InProgress(Box<WorkProgress>),
84}
85
86impl Default for WorkStatus {
87    fn default() -> Self {
88        Self::NotStarted
89    }
90}
91
92impl From<WorkProgress> for WorkStatus {
93    fn from(progress: WorkProgress) -> Self {
94        Self::InProgress(Box::new(progress))
95    }
96}
97
98#[derive(Debug, Clone)]
99pub(crate) struct WorkData {
100    source: PathBuf,
101    output: PathBuf,
102}
103
104impl WorkData {
105    pub fn with_status(self, status: impl Into<WorkStatus>) -> WorkItem {
106        WorkItem {
107            data: self,
108            status: status.into(),
109        }
110    }
111
112    pub fn source(&self) -> &Path {
113        &self.source
114    }
115
116    pub fn output(&self) -> &Path {
117        &self.output
118    }
119}
120
121#[derive(Debug, Clone)]
122pub(crate) struct WorkItem {
123    data: WorkData,
124    status: WorkStatus,
125}
126
127impl WorkItem {
128    pub fn new(source: impl Into<PathBuf>, output: impl Into<PathBuf>) -> Self {
129        Self {
130            data: WorkData {
131                source: source.into(),
132                output: output.into(),
133            },
134            status: Default::default(),
135        }
136    }
137
138    pub fn new_in_place(source: impl Into<PathBuf>) -> Self {
139        let source = source.into();
140        Self::new(source.clone(), source)
141    }
142
143    pub fn extract(self) -> (WorkStatus, WorkData) {
144        (self.status, self.data)
145    }
146
147    pub fn source(&self) -> &Path {
148        &self.data.source
149    }
150
151    pub fn get_created_file_path(&self) -> Option<PathBuf> {
152        if self.data.source == self.data.output {
153            None
154        } else {
155            Some(self.data.output.to_path_buf())
156        }
157    }
158
159    pub fn total_required_content(&self) -> usize {
160        match &self.status {
161            WorkStatus::NotStarted => 0,
162            WorkStatus::InProgress(progress) => progress.work.required.len(),
163        }
164    }
165}