forrust_fire_tree 0.1.2

A tree data structure
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
//! Immutable tree data structure.
//!
//! See [Ashes].

use std::{
    fmt::{self, Debug, Display},
    ops::Range,
};

#[cfg(feature = "serde")]
pub mod serde;

define_branch_id!(
    /// The ID for some branch of a [`Ashes`].
    ///
    /// Branch IDs should generally only be used within the tree where they
    /// were obtained, but, technically speaking, there is nothing barring
    /// you from doing it anyway.
    struct BranchId
);

#[derive(Clone, Copy, Debug)]
struct RootInfo<'a> {
    children: &'a Range<usize>,
}

/// Shared reference to a branch of [Ashes].
#[derive(Debug)]
pub struct BranchRef<'a, T> {
    // None for <root>
    node: Result<&'a Node<T>, RootInfo<'a>>,
}

impl<'a, T> Clone for BranchRef<'a, T> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<'a, T> Copy for BranchRef<'a, T> {}

impl<'a, T> BranchRef<'a, T> {
    /// Returns whether this is the root branch.
    pub fn is_root(self) -> bool {
        self.node.is_err()
    }

    /// Returns the parent of this branch, or `None` if it is root.
    pub fn parent(self) -> Option<BranchId> {
        match self.node {
            Ok(node) => Some(node.parent),
            Err(_) => None,
        }
    }

    /// Returns the payload of this branch, or `None` if it is root.
    pub fn payload(self) -> Option<&'a T> {
        match self.node {
            Ok(node) => Some(&node.payload),
            Err(_) => None,
        }
    }

    /// Returns an iterator of child IDs for this branch.
    pub fn child_iter(self) -> impl Iterator<Item = BranchId> {
        let range = Range::clone(match self.node {
            Ok(v) => &v.children,
            Err(r) => r.children,
        });
        range.map(BranchId::new_branch)
    }

    /// Returns the range of IDs which are all children of this node.
    pub fn children(self) -> Range<BranchId> {
        let range = match self.node {
            Ok(node) => &node.children,
            Err(root) => root.children,
        };
        child_range(range)
    }

    /// Returns how many children this node has.
    pub fn n_children(self) -> usize {
        children_len(self.children())
    }

    /// Returns the `n`th child's ID.
    pub fn child(self, n: usize) -> BranchId {
        nth_child(self.children(), n)
    }
}

fn children_len(r: Range<BranchId>) -> usize {
    // todo: maybe unchecked_sub?
    r.end.value() - r.start.value()
}

fn nth_child(range: Range<BranchId>, idx: usize) -> BranchId {
    let target = match range.start.value().checked_add(idx) {
        Some(v) => v,
        None => panic!(
            "the given child # ({idx}), when added to the child index start ({}), overflows usize",
            range.start.value()
        ),
    };
    let target = BranchId::new_branch(target);
    if !range.contains(&target) {
        panic!(
            "there are only {} children, but tried access #{idx}",
            range.end.value() - range.start.value()
        )
    }
    target
}

/// Mutable reference to a branch of [Ashes].
#[derive(Debug)]
pub struct BranchMut<'a, T> {
    // None for <root>
    node: Result<&'a mut Node<T>, RootInfo<'a>>,
}

impl<'a, T> BranchMut<'a, T> {
    /// Returns whether this is the root branch.
    pub fn is_root(&self) -> bool {
        self.node.is_err()
    }

    /// Returns the parent of this branch, or `None` if it is root.
    pub fn parent(&self) -> Option<BranchId> {
        match &self.node {
            Ok(node) => Some(node.parent),
            Err(_) => None,
        }
    }

    /// Returns the payload of this branch, or `None` if it is root.
    pub fn payload(&mut self) -> Option<&mut T> {
        match &mut self.node {
            Ok(node) => Some(&mut node.payload),
            Err(_) => None,
        }
    }

    /// Returns the range of IDs which are all children of this node.
    pub fn children(&self) -> Range<BranchId> {
        let range = match &self.node {
            Ok(node) => &node.children,
            Err(root) => root.children,
        };
        child_range(range)
    }

    /// Returns how many children this node has.
    pub fn children_len(&self) -> usize {
        children_len(self.children())
    }

    /// Returns the `n`th child's ID.
    pub fn child(&self, idx: usize) -> BranchId {
        nth_child(self.children(), idx)
    }
}

fn child_range(original: &Range<usize>) -> Range<BranchId> {
    BranchId::new_branch(original.start)..BranchId::new_branch(original.end)
}

#[derive(Debug, Clone)]
pub(crate) struct Node<T> {
    pub(crate) parent: BranchId,
    pub(crate) payload: T,
    pub(crate) children: Range<usize>,
    // note: do not rely on this being set!!
    //       the deserialization implementation simply sets this to usize::MAX
    //       this field is only meant for the `ForestFire::burn` impl
    pub(crate) old_idx: usize,
}

/// Immutable tree data structure.
///
/// While the tree's structure is immutable, the node values are fully available
/// through mutable references. For a mutable tree data structure, see [ForestFire].
///
/// `Ashes` may be serialized & deserialized; see [serde] (only available with the
/// `serde` feature enabled).
///
/// [ForestFire]: crate::fire::ForestFire
#[derive(Debug, Clone)]
pub struct Ashes<T> {
    pub(crate) nodes: Vec<Node<T>>,
    pub(crate) root_children: Range<usize>,
}

impl<T> Ashes<T> {
    /// Constructs a new, empty `Ashes<T>`.
    ///
    /// This is likely useless as `Ashes` cannot be inserted into, but some situations
    /// require it.
    pub const fn new() -> Self {
        Self {
            nodes: Vec::new(),
            root_children: 0..0,
        }
    }

    /// Clears this tree.
    pub fn clear(&mut self) {
        self.root_children = 0..0;
        self.nodes.clear();
    }

    /// Checks whether there is a branch with the given branch ID.
    ///
    /// Branch IDs given out by an `Ashes` are valid for the entirety of that `Ashes`'s lifetime, so
    /// there is never a need to check if you're sure your branch ID came from this exact `Ashes`
    /// instance.
    ///
    /// Always returns `true` for [`BranchId::ROOT`].
    pub fn exists(&self, branch: BranchId) -> bool {
        if branch.is_root() {
            return true;
        }

        self.nodes.get(branch.value()).is_some()
    }

    /// Returns a shared reference to the root branch.
    pub fn root<'a>(&'a self) -> BranchRef<'a, T> {
        BranchRef {
            node: Err(RootInfo {
                children: &self.root_children,
            }),
        }
    }

    /// Returns a shared reference to the branch with the given ID.
    ///
    /// # Panics
    ///
    /// Panics if `branch` is not an [existing](Self::exists) branch.
    pub fn branch<'a>(&'a self, branch: BranchId) -> BranchRef<'a, T> {
        if branch.is_root() {
            self.root()
        } else {
            BranchRef {
                node: Ok(self
                    .nodes
                    .get(branch.value())
                    .unwrap_or_else(|| branch.indexing_panic())),
            }
        }
    }

    /// Returns a mutable reference to the root branch.
    pub fn root_mut<'a>(&'a mut self) -> BranchMut<'a, T> {
        BranchMut {
            node: Err(RootInfo {
                children: &self.root_children,
            }),
        }
    }

    /// Returns a mutable reference to the branch with the given ID.
    ///
    /// # Panics
    ///
    /// Panics if `branch` is not an [existing](Self::exists) branch.
    pub fn branch_mut<'a>(&'a mut self, branch: BranchId) -> BranchMut<'a, T> {
        if branch.is_root() {
            self.root_mut()
        } else {
            BranchMut {
                node: Ok(self
                    .nodes
                    .get_mut(branch.value())
                    .unwrap_or_else(|| branch.indexing_panic())),
            }
        }
    }

    /// Returns a range of root's child IDs.
    pub fn root_children(&self) -> Range<BranchId> {
        child_range(&self.root_children)
    }

    /// Returns an object which can be used to print the tree contents in a somewhat
    /// human-friendly format.
    ///
    /// The `print_value` function defines how the actual value is printed. In order of
    /// appearance, its parameters are:
    /// - `formatter: &mut fmt::Formatter`
    ///     - The formatter to write data into.
    /// - `payload: Option<&T>`
    ///     - The payload placed in the node currently being printed. `None` for root.
    /// - `depth: usize`
    ///     - The depth of the node within the tree. Starts at `0` for root.
    ///
    /// For values which already implement [`Debug`], see [`print_tree_debug`], or
    /// [`print_tree_display`] for [`Display`].
    ///
    /// [`print_tree_debug`]: #method.print_tree_debug
    /// [`print_tree_display`]: #method.print_tree_display
    pub fn print_tree<F: Fn(&mut fmt::Formatter, Option<&T>, usize) -> fmt::Result>(
        &self,
        print_value: F,
    ) -> PrintTree<'_, T, F> {
        PrintTree {
            ashes: self,
            print_value,
        }
    }

    /// Returns an object which can be used to print the tree contents in a somewhat
    /// human-friendly format.
    ///
    /// The values are printed using their [`Debug`] implementation; for further
    /// customization, see [`print_tree`].
    ///
    /// [`print_tree`]: #method.print_tree
    pub fn print_tree_debug(
        &self,
    ) -> PrintTree<'_, T, impl Fn(&mut fmt::Formatter, Option<&T>, usize) -> fmt::Result>
    where
        T: Debug,
    {
        PrintTree {
            ashes: self,
            print_value: |f, v, indent| {
                for _ in 0..(indent.saturating_mul(2)) {
                    write!(f, "-")?;
                }
                if let Some(v) = v {
                    writeln!(f, "{v:?}:")?;
                } else {
                    writeln!(f, "$:")?;
                }

                Ok(())
            },
        }
    }

    /// Returns an object which can be used to print the tree contents in a somewhat
    /// human-friendly format.
    ///
    /// The values are printed using their [`Display`] implementation; for further
    /// customization, see [`print_tree`].
    ///
    /// [`print_tree`]: #method.print_tree
    pub fn print_tree_display(
        &self,
    ) -> PrintTree<'_, T, impl Fn(&mut fmt::Formatter, Option<&T>, usize) -> fmt::Result>
    where
        T: Display,
    {
        PrintTree {
            ashes: self,
            print_value: |f, v, indent| {
                for _ in 0..(indent.saturating_mul(2)) {
                    write!(f, "-")?;
                }
                if let Some(v) = v {
                    writeln!(f, "{v}:")?;
                } else {
                    writeln!(f, "$:")?;
                }

                Ok(())
            },
        }
    }
}

impl<T> Default for Ashes<T> {
    fn default() -> Self {
        Self::new()
    }
}

/// A struct for printing human-readable trees.
///
/// See [`Ashes::print_tree`].
pub struct PrintTree<'a, T, F: Fn(&mut fmt::Formatter, Option<&T>, usize) -> fmt::Result> {
    ashes: &'a Ashes<T>,
    print_value: F,
}

impl<'a, T, F: Fn(&mut fmt::Formatter, Option<&T>, usize) -> fmt::Result> PrintTree<'a, T, F> {
    /// Returns a reference to the [`Ashes`] instance used by this struct.
    pub fn ashes(&self) -> &'a Ashes<T> {
        self.ashes
    }
}

impl<'a, T, F: Fn(&mut fmt::Formatter, Option<&T>, usize) -> fmt::Result> Display
    for PrintTree<'a, T, F>
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        fn print<T, F: Fn(&mut fmt::Formatter, Option<&T>, usize) -> fmt::Result>(
            ashes: &Ashes<T>,
            f: &mut std::fmt::Formatter<'_>,
            branch: BranchRef<T>,
            print_value: &F,
            indent: usize,
        ) -> fmt::Result {
            print_value(f, branch.payload(), indent)?;
            let sub_indent = indent.saturating_add(1);
            for child in branch.child_iter() {
                print(ashes, f, ashes.branch(child), print_value, sub_indent)?;
            }
            Ok(())
        }
        print(self.ashes, f, self.ashes.root(), &self.print_value, 0)
    }
}

impl<'a, T, F: Fn(&mut fmt::Formatter, Option<&T>, usize) -> fmt::Result> Debug
    for PrintTree<'a, T, F>
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        Display::fmt(self, f)
    }
}