moduforge_transform/
transform.rs

1use std::{sync::Arc};
2
3use moduforge_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 {
16        base: Arc<NodePool>,
17        steps: im::Vector<Arc<dyn Step>>,
18    },
19    /// 已计算的最新状态
20    Computed(Arc<NodePool>),
21}
22
23#[derive(Debug, Clone)]
24pub struct Transform {
25    /// 原始文档状态
26    pub base_doc: Arc<NodePool>,
27    /// 延迟计算的当前文档状态
28    lazy_doc: LazyDoc,
29    /// 文档的草稿状态,用于临时修改 (Copy-on-Write)
30    draft: Option<Tree>,
31    /// 存储所有操作步骤
32    pub steps: im::Vector<Arc<dyn Step>>,
33    /// 存储所有反向操作步骤
34    pub invert_steps: im::Vector<Arc<dyn Step>>,
35    /// 文档的模式定义
36    pub schema: Arc<Schema>,
37    /// 标记是否需要重新计算文档状态
38    needs_recompute: bool,
39}
40
41impl Transform {
42    pub fn new(
43        doc: Arc<NodePool>,
44        schema: Arc<Schema>,
45    ) -> Transform {
46        Transform {
47            base_doc: doc.clone(),
48            lazy_doc: LazyDoc::Original(doc),
49            draft: None,
50            steps: im::Vector::new(),
51            invert_steps: im::Vector::new(),
52            schema,
53            needs_recompute: false,
54        }
55    }
56
57    /// 获取当前文档状态,使用延迟计算
58    pub fn doc(&self) -> Arc<NodePool> {
59        match &self.lazy_doc {
60            LazyDoc::Original(doc) => doc.clone(),
61            LazyDoc::Computed(doc) => doc.clone(),
62            LazyDoc::Pending { base, steps } => {
63                // 延迟计算:只有在需要时才重新计算文档状态
64                self.compute_doc_state(base.clone(), steps.clone())
65            }
66        }
67    }
68
69    /// 获取草稿状态,使用 Copy-on-Write
70    fn get_draft(&mut self) -> &mut Tree {
71        if self.draft.is_none() {
72            // 只有在第一次修改时才克隆
73            self.draft = Some(self.base_doc.get_inner().as_ref().clone());
74        }
75        self.draft.as_mut().unwrap()
76    }
77
78    pub fn step(
79        &mut self,
80        step: Arc<dyn Step>,
81    ) -> TransformResult<()> {
82        let schema = self.schema.clone();
83        let draft = self.get_draft();
84        let result: StepResult = step.apply(draft, schema)?;
85        
86        match result.failed {
87            Some(message) => Err(anyhow::anyhow!(message)),
88            None => {
89                self.add_step(step);
90                Ok(())
91            },
92        }
93    }
94
95    /// 检查文档是否被修改
96    pub fn doc_changed(&self) -> bool {
97        !self.steps.is_empty()
98    }
99
100    /// 添加一个步骤及其结果到事务中
101    fn add_step(&mut self, step: Arc<dyn Step>) {
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: im::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(&mut self, steps: Vec<Arc<dyn Step>>) -> TransformResult<()> {
137        let schema = self.schema.clone();
138        let base_doc_inner = self.base_doc.get_inner().clone();
139        
140        // 收集反向步骤
141        let mut new_invert_steps = Vec::new();
142        for step in &steps {
143            if let Some(invert_step) = step.invert(&base_doc_inner) {
144                new_invert_steps.push(invert_step);
145            }
146        }
147        
148        let draft = self.get_draft();
149        
150        // 批量应用,减少中间状态创建
151        for step in &steps {
152            let result = step.apply(draft, schema.clone())?;
153            if let Some(message) = result.failed {
154                return Err(anyhow::anyhow!(message));
155            }
156        }
157        
158        // 更新步骤列表
159        for step in steps {
160            self.steps.push_back(step);
161        }
162        for invert_step in new_invert_steps {
163            self.invert_steps.push_back(invert_step);
164        }
165
166        // 只在最后更新状态
167        self.lazy_doc = LazyDoc::Pending {
168            base: self.base_doc.clone(),
169            steps: self.steps.clone(),
170        };
171        self.needs_recompute = true;
172        
173        Ok(())
174    }
175
176    /// 提交更改,将当前状态设为新的基础状态
177    /// 保留历史记录(steps 和 invert_steps)以支持回滚功能
178    pub fn commit(&mut self) {
179        if self.needs_recompute && self.draft.is_some() {
180            let new_doc = NodePool::new(Arc::new(self.draft.as_ref().unwrap().clone()));
181            self.base_doc = new_doc.clone();
182            self.lazy_doc = LazyDoc::Computed(new_doc);
183            self.draft = None;
184            // 保留 steps 和 invert_steps 用于历史记录和回滚
185            self.needs_recompute = false;
186        }
187    }
188
189    /// 回滚所有未提交的更改
190    pub fn rollback(&mut self) {
191        self.lazy_doc = LazyDoc::Original(self.base_doc.clone());
192        self.draft = None;
193        self.steps = im::Vector::new();
194        self.invert_steps = im::Vector::new();
195        self.needs_recompute = false;
196    }
197
198    /// 回滚指定数量的步骤
199    pub fn rollback_steps(&mut self, count: usize) -> TransformResult<()> {
200        if count > self.invert_steps.len() {
201            return Err(anyhow::anyhow!("回滚步骤数量超出历史记录"));
202        }
203
204        let schema = self.schema.clone();
205        
206        // 收集要应用的反向步骤
207        let mut invert_steps_to_apply = Vec::new();
208        for _ in 0..count {
209            if let Some(invert_step) = self.invert_steps.pop_back() {
210                invert_steps_to_apply.push(invert_step);
211                self.steps.pop_back();
212            }
213        }
214
215        let draft = self.get_draft();
216        
217        // 应用反向步骤
218        for invert_step in invert_steps_to_apply {
219            invert_step.apply(draft, schema.clone())?;
220        }
221
222        self.needs_recompute = true;
223        Ok(())
224    }
225
226    /// 清除历史记录(释放内存)
227    pub fn clear_history(&mut self) {
228        self.steps = im::Vector::new();
229        self.invert_steps = im::Vector::new();
230    }
231
232    /// 获取历史记录大小
233    pub fn history_size(&self) -> usize {
234        self.steps.len()
235    }
236}