Skip to content

Commit 78c6bd8

Browse files
authored
Add fn map(…) and fn map_ref(..) methods to Tree<T>
1 parent 95aaf8b commit 78c6bd8

File tree

3 files changed

+109
-1
lines changed

3 files changed

+109
-1
lines changed

src/lib.rs

+56
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,32 @@ impl<T> Node<T> {
9494
value,
9595
}
9696
}
97+
98+
pub fn map<F, U>(self, mut transform: F) -> Node<U>
99+
where
100+
F: FnMut(T) -> U,
101+
{
102+
Node {
103+
parent: self.parent,
104+
prev_sibling: self.prev_sibling,
105+
next_sibling: self.next_sibling,
106+
children: self.children,
107+
value: transform(self.value),
108+
}
109+
}
110+
111+
pub fn map_ref<F, U>(&self, mut transform: F) -> Node<U>
112+
where
113+
F: FnMut(&T) -> U,
114+
{
115+
Node {
116+
parent: self.parent,
117+
prev_sibling: self.prev_sibling,
118+
next_sibling: self.next_sibling,
119+
children: self.children,
120+
value: transform(&self.value),
121+
}
122+
}
97123
}
98124

99125
/// Node reference.
@@ -232,6 +258,36 @@ impl<T> Tree<T> {
232258
self.vec.extend(other_tree.vec);
233259
unsafe { self.get_unchecked_mut(other_tree_root_id) }
234260
}
261+
262+
/// Maps a `Tree<T>` to `Tree<U>` by applying a function to all node values,
263+
/// copying over the tree's structure and node ids untouched, consuming `self`.
264+
pub fn map<F, U>(self, mut transform: F) -> Tree<U>
265+
where
266+
F: FnMut(T) -> U,
267+
{
268+
Tree {
269+
vec: self
270+
.vec
271+
.into_iter()
272+
.map(|node| node.map(&mut transform))
273+
.collect(),
274+
}
275+
}
276+
277+
/// Maps a `&Tree<T>` to `Tree<U>` by applying a function to all node values,
278+
/// copying over the tree's structure and node ids untouched.
279+
pub fn map_ref<F, U>(&self, mut transform: F) -> Tree<U>
280+
where
281+
F: FnMut(&T) -> U,
282+
{
283+
Tree {
284+
vec: self
285+
.vec
286+
.iter()
287+
.map(|node| node.map_ref(&mut transform))
288+
.collect(),
289+
}
290+
}
235291
}
236292

237293
impl<'a, T: 'a> NodeRef<'a, T> {

src/serde.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl<'a, T> From<NodeRef<'a, T>> for SerNode<'a, T> {
2828
}
2929
}
3030

31-
impl<'a, T: Serialize> Serialize for SerNode<'a, T> {
31+
impl<T: Serialize> Serialize for SerNode<'_, T> {
3232
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3333
where
3434
S: serde::Serializer,

tests/tree.rs

+52
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,58 @@ fn insert_id_before() {
155155
assert_eq!(3, tree.root().children().count());
156156
}
157157

158+
#[test]
159+
fn test_map_values() {
160+
let str_tree = tree! {
161+
"root" => {
162+
"a" => {
163+
"child 1",
164+
},
165+
"b" => {
166+
"child 2",
167+
},
168+
}
169+
};
170+
171+
let identity_mapped_tree = str_tree.clone().map(|value| value);
172+
173+
// If we pass the identity function to `.map_values()`,
174+
// then we expect the tree to effectively remain untouched:
175+
assert_eq!(str_tree, identity_mapped_tree);
176+
177+
let string_tree = str_tree.clone().map(|value| value.to_owned());
178+
179+
// A `&str` will produce the same output for `.to_string()` as its equivalent `String`,
180+
// so the output of `.to_string()` should match for corresponding trees as well:
181+
assert_eq!(str_tree.to_string(), string_tree.to_string());
182+
}
183+
184+
#[test]
185+
fn test_map_value_refs() {
186+
let str_tree = tree! {
187+
"root" => {
188+
"a" => {
189+
"child 1",
190+
},
191+
"b" => {
192+
"child 2",
193+
},
194+
}
195+
};
196+
197+
let identity_mapped_tree = str_tree.map_ref(|&value| value);
198+
199+
// If we pass the identity function to `.map_values()`,
200+
// then we expect the tree to effectively remain untouched:
201+
assert_eq!(str_tree, identity_mapped_tree);
202+
203+
let string_tree = str_tree.map_ref(|&value| value.to_owned());
204+
205+
// A `&str` will produce the same output for `.to_string()` as its equivalent `String`,
206+
// so the output of `.to_string()` should match for corresponding trees as well:
207+
assert_eq!(str_tree.to_string(), string_tree.to_string());
208+
}
209+
158210
#[test]
159211
fn test_display() {
160212
let tree = tree! {

0 commit comments

Comments
 (0)