mf_transform/
transform.rs1use std::{sync::Arc};
2
3use mf_model::{node_pool::NodePool, schema::Schema, tree::Tree};
4
5use crate::TransformResult;
6
7use super::step::{Step, StepResult};
8
9#[derive(Debug, Clone)]
11enum LazyDoc {
12 Original(Arc<NodePool>),
14 Pending { base: Arc<NodePool>, steps: imbl::Vector<Arc<dyn Step>> },
16 Computed(Arc<NodePool>),
18}
19
20#[derive(Debug, Clone)]
21pub struct Transform {
22 pub base_doc: Arc<NodePool>,
24 lazy_doc: LazyDoc,
26 draft: Option<Tree>,
28 pub steps: imbl::Vector<Arc<dyn Step>>,
30 pub invert_steps: imbl::Vector<Arc<dyn Step>>,
32 pub schema: Arc<Schema>,
34 needs_recompute: bool,
36}
37
38impl Transform {
39 pub fn new(
40 doc: Arc<NodePool>,
41 schema: Arc<Schema>,
42 ) -> Transform {
43 Transform {
44 base_doc: doc.clone(),
45 lazy_doc: LazyDoc::Original(doc),
46 draft: None,
47 steps: imbl::Vector::new(),
48 invert_steps: imbl::Vector::new(),
49 schema,
50 needs_recompute: false,
51 }
52 }
53
54 pub fn doc(&self) -> Arc<NodePool> {
56 match &self.lazy_doc {
57 LazyDoc::Original(doc) => doc.clone(),
58 LazyDoc::Computed(doc) => doc.clone(),
59 LazyDoc::Pending { base, steps } => {
60 self.compute_doc_state(base.clone(), steps.clone())
62 },
63 }
64 }
65
66 fn get_draft(&mut self) -> &mut Tree {
68 if self.draft.is_none() {
69 self.draft = Some(self.base_doc.get_inner().as_ref().clone());
71 }
72 self.draft.as_mut().unwrap()
73 }
74
75 pub fn step(
76 &mut self,
77 step: Arc<dyn Step>,
78 ) -> TransformResult<()> {
79 let schema = self.schema.clone();
80 let draft = self.get_draft();
81 let result: StepResult = step.apply(draft, schema)?;
82
83 match result.failed {
84 Some(message) => Err(anyhow::anyhow!(message)),
85 None => {
86 self.add_step(step);
87 Ok(())
88 },
89 }
90 }
91
92 pub fn doc_changed(&self) -> bool {
94 !self.steps.is_empty()
95 }
96
97 fn add_step(
99 &mut self,
100 step: Arc<dyn Step>,
101 ) {
102 if let Some(invert_step) = step.invert(&self.base_doc.get_inner()) {
104 self.invert_steps.push_back(invert_step);
105 }
106
107 self.steps.push_back(step.clone());
108
109 self.lazy_doc = LazyDoc::Pending {
111 base: self.base_doc.clone(),
112 steps: self.steps.clone(),
113 };
114 self.needs_recompute = true;
115 }
116
117 fn compute_doc_state(
119 &self,
120 base: Arc<NodePool>,
121 steps: imbl::Vector<Arc<dyn Step>>,
122 ) -> Arc<NodePool> {
123 if steps.is_empty() {
124 return base;
125 }
126
127 if let Some(ref draft) = self.draft {
129 NodePool::new(Arc::new(draft.clone()))
130 } else {
131 base
132 }
133 }
134
135 pub fn apply_steps_batch(
137 &mut self,
138 steps: Vec<Arc<dyn Step>>,
139 ) -> TransformResult<()> {
140 let schema = self.schema.clone();
141 let base_doc_inner = self.base_doc.get_inner().clone();
142
143 let mut new_invert_steps = Vec::new();
145 for step in &steps {
146 if let Some(invert_step) = step.invert(&base_doc_inner) {
147 new_invert_steps.push(invert_step);
148 }
149 }
150
151 let draft = self.get_draft();
152
153 for step in &steps {
155 let result = step.apply(draft, schema.clone())?;
156 if let Some(message) = result.failed {
157 return Err(anyhow::anyhow!(message));
158 }
159 }
160
161 for step in steps {
163 self.steps.push_back(step);
164 }
165 for invert_step in new_invert_steps {
166 self.invert_steps.push_back(invert_step);
167 }
168
169 self.lazy_doc = LazyDoc::Pending {
171 base: self.base_doc.clone(),
172 steps: self.steps.clone(),
173 };
174 self.needs_recompute = true;
175
176 Ok(())
177 }
178
179 pub fn commit(&mut self) {
182 if self.needs_recompute && self.draft.is_some() {
183 let new_doc =
184 NodePool::new(Arc::new(self.draft.as_ref().unwrap().clone()));
185 self.base_doc = new_doc.clone();
186 self.lazy_doc = LazyDoc::Computed(new_doc);
187 self.draft = None;
188 self.needs_recompute = false;
190 }
191 }
192
193 pub fn rollback(&mut self) {
195 self.lazy_doc = LazyDoc::Original(self.base_doc.clone());
196 self.draft = None;
197 self.steps = imbl::Vector::new();
198 self.invert_steps = imbl::Vector::new();
199 self.needs_recompute = false;
200 }
201
202 pub fn rollback_steps(
204 &mut self,
205 count: usize,
206 ) -> TransformResult<()> {
207 if count > self.invert_steps.len() {
208 return Err(anyhow::anyhow!("回滚步骤数量超出历史记录"));
209 }
210
211 let schema = self.schema.clone();
212
213 let mut invert_steps_to_apply = Vec::new();
215 for _ in 0..count {
216 if let Some(invert_step) = self.invert_steps.pop_back() {
217 invert_steps_to_apply.push(invert_step);
218 self.steps.pop_back();
219 }
220 }
221
222 let draft = self.get_draft();
223
224 for invert_step in invert_steps_to_apply {
226 invert_step.apply(draft, schema.clone())?;
227 }
228
229 self.needs_recompute = true;
230 Ok(())
231 }
232
233 pub fn clear_history(&mut self) {
235 self.steps = imbl::Vector::new();
236 self.invert_steps = imbl::Vector::new();
237 }
238
239 pub fn history_size(&self) -> usize {
241 self.steps.len()
242 }
243}