pdf_ast/transform/
operations.rs1use super::*;
2use crate::ast::{AstNode, NodeId, PdfAstGraph};
3use crate::types::PdfValue;
4
5#[derive(Debug, Clone)]
7pub enum TransformOperation {
8 ReplaceNode { target: NodeId, new_node: AstNode },
10 InsertChild {
12 parent: NodeId,
13 child: AstNode,
14 position: Option<usize>,
15 },
16 RemoveNode {
18 target: NodeId,
19 preserve_children: bool,
20 },
21 MoveNode {
23 target: NodeId,
24 new_parent: NodeId,
25 position: Option<usize>,
26 },
27 UpdateValue { target: NodeId, new_value: PdfValue },
29 Batch(Vec<TransformOperation>),
31}
32
33impl TransformOperation {
34 pub fn apply(&self, graph: &mut PdfAstGraph) -> AstResult<()> {
36 match self {
37 TransformOperation::ReplaceNode { target, new_node } => {
38 graph.replace_node(*target, new_node.clone())?;
39 }
40 TransformOperation::InsertChild {
41 parent,
42 child,
43 position,
44 } => {
45 let child_id = graph.create_node(child.node_type.clone(), child.value.clone());
46 graph.add_edge(*parent, child_id, crate::ast::EdgeType::Child);
47
48 let _ = position;
50 }
51 TransformOperation::RemoveNode {
52 target,
53 preserve_children,
54 } => {
55 if *preserve_children {
56 let children = graph.get_children(*target);
58 if let Some(parent_id) = graph.get_parent(*target) {
59 for child_id in children {
60 graph.remove_edge(*target, child_id);
61 graph.add_edge(parent_id, child_id, crate::ast::EdgeType::Child);
62 }
63 }
64 }
65 graph.remove_node(*target);
66 }
67 TransformOperation::MoveNode {
68 target,
69 new_parent,
70 position,
71 } => {
72 if let Some(old_parent) = graph.get_parent(*target) {
74 graph.remove_edge(old_parent, *target);
75 }
76
77 graph.add_edge(*new_parent, *target, crate::ast::EdgeType::Child);
79
80 let _ = position;
82 }
83 TransformOperation::UpdateValue { target, new_value } => {
84 if let Some(node) = graph.get_node_mut(*target) {
85 node.value = new_value.clone();
86 } else {
87 return Err(AstError::NodeNotFound(format!("Node {:?}", target)));
88 }
89 }
90 TransformOperation::Batch(operations) => {
91 for operation in operations {
92 operation.apply(graph)?;
93 }
94 }
95 }
96 Ok(())
97 }
98
99 pub fn replace(target: NodeId, new_node: AstNode) -> Self {
101 TransformOperation::ReplaceNode { target, new_node }
102 }
103
104 pub fn insert(parent: NodeId, child: AstNode) -> Self {
106 TransformOperation::InsertChild {
107 parent,
108 child,
109 position: None,
110 }
111 }
112
113 pub fn insert_at(parent: NodeId, child: AstNode, position: usize) -> Self {
115 TransformOperation::InsertChild {
116 parent,
117 child,
118 position: Some(position),
119 }
120 }
121
122 pub fn remove(target: NodeId) -> Self {
124 TransformOperation::RemoveNode {
125 target,
126 preserve_children: false,
127 }
128 }
129
130 pub fn remove_preserve_children(target: NodeId) -> Self {
132 TransformOperation::RemoveNode {
133 target,
134 preserve_children: true,
135 }
136 }
137
138 pub fn move_node(target: NodeId, new_parent: NodeId) -> Self {
140 TransformOperation::MoveNode {
141 target,
142 new_parent,
143 position: None,
144 }
145 }
146
147 pub fn move_to_position(target: NodeId, new_parent: NodeId, position: usize) -> Self {
149 TransformOperation::MoveNode {
150 target,
151 new_parent,
152 position: Some(position),
153 }
154 }
155
156 pub fn update_value(target: NodeId, new_value: PdfValue) -> Self {
158 TransformOperation::UpdateValue { target, new_value }
159 }
160
161 pub fn batch(operations: Vec<TransformOperation>) -> Self {
163 TransformOperation::Batch(operations)
164 }
165}