mf_transform/
transform.rs

1use 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/// 延迟计算的文档状态
10#[derive(Debug, Clone)]
11enum LazyDoc {
12    /// 原始文档,未进行任何修改
13    Original(Arc<NodePool>),
14    /// 需要重新计算的状态,包含基础文档和待应用的步骤
15    Pending { base: Arc<NodePool>, steps: imbl::Vector<Arc<dyn Step>> },
16    /// 已计算的最新状态
17    Computed(Arc<NodePool>),
18}
19
20#[derive(Debug, Clone)]
21pub struct Transform {
22    /// 原始文档状态
23    pub base_doc: Arc<NodePool>,
24    /// 延迟计算的当前文档状态
25    lazy_doc: LazyDoc,
26    /// 文档的草稿状态,用于临时修改 (Copy-on-Write)
27    draft: Option<Tree>,
28    /// 存储所有操作步骤
29    pub steps: imbl::Vector<Arc<dyn Step>>,
30    /// 存储所有反向操作步骤
31    pub invert_steps: imbl::Vector<Arc<dyn Step>>,
32    /// 文档的模式定义
33    pub schema: Arc<Schema>,
34    /// 标记是否需要重新计算文档状态
35    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    /// 获取当前文档状态,使用延迟计算
55    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                // 延迟计算:只有在需要时才重新计算文档状态
61                self.compute_doc_state(base.clone(), steps.clone())
62            },
63        }
64    }
65
66    /// 获取草稿状态,使用 Copy-on-Write
67    fn get_draft(&mut self) -> &mut Tree {
68        if self.draft.is_none() {
69            // 只有在第一次修改时才克隆
70            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    /// 检查文档是否被修改
93    pub fn doc_changed(&self) -> bool {
94        !self.steps.is_empty()
95    }
96
97    /// 添加一个步骤及其结果到事务中
98    fn add_step(
99        &mut self,
100        step: Arc<dyn Step>,
101    ) {
102        // 生成反向步骤
103        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        // 标记需要延迟重新计算,而不是立即计算
110        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    /// 强制重新计算文档状态(私有方法)
118    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        // 只有在真正需要时才进行计算
128        if let Some(ref draft) = self.draft {
129            NodePool::new(Arc::new(draft.clone()))
130        } else {
131            base
132        }
133    }
134
135    /// 批量应用步骤(优化版本)
136    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        // 收集反向步骤
144        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        // 批量应用,减少中间状态创建
154        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        // 更新步骤列表
162        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        // 只在最后更新状态
170        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    /// 提交更改,将当前状态设为新的基础状态
180    /// 保留历史记录(steps 和 invert_steps)以支持回滚功能
181    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            // 保留 steps 和 invert_steps 用于历史记录和回滚
189            self.needs_recompute = false;
190        }
191    }
192
193    /// 回滚所有未提交的更改
194    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    /// 回滚指定数量的步骤
203    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        // 收集要应用的反向步骤
214        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        // 应用反向步骤
225        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    /// 清除历史记录(释放内存)
234    pub fn clear_history(&mut self) {
235        self.steps = imbl::Vector::new();
236        self.invert_steps = imbl::Vector::new();
237    }
238
239    /// 获取历史记录大小
240    pub fn history_size(&self) -> usize {
241        self.steps.len()
242    }
243}