1 | #![allow (missing_docs)] |
2 | |
3 | //! Document tree traversal to mutate an exclusive borrow of a document tree in place. |
4 | //! |
5 | //! |
6 | //! Each method of the [`VisitMut`] trait is a hook that can be overridden |
7 | //! to customize the behavior when mutating the corresponding type of node. |
8 | //! By default, every method recursively visits the substructure of the |
9 | //! input by invoking the right visitor method of each of its fields. |
10 | //! |
11 | //! ``` |
12 | //! # use toml_edit::{Item, ArrayOfTables, Table, Value}; |
13 | //! |
14 | //! pub trait VisitMut { |
15 | //! /* ... */ |
16 | //! |
17 | //! fn visit_item_mut(&mut self, i: &mut Item) { |
18 | //! visit_item_mut(self, i); |
19 | //! } |
20 | //! |
21 | //! /* ... */ |
22 | //! # fn visit_value_mut(&mut self, i: &mut Value); |
23 | //! # fn visit_table_mut(&mut self, i: &mut Table); |
24 | //! # fn visit_array_of_tables_mut(&mut self, i: &mut ArrayOfTables); |
25 | //! } |
26 | //! |
27 | //! pub fn visit_item_mut<V>(v: &mut V, node: &mut Item) |
28 | //! where |
29 | //! V: VisitMut + ?Sized, |
30 | //! { |
31 | //! match node { |
32 | //! Item::None => {} |
33 | //! Item::Value(value) => v.visit_value_mut(value), |
34 | //! Item::Table(table) => v.visit_table_mut(table), |
35 | //! Item::ArrayOfTables(array) => v.visit_array_of_tables_mut(array), |
36 | //! } |
37 | //! } |
38 | //! ``` |
39 | //! |
40 | //! The API is modeled after [`syn::visit_mut`](https://docs.rs/syn/1/syn/visit_mut). |
41 | //! |
42 | //! # Examples |
43 | //! |
44 | //! This visitor replaces every floating point value with its decimal string representation, to |
45 | //! 2 decimal points. |
46 | //! |
47 | //! ``` |
48 | //! # use toml_edit::*; |
49 | //! use toml_edit::visit_mut::*; |
50 | //! |
51 | //! struct FloatToString; |
52 | //! |
53 | //! impl VisitMut for FloatToString { |
54 | //! fn visit_value_mut(&mut self, node: &mut Value) { |
55 | //! if let Value::Float(f) = node { |
56 | //! // Convert the float to a string. |
57 | //! let mut s = Formatted::new(format!("{:.2}" , f.value())); |
58 | //! // Copy over the formatting. |
59 | //! std::mem::swap(s.decor_mut(), f.decor_mut()); |
60 | //! *node = Value::String(s); |
61 | //! } |
62 | //! // Most of the time, you will also need to call the default implementation to recurse |
63 | //! // further down the document tree. |
64 | //! visit_value_mut(self, node); |
65 | //! } |
66 | //! } |
67 | //! |
68 | //! let input = r#" |
69 | //! banana = 3.26 |
70 | //! table = { apple = 4.5 } |
71 | //! "# ; |
72 | //! |
73 | //! let mut document: Document = input.parse().unwrap(); |
74 | //! let mut visitor = FloatToString; |
75 | //! visitor.visit_document_mut(&mut document); |
76 | //! |
77 | //! let output = r#" |
78 | //! banana = "3.26" |
79 | //! table = { apple = "4.50" } |
80 | //! "# ; |
81 | //! |
82 | //! assert_eq!(format!("{}" , document), output); |
83 | //! ``` |
84 | //! |
85 | //! For a more complex example where the visitor has internal state, see `examples/visit.rs` |
86 | //! [on GitHub](https://github.com/ordian/toml_edit/blob/master/examples/visit.rs). |
87 | |
88 | use crate::{ |
89 | Array, ArrayOfTables, Datetime, Document, Formatted, InlineTable, Item, KeyMut, Table, |
90 | TableLike, Value, |
91 | }; |
92 | |
93 | /// Document tree traversal to mutate an exclusive borrow of a document tree in-place. |
94 | /// |
95 | /// See the [module documentation](self) for details. |
96 | pub trait VisitMut { |
97 | fn visit_document_mut(&mut self, node: &mut Document) { |
98 | visit_document_mut(self, node); |
99 | } |
100 | |
101 | fn visit_item_mut(&mut self, node: &mut Item) { |
102 | visit_item_mut(self, node); |
103 | } |
104 | |
105 | fn visit_table_mut(&mut self, node: &mut Table) { |
106 | visit_table_mut(self, node); |
107 | } |
108 | |
109 | fn visit_inline_table_mut(&mut self, node: &mut InlineTable) { |
110 | visit_inline_table_mut(self, node) |
111 | } |
112 | |
113 | /// [`visit_table_mut`](Self::visit_table_mut) and |
114 | /// [`visit_inline_table_mut`](Self::visit_inline_table_mut) both recurse into this method. |
115 | fn visit_table_like_mut(&mut self, node: &mut dyn TableLike) { |
116 | visit_table_like_mut(self, node); |
117 | } |
118 | |
119 | fn visit_table_like_kv_mut(&mut self, key: KeyMut<'_>, node: &mut Item) { |
120 | visit_table_like_kv_mut(self, key, node); |
121 | } |
122 | |
123 | fn visit_array_mut(&mut self, node: &mut Array) { |
124 | visit_array_mut(self, node); |
125 | } |
126 | |
127 | fn visit_array_of_tables_mut(&mut self, node: &mut ArrayOfTables) { |
128 | visit_array_of_tables_mut(self, node); |
129 | } |
130 | |
131 | fn visit_value_mut(&mut self, node: &mut Value) { |
132 | visit_value_mut(self, node); |
133 | } |
134 | |
135 | fn visit_boolean_mut(&mut self, node: &mut Formatted<bool>) { |
136 | visit_boolean_mut(self, node) |
137 | } |
138 | |
139 | fn visit_datetime_mut(&mut self, node: &mut Formatted<Datetime>) { |
140 | visit_datetime_mut(self, node); |
141 | } |
142 | |
143 | fn visit_float_mut(&mut self, node: &mut Formatted<f64>) { |
144 | visit_float_mut(self, node) |
145 | } |
146 | |
147 | fn visit_integer_mut(&mut self, node: &mut Formatted<i64>) { |
148 | visit_integer_mut(self, node) |
149 | } |
150 | |
151 | fn visit_string_mut(&mut self, node: &mut Formatted<String>) { |
152 | visit_string_mut(self, node) |
153 | } |
154 | } |
155 | |
156 | pub fn visit_document_mut<V>(v: &mut V, node: &mut Document) |
157 | where |
158 | V: VisitMut + ?Sized, |
159 | { |
160 | v.visit_table_mut(node:node.as_table_mut()); |
161 | } |
162 | |
163 | pub fn visit_item_mut<V>(v: &mut V, node: &mut Item) |
164 | where |
165 | V: VisitMut + ?Sized, |
166 | { |
167 | match node { |
168 | Item::None => {} |
169 | Item::Value(value: &mut Value) => v.visit_value_mut(node:value), |
170 | Item::Table(table: &mut Table) => v.visit_table_mut(node:table), |
171 | Item::ArrayOfTables(array: &mut ArrayOfTables) => v.visit_array_of_tables_mut(node:array), |
172 | } |
173 | } |
174 | |
175 | pub fn visit_table_mut<V>(v: &mut V, node: &mut Table) |
176 | where |
177 | V: VisitMut + ?Sized, |
178 | { |
179 | v.visit_table_like_mut(node); |
180 | } |
181 | |
182 | pub fn visit_inline_table_mut<V>(v: &mut V, node: &mut InlineTable) |
183 | where |
184 | V: VisitMut + ?Sized, |
185 | { |
186 | v.visit_table_like_mut(node); |
187 | } |
188 | |
189 | pub fn visit_table_like_mut<V>(v: &mut V, node: &mut dyn TableLike) |
190 | where |
191 | V: VisitMut + ?Sized, |
192 | { |
193 | for (key: KeyMut<'_>, item: &mut Item) in node.iter_mut() { |
194 | v.visit_table_like_kv_mut(key, node:item); |
195 | } |
196 | } |
197 | |
198 | pub fn visit_table_like_kv_mut<V>(v: &mut V, _key: KeyMut<'_>, node: &mut Item) |
199 | where |
200 | V: VisitMut + ?Sized, |
201 | { |
202 | v.visit_item_mut(node) |
203 | } |
204 | |
205 | pub fn visit_array_mut<V>(v: &mut V, node: &mut Array) |
206 | where |
207 | V: VisitMut + ?Sized, |
208 | { |
209 | for value: &mut Value in node.iter_mut() { |
210 | v.visit_value_mut(node:value); |
211 | } |
212 | } |
213 | |
214 | pub fn visit_array_of_tables_mut<V>(v: &mut V, node: &mut ArrayOfTables) |
215 | where |
216 | V: VisitMut + ?Sized, |
217 | { |
218 | for table: &mut Table in node.iter_mut() { |
219 | v.visit_table_mut(node:table); |
220 | } |
221 | } |
222 | |
223 | pub fn visit_value_mut<V>(v: &mut V, node: &mut Value) |
224 | where |
225 | V: VisitMut + ?Sized, |
226 | { |
227 | match node { |
228 | Value::String(s: &mut Formatted) => v.visit_string_mut(node:s), |
229 | Value::Integer(i: &mut Formatted) => v.visit_integer_mut(node:i), |
230 | Value::Float(f: &mut Formatted) => v.visit_float_mut(node:f), |
231 | Value::Boolean(b: &mut Formatted) => v.visit_boolean_mut(node:b), |
232 | Value::Datetime(dt: &mut Formatted) => v.visit_datetime_mut(node:dt), |
233 | Value::Array(array: &mut Array) => v.visit_array_mut(node:array), |
234 | Value::InlineTable(table: &mut InlineTable) => v.visit_inline_table_mut(node:table), |
235 | } |
236 | } |
237 | |
238 | macro_rules! empty_visit_mut { |
239 | ($name: ident, $t: ty) => { |
240 | fn $name<V>(_v: &mut V, _node: &mut $t) |
241 | where |
242 | V: VisitMut + ?Sized, |
243 | { |
244 | } |
245 | }; |
246 | } |
247 | |
248 | empty_visit_mut!(visit_boolean_mut, Formatted<bool>); |
249 | empty_visit_mut!(visit_datetime_mut, Formatted<Datetime>); |
250 | empty_visit_mut!(visit_float_mut, Formatted<f64>); |
251 | empty_visit_mut!(visit_integer_mut, Formatted<i64>); |
252 | empty_visit_mut!(visit_string_mut, Formatted<String>); |
253 | |