Skip to main content

universal_weave/
wrappers.rs

1//! Wrappers which add additional functionality to [`Weave`] implementations.
2
3#![allow(missing_docs, reason = "False positives")]
4
5use alloc::{collections::VecDeque, vec::Vec};
6use core::{
7    cmp::Ordering,
8    hash::{BuildHasher, Hash},
9    marker::PhantomData,
10};
11
12use hashbrown::HashMap;
13
14#[cfg(feature = "rkyv")]
15use rkyv::{Archive, Deserialize, Serialize};
16
17#[cfg(feature = "serde")]
18use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};
19
20use crate::{
21    ActivePathWeave, ActiveSingularWeave, BookmarkableWeave, DeduplicatableContents,
22    DeduplicatableWeave, DiscreteContents, DiscreteWeave, IndependentContents, IndependentWeave,
23    MetadataWeave, Node, SemiIndependentWeave, SortableBookmarkableWeave, SortableWeave, Weave,
24    dependent, independent,
25};
26
27/// A [`Weave`] wrapper which logs actions successfully performed on the inner [`Weave`] in the order that they are performed.
28///
29/// See [`WeaveAction`] for the complete list of loggable actions.
30#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
31#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
32#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
33#[must_use]
34pub struct LoggedWeave<W, K, N, T, M>
35where
36    W: Weave<K, N, T>,
37    K: Hash + Copy + Eq + Ord,
38    N: Node<K, T>,
39{
40    /// The [`Weave`] being wrapped.
41    ///
42    /// Actions performed directly on the inner [`Weave`] (without using the wrapper's functions) are not logged.
43    pub weave: W,
44
45    /// The list of actions that were performed on the attached [`Weave`] in the order they were performed.
46    pub actions: VecDeque<WeaveAction<K, N, T, M>>,
47}
48
49impl<W, K, N, T, M> AsRef<W> for LoggedWeave<W, K, N, T, M>
50where
51    W: Weave<K, N, T>,
52    K: Hash + Copy + Eq + Ord,
53    N: Node<K, T>,
54{
55    #[inline]
56    fn as_ref(&self) -> &W {
57        &self.weave
58    }
59}
60
61impl<W, K, N, T, M> From<W> for LoggedWeave<W, K, N, T, M>
62where
63    W: Weave<K, N, T>,
64    K: Hash + Copy + Eq + Ord,
65    N: Node<K, T>,
66{
67    #[inline]
68    fn from(value: W) -> Self {
69        Self {
70            weave: value,
71            actions: VecDeque::new(),
72        }
73    }
74}
75
76impl<W, K, N, T, M> LoggedWeave<W, K, N, T, M>
77where
78    W: Weave<K, N, T>,
79    K: Hash + Copy + Eq + Ord,
80    N: Node<K, T>,
81{
82    /// Creates a [`LoggedWeave`] with at least the specified capacity from a [`Weave`].
83    #[inline]
84    pub fn with_capacity(weave: W, capacity: usize) -> Self {
85        Self {
86            actions: VecDeque::with_capacity(capacity),
87            weave,
88        }
89    }
90    /// Converts a [`LoggedWeave`] into it's inner [`Weave`].
91    #[inline]
92    pub fn into_weave(self) -> W {
93        self.weave
94    }
95    /// Returns a reference to the inner [`Weave`].
96    #[inline]
97    pub const fn as_weave(&self) -> &W {
98        &self.weave
99    }
100    /// Returns a reference to the list of actions performed on the [`Weave`].
101    #[inline]
102    pub const fn as_actions(&self) -> &VecDeque<WeaveAction<K, N, T, M>> {
103        &self.actions
104    }
105    /// Clears the inner list of actions performed on the [`Weave`].
106    #[inline]
107    pub fn clear_actions(&mut self) {
108        self.actions.clear();
109    }
110    /// Returns a [`WeaveActionCount`] calculated from the inner list of actions performed on the [`Weave`].
111    pub fn count_actions(&self) -> WeaveActionCount {
112        let mut count = WeaveActionCount::new();
113
114        for action in &self.actions {
115            count.increment(action);
116        }
117
118        count
119    }
120}
121
122/// An action performed on a [`Weave`] which changes its outwardly facing state.
123///
124/// When possible, actions map to a function of the [`Weave`] trait (or its supertraits), and use the same argument ordering as their corresponding function.
125///
126/// Some actions not logged here may change the [`Weave`]'s inner state but not its outwardly facing state.
127#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
128#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
129#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
130#[allow(clippy::doc_paragraphs_missing_punctuation, reason = "False positive")]
131#[non_exhaustive]
132#[must_use]
133pub enum WeaveAction<K, N, T, M>
134where
135    K: Hash + Copy + Eq + Ord,
136    N: Node<K, T>,
137{
138    /// [`Weave::add_node()`]
139    AddNode(N),
140    /// [`Weave::set_node_active_status()`]
141    SetNodeActiveStatus { id: K, value: bool },
142    /// [`BookmarkableWeave::set_node_bookmarked_status()`]
143    SetNodeBookmarkedStatus { id: K, value: bool },
144    /// [`Weave::remove_node()`] or [`Weave::remove_node_tracked()`]
145    RemoveNode(K),
146    /// [`Weave::remove_all_nodes()`]
147    RemoveAllNodes,
148    /// [`MetadataWeave::metadata_mut()`]
149    SetMetadata(M),
150    /// Caused by [`SortableWeave::sort_node_children_by()`], [`SortableWeave::sort_node_children_by_id()`], [`SortableWeave::sort_roots_by()`], and [`SortableWeave::sort_roots_by_id()`]
151    SetNodeChildOrdering { parent: Option<K>, children: Vec<K> },
152    /// Caused by [`SortableBookmarkableWeave::sort_bookmarks_by()`] and [`SortableBookmarkableWeave::sort_bookmarks_by_id()`]
153    SetBookmarkOrdering(Vec<K>),
154    /// [`ActivePathWeave::set_active_path()`]
155    SetActivePath(Vec<K>),
156    /// [`IndependentWeave::move_node()`]
157    MoveNode { id: K, new_parents: Vec<K> },
158    /// Caused by [`SemiIndependentWeave::get_contents_mut()`]
159    SetNodeContent { id: K, contents: T },
160    /// [`DiscreteWeave::split_node()`]
161    SplitNode { id: K, at: usize, new_id: K },
162    /// [`DiscreteWeave::merge_with_parent()`]
163    MergeNodeWithParent(K),
164}
165
166/// A [`Weave`] wrapper which logs the number of actions successfully performed on the inner [`Weave`].
167///
168/// See [`WeaveActionCount`] for the complete list of loggable actions.
169#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
170#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
171#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
172#[must_use]
173pub struct CountedWeave<W, K, N, T>
174where
175    W: Weave<K, N, T>,
176    K: Hash + Copy + Eq + Ord,
177    N: Node<K, T>,
178{
179    /// The [`Weave`] being wrapped.
180    ///
181    /// Actions performed directly on the inner [`Weave`] (without using the wrapper's functions) are not logged.
182    pub weave: W,
183
184    /// The number of actions that were performed on the attached [`Weave`].
185    pub count: WeaveActionCount,
186
187    _phantom_k: PhantomData<K>,
188    _phantom_n: PhantomData<N>,
189    _phantom_t: PhantomData<T>,
190}
191
192impl<W, K, N, T> AsRef<W> for CountedWeave<W, K, N, T>
193where
194    W: Weave<K, N, T>,
195    K: Hash + Copy + Eq + Ord,
196    N: Node<K, T>,
197{
198    #[inline]
199    fn as_ref(&self) -> &W {
200        &self.weave
201    }
202}
203
204impl<W, K, N, T> From<W> for CountedWeave<W, K, N, T>
205where
206    W: Weave<K, N, T>,
207    K: Hash + Copy + Eq + Ord,
208    N: Node<K, T>,
209{
210    #[inline]
211    fn from(value: W) -> Self {
212        Self {
213            weave: value,
214            count: WeaveActionCount::default(),
215            _phantom_k: PhantomData,
216            _phantom_n: PhantomData,
217            _phantom_t: PhantomData,
218        }
219    }
220}
221
222impl<W, K, N, T> CountedWeave<W, K, N, T>
223where
224    W: Weave<K, N, T>,
225    K: Hash + Copy + Eq + Ord,
226    N: Node<K, T>,
227{
228    /// Creates a [`CountedWeave`] from a [`Weave`] and [`WeaveActionCount`] pair.
229    #[inline]
230    pub const fn new(weave: W, count: WeaveActionCount) -> Self {
231        Self {
232            weave,
233            count,
234            _phantom_k: PhantomData,
235            _phantom_n: PhantomData,
236            _phantom_t: PhantomData,
237        }
238    }
239    /// Creates a [`CountedWeave`] from a [`Weave`].
240    pub fn from_weave(weave: W) -> Self {
241        Self::new(weave, WeaveActionCount::new())
242    }
243    /// Converts a [`CountedWeave`] into it's inner [`Weave`].
244    #[inline]
245    pub fn into_weave(self) -> W {
246        self.weave
247    }
248    /// Returns a reference to the inner [`Weave`].
249    #[inline]
250    pub const fn as_weave(&self) -> &W {
251        &self.weave
252    }
253    /// Returns a reference to the inner [`WeaveActionCount`].
254    #[inline]
255    pub const fn as_count(&self) -> &WeaveActionCount {
256        &self.count
257    }
258    /// Resets the inner [`WeaveActionCount`] to zero.
259    #[inline]
260    pub fn reset_count(&mut self) {
261        self.count.reset();
262    }
263}
264
265/// The number of times actions changing the outwardly facing state of a [`Weave`] were performed.
266///
267/// When possible, actions map to a function of the [`Weave`] trait or its supertraits.
268/// Some actions not logged here may change the [`Weave`]'s inner state but not its outwardly facing state.
269#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
270#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
271#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
272#[allow(clippy::doc_paragraphs_missing_punctuation, reason = "False positive")]
273#[non_exhaustive]
274#[must_use]
275pub struct WeaveActionCount {
276    /// [`Weave::add_node()`]
277    pub add_node: usize,
278    /// [`Weave::set_node_active_status()`]
279    pub set_node_active_status: usize,
280    /// [`BookmarkableWeave::set_node_bookmarked_status()`]
281    pub set_node_bookmarked_status: usize,
282    /// [`Weave::remove_node()`] or [`Weave::remove_node_tracked()`]
283    pub remove_node: usize,
284    /// [`Weave::remove_all_nodes()`]
285    pub remove_all_nodes: usize,
286    /// [`MetadataWeave::metadata_mut()`]
287    pub metadata_mut: usize,
288    /// [`SortableWeave::sort_node_children_by()`] or [`SortableWeave::sort_node_children_by_id()`]
289    pub sort_node_children: usize,
290    /// [`SortableWeave::sort_roots_by()`] or [`SortableWeave::sort_roots_by_id()`]
291    pub sort_roots: usize,
292    /// [`SortableBookmarkableWeave::sort_bookmarks_by()`] or [`SortableBookmarkableWeave::sort_bookmarks_by_id()`]
293    pub sort_bookmarks: usize,
294    /// [`ActivePathWeave::set_active_path()`]
295    pub set_active_path: usize,
296    /// [`IndependentWeave::move_node()`]
297    pub move_node: usize,
298    /// [`SemiIndependentWeave::get_contents_mut()`]
299    pub get_contents_mut: usize,
300    /// [`DiscreteWeave::split_node()`]
301    pub split_node: usize,
302    /// [`DiscreteWeave::merge_with_parent()`]
303    pub merge_with_parent: usize,
304    /// User defined; Not incremented/decremented by the [`CountedWeave`] wrapper or [`WeaveActionCount`] functions.
305    pub other: usize,
306}
307
308impl WeaveActionCount {
309    /// Creates a new action count initalized to zero.
310    #[inline]
311    pub fn new() -> Self {
312        Self::default()
313    }
314    /// Resets all action counts to zero.
315    #[inline]
316    pub fn reset(&mut self) {
317        *self = Self::default();
318    }
319    /// Returns the sum of all action counts.
320    #[must_use]
321    pub const fn total_count(&self) -> usize {
322        self.add_node
323            .saturating_add(self.set_node_active_status)
324            .saturating_add(self.set_node_bookmarked_status)
325            .saturating_add(self.remove_node)
326            .saturating_add(self.remove_all_nodes)
327            .saturating_add(self.metadata_mut)
328            .saturating_add(self.sort_node_children)
329            .saturating_add(self.sort_roots)
330            .saturating_add(self.sort_bookmarks)
331            .saturating_add(self.set_active_path)
332            .saturating_add(self.move_node)
333            .saturating_add(self.get_contents_mut)
334            .saturating_add(self.split_node)
335            .saturating_add(self.merge_with_parent)
336            .saturating_add(self.other)
337    }
338    /// Increments the action count corresponding to the [`WeaveAction`]'s type.
339    pub const fn increment<K, N, T, M>(&mut self, action: &WeaveAction<K, N, T, M>)
340    where
341        K: Hash + Copy + Eq + Ord,
342        N: Node<K, T>,
343    {
344        match action {
345            WeaveAction::AddNode(_node) => self.add_node = self.add_node.saturating_add(1),
346            WeaveAction::SetNodeActiveStatus { .. } => {
347                self.set_node_active_status = self.set_node_active_status.saturating_add(1);
348            }
349            WeaveAction::SetNodeBookmarkedStatus { .. } => {
350                self.set_node_bookmarked_status = self.set_node_bookmarked_status.saturating_add(1);
351            }
352            WeaveAction::RemoveNode(_id) => self.remove_node = self.remove_node.saturating_add(1),
353            WeaveAction::RemoveAllNodes => {
354                self.remove_all_nodes = self.remove_all_nodes.saturating_add(1);
355            }
356            WeaveAction::SetMetadata(_metadata) => {
357                self.metadata_mut = self.metadata_mut.saturating_add(1);
358            }
359            WeaveAction::SetNodeChildOrdering { parent, .. } => match parent {
360                Some(_id) => self.sort_node_children = self.sort_node_children.saturating_add(1),
361                None => self.sort_roots = self.sort_roots.saturating_add(1),
362            },
363            WeaveAction::SetBookmarkOrdering(_ids) => {
364                self.sort_bookmarks = self.sort_bookmarks.saturating_add(1);
365            }
366            WeaveAction::SetActivePath(_) => {
367                self.set_active_path = self.set_active_path.saturating_add(1);
368            }
369            WeaveAction::MoveNode { .. } => self.move_node = self.move_node.saturating_add(1),
370            WeaveAction::SetNodeContent { .. } => {
371                self.get_contents_mut = self.get_contents_mut.saturating_add(1);
372            }
373            WeaveAction::SplitNode { .. } => self.split_node = self.split_node.saturating_add(1),
374            WeaveAction::MergeNodeWithParent(_id) => {
375                self.merge_with_parent = self.merge_with_parent.saturating_add(1);
376            }
377        }
378    }
379    /// Decrements the action count corresponding to the [`WeaveAction`]'s type.
380    pub const fn decrement<K, N, T, M>(&mut self, action: &WeaveAction<K, N, T, M>)
381    where
382        K: Hash + Copy + Eq + Ord,
383        N: Node<K, T>,
384    {
385        match action {
386            WeaveAction::AddNode(_node) => self.add_node = self.add_node.saturating_sub(1),
387            WeaveAction::SetNodeActiveStatus { .. } => {
388                self.set_node_active_status = self.set_node_active_status.saturating_sub(1);
389            }
390            WeaveAction::SetNodeBookmarkedStatus { .. } => {
391                self.set_node_bookmarked_status = self.set_node_bookmarked_status.saturating_sub(1);
392            }
393            WeaveAction::RemoveNode(_id) => self.remove_node = self.remove_node.saturating_sub(1),
394            WeaveAction::RemoveAllNodes => {
395                self.remove_all_nodes = self.remove_all_nodes.saturating_sub(1);
396            }
397            WeaveAction::SetMetadata(_metadata) => {
398                self.metadata_mut = self.metadata_mut.saturating_sub(1);
399            }
400            WeaveAction::SetNodeChildOrdering { parent, .. } => match parent {
401                Some(_id) => self.sort_node_children = self.sort_node_children.saturating_sub(1),
402                None => self.sort_roots = self.sort_roots.saturating_sub(1),
403            },
404            WeaveAction::SetBookmarkOrdering(_ids) => {
405                self.sort_bookmarks = self.sort_bookmarks.saturating_sub(1);
406            }
407            WeaveAction::SetActivePath(_) => {
408                self.set_active_path = self.set_active_path.saturating_sub(1);
409            }
410            WeaveAction::MoveNode { .. } => self.move_node = self.move_node.saturating_sub(1),
411            WeaveAction::SetNodeContent { .. } => {
412                self.get_contents_mut = self.get_contents_mut.saturating_sub(1);
413            }
414            WeaveAction::SplitNode { .. } => self.split_node = self.split_node.saturating_sub(1),
415            WeaveAction::MergeNodeWithParent(_id) => {
416                self.merge_with_parent = self.merge_with_parent.saturating_sub(1);
417            }
418        }
419    }
420}
421
422/// A [`Weave`] which can have [`WeaveAction`]s applied to it.
423pub trait ActionableWeave<K, N, T, M, S>
424where
425    K: Hash + Copy + Eq + Ord,
426    N: Node<K, T>,
427    S: BuildHasher + Default + Clone,
428{
429    /// Applies a [`WeaveAction`] to a [`Weave`].
430    ///
431    /// # Panics
432    ///
433    /// May panic if applying the action fails.
434    fn apply(&mut self, action: WeaveAction<K, N, T, M>);
435}
436
437/*impl<W, K, N, T, M, S> ActionableWeave<K, N, T, M, S> for W
438where
439    W: Weave<K, N, T>
440        + MetadataWeave<K, N, T, M>
441        + BookmarkableWeave<K, N, T>
442        + SortableWeave<K, N, T>
443        + SortableBookmarkableWeave<K, N, T>
444        + ActivePathWeave<K, N, T>
445        + IndependentWeave<K, N, T>
446        + SemiIndependentWeave<K, N, T>
447        + DiscreteWeave<K, N, T>,
448    K: Hash + Copy + Eq + Ord,
449    N: Node<K, T>,
450    T: IndependentContents + DiscreteContents,
451    S: BuildHasher + Default + Clone,
452{
453    fn apply(&mut self, action: WeaveAction<K, N, T, M>) {
454        match action {
455            WeaveAction::AddNode(node) => {
456                assert!(self.add_node(node), "Failed to apply Weave action");
457            }
458            WeaveAction::SetNodeActiveStatus { id, value } => {
459                assert!(
460                    self.set_node_active_status(&id, value),
461                    "Failed to apply Weave action"
462                );
463            }
464            WeaveAction::SetNodeBookmarkedStatus { id, value } => {
465                assert!(
466                    self.set_node_bookmarked_status(&id, value),
467                    "Failed to apply Weave action"
468                );
469            }
470            WeaveAction::RemoveNode(id) => assert!(
471                self.remove_node(&id).is_some(),
472                "Failed to apply Weave action"
473            ),
474            WeaveAction::RemoveAllNodes => self.remove_all_nodes(),
475            WeaveAction::SetMetadata(metadata) => {
476                self.metadata_mut(|m| *m = metadata);
477            }
478            WeaveAction::SetNodeChildOrdering { parent, children } => {
479                let mut id_mapping =
480                    HashMap::with_capacity_and_hasher(children.len(), S::default());
481                id_mapping.extend(
482                    children
483                        .into_iter()
484                        .enumerate()
485                        .map(|(index, id)| (id, index)),
486                );
487
488                match parent {
489                    Some(id) => {
490                        assert!(
491                            self.sort_node_children_by_id(&id, |a, b| {
492                                id_mapping[a].cmp(&id_mapping[b])
493                            }),
494                            "Failed to apply Weave action"
495                        );
496                    }
497                    None => {
498                        self.sort_roots_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
499                    }
500                }
501            }
502            WeaveAction::SetBookmarkOrdering(ids) => {
503                let mut id_mapping = HashMap::with_capacity_and_hasher(ids.len(), S::default());
504                id_mapping.extend(ids.into_iter().enumerate().map(|(index, id)| (id, index)));
505
506                self.sort_bookmarks_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
507            }
508            WeaveAction::SetActivePath(active) => {
509                self.set_active_path(active.into_iter());
510            }
511            WeaveAction::MoveNode { id, new_parents } => assert!(
512                self.move_node(&id, &new_parents),
513                "Failed to apply Weave action"
514            ),
515            WeaveAction::SetNodeContent { id, contents } => {
516                assert!(
517                    self.get_contents_mut(&id, |c| *c = contents).is_some(),
518                    "Failed to apply Weave action"
519                );
520            }
521            WeaveAction::SplitNode { id, at, new_id } => assert!(
522                self.split_node(&id, at, new_id),
523                "Failed to apply Weave action"
524            ),
525            WeaveAction::MergeNodeWithParent(id) => assert!(
526                self.merge_with_parent(&id).is_some(),
527                "Failed to apply Weave action"
528            ),
529        }
530    }
531}*/
532
533// Replace this if/when specialization lands in stable
534impl<K, T, M, S> ActionableWeave<K, dependent::DependentNode<K, T, S>, T, M, S>
535    for dependent::DependentWeave<K, T, M, S>
536where
537    K: Hash + Copy + Eq + Ord,
538    T: IndependentContents + DiscreteContents,
539    S: BuildHasher + Default + Clone,
540{
541    #[allow(clippy::panic, reason = "Necessary due to API shape")]
542    fn apply(&mut self, action: WeaveAction<K, dependent::DependentNode<K, T, S>, T, M>) {
543        match action {
544            WeaveAction::AddNode(node) => {
545                assert!(self.add_node(node), "Failed to apply Weave action");
546            }
547            WeaveAction::SetNodeActiveStatus { id, value } => {
548                assert!(
549                    self.set_node_active_status(&id, value),
550                    "Failed to apply Weave action"
551                );
552            }
553            WeaveAction::SetNodeBookmarkedStatus { id, value } => {
554                assert!(
555                    self.set_node_bookmarked_status(&id, value),
556                    "Failed to apply Weave action"
557                );
558            }
559            WeaveAction::RemoveNode(id) => assert!(
560                self.remove_node(&id).is_some(),
561                "Failed to apply Weave action"
562            ),
563            WeaveAction::RemoveAllNodes => self.remove_all_nodes(),
564            WeaveAction::SetMetadata(metadata) => {
565                self.metadata_mut(|m| *m = metadata);
566            }
567            WeaveAction::SetNodeChildOrdering { parent, children } => {
568                let mut id_mapping =
569                    HashMap::with_capacity_and_hasher(children.len(), S::default());
570                id_mapping.extend(
571                    children
572                        .into_iter()
573                        .enumerate()
574                        .map(|(index, id)| (id, index)),
575                );
576
577                match parent {
578                    Some(id) => {
579                        assert!(
580                            self.sort_node_children_by_id(&id, |a, b| {
581                                id_mapping[a].cmp(&id_mapping[b])
582                            }),
583                            "Failed to apply Weave action"
584                        );
585                    }
586                    None => {
587                        self.sort_roots_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
588                    }
589                }
590            }
591            WeaveAction::SetBookmarkOrdering(ids) => {
592                let mut id_mapping = HashMap::with_capacity_and_hasher(ids.len(), S::default());
593                id_mapping.extend(ids.into_iter().enumerate().map(|(index, id)| (id, index)));
594
595                self.sort_bookmarks_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
596            }
597            WeaveAction::SetActivePath(_) => {
598                panic!("Weave does not implement set_active_path()");
599            }
600            WeaveAction::MoveNode { .. } => {
601                panic!("Weave does not implement move_node()");
602            }
603            WeaveAction::SetNodeContent { id, contents } => {
604                assert!(
605                    self.get_contents_mut(&id, |c| *c = contents).is_some(),
606                    "Failed to apply Weave action"
607                );
608            }
609            WeaveAction::SplitNode { id, at, new_id } => assert!(
610                self.split_node(&id, at, new_id),
611                "Failed to apply Weave action"
612            ),
613            WeaveAction::MergeNodeWithParent(id) => assert!(
614                self.merge_with_parent(&id).is_some(),
615                "Failed to apply Weave action"
616            ),
617        }
618    }
619}
620
621// Replace this if/when specialization lands in stable
622impl<K, T, M, S> ActionableWeave<K, independent::IndependentNode<K, T, S>, T, M, S>
623    for independent::IndependentWeave<K, T, M, S>
624where
625    K: Hash + Copy + Eq + Ord,
626    T: IndependentContents + DiscreteContents,
627    S: BuildHasher + Default + Clone,
628{
629    fn apply(&mut self, action: WeaveAction<K, independent::IndependentNode<K, T, S>, T, M>) {
630        match action {
631            WeaveAction::AddNode(node) => {
632                assert!(self.add_node(node), "Failed to apply Weave action");
633            }
634            WeaveAction::SetNodeActiveStatus { id, value } => {
635                assert!(
636                    self.set_node_active_status(&id, value),
637                    "Failed to apply Weave action"
638                );
639            }
640            WeaveAction::SetNodeBookmarkedStatus { id, value } => {
641                assert!(
642                    self.set_node_bookmarked_status(&id, value),
643                    "Failed to apply Weave action"
644                );
645            }
646            WeaveAction::RemoveNode(id) => assert!(
647                self.remove_node(&id).is_some(),
648                "Failed to apply Weave action"
649            ),
650            WeaveAction::RemoveAllNodes => self.remove_all_nodes(),
651            WeaveAction::SetMetadata(metadata) => {
652                self.metadata_mut(|m| *m = metadata);
653            }
654            WeaveAction::SetNodeChildOrdering { parent, children } => {
655                let mut id_mapping =
656                    HashMap::with_capacity_and_hasher(children.len(), S::default());
657                id_mapping.extend(
658                    children
659                        .into_iter()
660                        .enumerate()
661                        .map(|(index, id)| (id, index)),
662                );
663
664                match parent {
665                    Some(id) => {
666                        assert!(
667                            self.sort_node_children_by_id(&id, |a, b| {
668                                id_mapping[a].cmp(&id_mapping[b])
669                            }),
670                            "Failed to apply Weave action"
671                        );
672                    }
673                    None => {
674                        self.sort_roots_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
675                    }
676                }
677            }
678            WeaveAction::SetBookmarkOrdering(ids) => {
679                let mut id_mapping = HashMap::with_capacity_and_hasher(ids.len(), S::default());
680                id_mapping.extend(ids.into_iter().enumerate().map(|(index, id)| (id, index)));
681
682                self.sort_bookmarks_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
683            }
684            WeaveAction::SetActivePath(active) => {
685                self.set_active_path(active.into_iter());
686            }
687            WeaveAction::MoveNode { id, new_parents } => assert!(
688                self.move_node(&id, &new_parents),
689                "Failed to apply Weave action"
690            ),
691            WeaveAction::SetNodeContent { id, contents } => {
692                assert!(
693                    self.get_contents_mut(&id, |c| *c = contents).is_some(),
694                    "Failed to apply Weave action"
695                );
696            }
697            WeaveAction::SplitNode { id, at, new_id } => assert!(
698                self.split_node(&id, at, new_id),
699                "Failed to apply Weave action"
700            ),
701            WeaveAction::MergeNodeWithParent(id) => assert!(
702                self.merge_with_parent(&id).is_some(),
703                "Failed to apply Weave action"
704            ),
705        }
706    }
707}
708
709impl<W, K, N, T, M> Weave<K, N, T> for LoggedWeave<W, K, N, T, M>
710where
711    W: Weave<K, N, T>,
712    K: Hash + Copy + Eq + Ord,
713    N: Node<K, T> + Clone,
714{
715    type Nodes = W::Nodes;
716    type Roots = W::Roots;
717
718    #[inline]
719    fn len(&self) -> usize {
720        self.weave.len()
721    }
722    #[inline]
723    fn is_empty(&self) -> bool {
724        self.weave.is_empty()
725    }
726    #[inline]
727    fn nodes(&self) -> &Self::Nodes {
728        self.weave.nodes()
729    }
730    #[inline]
731    fn roots(&self) -> &Self::Roots {
732        self.weave.roots()
733    }
734    #[inline]
735    fn contains(&self, id: &K) -> bool {
736        self.weave.contains(id)
737    }
738    #[inline]
739    fn contains_active(&self, id: &K) -> bool {
740        self.weave.contains_active(id)
741    }
742    #[inline]
743    fn get_node(&self, id: &K) -> Option<&N> {
744        self.weave.get_node(id)
745    }
746    #[inline]
747    fn get_ordered_node_identifiers(&mut self, output: &mut Vec<K>) {
748        self.weave.get_ordered_node_identifiers(output);
749    }
750    #[inline]
751    fn get_ordered_node_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
752        self.weave.get_ordered_node_identifiers_from(id, output);
753    }
754    #[inline]
755    fn get_active_path(&mut self, output: &mut Vec<K>) {
756        self.weave.get_active_path(output);
757    }
758    #[inline]
759    fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
760        self.weave.get_path_from(id, output);
761    }
762    fn add_node(&mut self, node: N) -> bool {
763        if self.weave.add_node(node.clone()) {
764            self.actions.push_back(WeaveAction::AddNode(node));
765            true
766        } else {
767            false
768        }
769    }
770    fn set_node_active_status(&mut self, id: &K, value: bool) -> bool {
771        if self.weave.set_node_active_status(id, value) {
772            self.actions
773                .push_back(WeaveAction::SetNodeActiveStatus { id: *id, value });
774            true
775        } else {
776            false
777        }
778    }
779    fn remove_node(&mut self, id: &K) -> Option<N> {
780        if let Some(removed) = self.weave.remove_node(id) {
781            self.actions.push_back(WeaveAction::RemoveNode(*id));
782            Some(removed)
783        } else {
784            None
785        }
786    }
787    fn remove_node_tracked(&mut self, id: &K, on_removal: impl FnMut(N)) -> bool {
788        if self.weave.remove_node_tracked(id, on_removal) {
789            self.actions.push_back(WeaveAction::RemoveNode(*id));
790            true
791        } else {
792            false
793        }
794    }
795    fn remove_all_nodes(&mut self) {
796        self.weave.remove_all_nodes();
797        self.actions.push_back(WeaveAction::RemoveAllNodes);
798    }
799}
800
801impl<W, K, N, T, M> MetadataWeave<K, N, T, M> for LoggedWeave<W, K, N, T, M>
802where
803    W: MetadataWeave<K, N, T, M>,
804    K: Hash + Copy + Eq + Ord,
805    N: Node<K, T> + Clone,
806    M: Clone,
807{
808    #[inline]
809    fn metadata(&self) -> &M {
810        self.weave.metadata()
811    }
812    fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
813        self.weave.metadata_mut(|metadata| {
814            let output = callback(metadata);
815
816            self.actions
817                .push_back(WeaveAction::SetMetadata(metadata.clone()));
818
819            output
820        })
821    }
822}
823
824impl<W, K, N, T, M> BookmarkableWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
825where
826    W: BookmarkableWeave<K, N, T>,
827    K: Hash + Copy + Eq + Ord,
828    N: Node<K, T> + Clone,
829{
830    type Bookmarks = W::Bookmarks;
831
832    #[inline]
833    fn bookmarks(&self) -> &Self::Bookmarks {
834        self.weave.bookmarks()
835    }
836    #[inline]
837    fn contains_bookmark(&self, id: &K) -> bool {
838        self.weave.contains_bookmark(id)
839    }
840    fn set_node_bookmarked_status(&mut self, id: &K, value: bool) -> bool {
841        if self.weave.set_node_bookmarked_status(id, value) {
842            self.actions
843                .push_back(WeaveAction::SetNodeBookmarkedStatus { id: *id, value });
844            true
845        } else {
846            false
847        }
848    }
849}
850
851impl<W, K, N, T, M> SortableWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
852where
853    W: SortableWeave<K, N, T>,
854    K: Hash + Copy + Eq + Ord,
855    N: Node<K, T> + Clone,
856    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
857    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
858{
859    #[inline]
860    fn get_ordered_node_identifiers_mirrored(&mut self, output: &mut Vec<K>) {
861        self.weave.get_ordered_node_identifiers_mirrored(output);
862    }
863    #[inline]
864    fn get_ordered_node_identifiers_mirrored_from(&mut self, id: &K, output: &mut Vec<K>) {
865        self.weave
866            .get_ordered_node_identifiers_mirrored_from(id, output);
867    }
868    fn sort_node_children_by(&mut self, id: &K, cmp: impl FnMut(&N, &N) -> Ordering) -> bool {
869        if self.weave.sort_node_children_by(id, cmp) {
870            self.actions.push_back(WeaveAction::SetNodeChildOrdering {
871                parent: Some(*id),
872                children: self
873                    .weave
874                    .get_node(id)
875                    .unwrap()
876                    .to()
877                    .into_iter()
878                    .copied()
879                    .collect(),
880            });
881            true
882        } else {
883            false
884        }
885    }
886    fn sort_node_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
887        if self.weave.sort_node_children_by_id(id, cmp) {
888            self.actions.push_back(WeaveAction::SetNodeChildOrdering {
889                parent: Some(*id),
890                children: self
891                    .weave
892                    .get_node(id)
893                    .unwrap()
894                    .to()
895                    .into_iter()
896                    .copied()
897                    .collect(),
898            });
899            true
900        } else {
901            false
902        }
903    }
904    fn sort_roots_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
905        self.weave.sort_roots_by(cmp);
906        self.actions.push_back(WeaveAction::SetNodeChildOrdering {
907            parent: None,
908            children: self.weave.roots().into_iter().copied().collect(),
909        });
910    }
911    fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
912        self.weave.sort_roots_by_id(cmp);
913        self.actions.push_back(WeaveAction::SetNodeChildOrdering {
914            parent: None,
915            children: self.weave.roots().into_iter().copied().collect(),
916        });
917    }
918}
919
920impl<W, K, N, T, M> SortableBookmarkableWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
921where
922    W: SortableBookmarkableWeave<K, N, T>,
923    K: Hash + Copy + Eq + Ord,
924    N: Node<K, T> + Clone,
925    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
926    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
927    for<'a> &'a W::Bookmarks: IntoIterator<Item = &'a K>,
928{
929    fn sort_bookmarks_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
930        self.weave.sort_bookmarks_by(cmp);
931        self.actions.push_back(WeaveAction::SetBookmarkOrdering(
932            self.weave.bookmarks().into_iter().copied().collect(),
933        ));
934    }
935    fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
936        self.weave.sort_bookmarks_by_id(cmp);
937        self.actions.push_back(WeaveAction::SetBookmarkOrdering(
938            self.weave.bookmarks().into_iter().copied().collect(),
939        ));
940    }
941}
942
943impl<W, K, N, T, M> ActiveSingularWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
944where
945    W: ActiveSingularWeave<K, N, T>,
946    K: Hash + Copy + Eq + Ord,
947    N: Node<K, T> + Clone,
948{
949    #[inline]
950    fn active(&self) -> Option<K> {
951        self.weave.active()
952    }
953}
954
955impl<W, K, N, T, M> ActivePathWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
956where
957    W: ActivePathWeave<K, N, T>,
958    K: Hash + Copy + Eq + Ord,
959    N: Node<K, T> + Clone,
960{
961    type Active = W::Active;
962
963    #[inline]
964    fn active(&self) -> &Self::Active {
965        self.weave.active()
966    }
967    fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
968        let active: Vec<K> = active.collect();
969
970        self.weave.set_active_path(active.iter().copied());
971        self.actions.push_back(WeaveAction::SetActivePath(active));
972    }
973}
974
975impl<W, K, N, T, M> IndependentWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
976where
977    W: IndependentWeave<K, N, T>,
978    K: Hash + Copy + Eq + Ord,
979    N: Node<K, T> + Clone,
980    T: IndependentContents + Clone,
981{
982    fn move_node(&mut self, id: &K, new_parents: &[K]) -> bool {
983        if self.weave.move_node(id, new_parents) {
984            self.actions.push_back(WeaveAction::MoveNode {
985                id: *id,
986                new_parents: new_parents.to_vec(),
987            });
988            true
989        } else {
990            false
991        }
992    }
993}
994
995impl<W, K, N, T, M> SemiIndependentWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
996where
997    W: SemiIndependentWeave<K, N, T>,
998    K: Hash + Copy + Eq + Ord,
999    N: Node<K, T> + Clone,
1000    T: IndependentContents + Clone,
1001{
1002    fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
1003        self.weave.get_contents_mut(id, |contents| {
1004            let output = callback(contents);
1005
1006            self.actions.push_back(WeaveAction::SetNodeContent {
1007                id: *id,
1008                contents: contents.clone(),
1009            });
1010
1011            output
1012        })
1013    }
1014}
1015
1016impl<W, K, N, T, M> DiscreteWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
1017where
1018    W: DiscreteWeave<K, N, T>,
1019    K: Hash + Copy + Eq + Ord,
1020    N: Node<K, T> + Clone,
1021    T: DiscreteContents,
1022{
1023    fn split_node(&mut self, id: &K, at: usize, new_id: K) -> bool {
1024        if self.weave.split_node(id, at, new_id) {
1025            self.actions.push_back(WeaveAction::SplitNode {
1026                id: *id,
1027                at,
1028                new_id,
1029            });
1030            true
1031        } else {
1032            false
1033        }
1034    }
1035    fn merge_with_parent(&mut self, id: &K) -> Option<K> {
1036        match self.weave.merge_with_parent(id) {
1037            Some(new_id) => {
1038                self.actions
1039                    .push_back(WeaveAction::MergeNodeWithParent(*id));
1040                Some(new_id)
1041            }
1042            None => None,
1043        }
1044    }
1045}
1046
1047impl<W, K, N, T, M> DeduplicatableWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
1048where
1049    W: DeduplicatableWeave<K, N, T>,
1050    K: Hash + Copy + Eq + Ord,
1051    N: Node<K, T> + Clone,
1052    T: DeduplicatableContents,
1053{
1054    #[inline]
1055    fn find_duplicates(&self, id: &K) -> impl Iterator<Item = K> {
1056        self.weave.find_duplicates(id)
1057    }
1058}
1059
1060impl<W, K, N, T> Weave<K, N, T> for CountedWeave<W, K, N, T>
1061where
1062    W: Weave<K, N, T>,
1063    K: Hash + Copy + Eq + Ord,
1064    N: Node<K, T>,
1065{
1066    type Nodes = W::Nodes;
1067    type Roots = W::Roots;
1068
1069    #[inline]
1070    fn len(&self) -> usize {
1071        self.weave.len()
1072    }
1073    #[inline]
1074    fn is_empty(&self) -> bool {
1075        self.weave.is_empty()
1076    }
1077    #[inline]
1078    fn nodes(&self) -> &Self::Nodes {
1079        self.weave.nodes()
1080    }
1081    #[inline]
1082    fn roots(&self) -> &Self::Roots {
1083        self.weave.roots()
1084    }
1085    #[inline]
1086    fn contains(&self, id: &K) -> bool {
1087        self.weave.contains(id)
1088    }
1089    #[inline]
1090    fn contains_active(&self, id: &K) -> bool {
1091        self.weave.contains_active(id)
1092    }
1093    #[inline]
1094    fn get_node(&self, id: &K) -> Option<&N> {
1095        self.weave.get_node(id)
1096    }
1097    #[inline]
1098    fn get_ordered_node_identifiers(&mut self, output: &mut Vec<K>) {
1099        self.weave.get_ordered_node_identifiers(output);
1100    }
1101    #[inline]
1102    fn get_ordered_node_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
1103        self.weave.get_ordered_node_identifiers_from(id, output);
1104    }
1105    #[inline]
1106    fn get_active_path(&mut self, output: &mut Vec<K>) {
1107        self.weave.get_active_path(output);
1108    }
1109    #[inline]
1110    fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
1111        self.weave.get_path_from(id, output);
1112    }
1113    #[inline]
1114    fn add_node(&mut self, node: N) -> bool {
1115        if self.weave.add_node(node) {
1116            self.count.add_node = self.count.add_node.saturating_add(1);
1117            true
1118        } else {
1119            false
1120        }
1121    }
1122    #[inline]
1123    fn set_node_active_status(&mut self, id: &K, value: bool) -> bool {
1124        if self.weave.set_node_active_status(id, value) {
1125            self.count.set_node_active_status = self.count.set_node_active_status.saturating_add(1);
1126            true
1127        } else {
1128            false
1129        }
1130    }
1131    #[inline]
1132    fn remove_node(&mut self, id: &K) -> Option<N> {
1133        if let Some(removed) = self.weave.remove_node(id) {
1134            self.count.remove_node = self.count.remove_node.saturating_add(1);
1135            Some(removed)
1136        } else {
1137            None
1138        }
1139    }
1140    #[inline]
1141    fn remove_node_tracked(&mut self, id: &K, on_removal: impl FnMut(N)) -> bool {
1142        if self.weave.remove_node_tracked(id, on_removal) {
1143            self.count.remove_node = self.count.remove_node.saturating_add(1);
1144            true
1145        } else {
1146            false
1147        }
1148    }
1149    #[inline]
1150    fn remove_all_nodes(&mut self) {
1151        self.weave.remove_all_nodes();
1152        self.count.remove_all_nodes = self.count.remove_all_nodes.saturating_add(1);
1153    }
1154}
1155
1156impl<W, K, N, T, M> MetadataWeave<K, N, T, M> for CountedWeave<W, K, N, T>
1157where
1158    W: MetadataWeave<K, N, T, M>,
1159    K: Hash + Copy + Eq + Ord,
1160    N: Node<K, T>,
1161{
1162    #[inline]
1163    fn metadata(&self) -> &M {
1164        self.weave.metadata()
1165    }
1166    #[inline]
1167    fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
1168        self.weave.metadata_mut(|metadata| {
1169            let output = callback(metadata);
1170            self.count.metadata_mut = self.count.metadata_mut.saturating_add(1);
1171            output
1172        })
1173    }
1174}
1175
1176impl<W, K, N, T> BookmarkableWeave<K, N, T> for CountedWeave<W, K, N, T>
1177where
1178    W: BookmarkableWeave<K, N, T>,
1179    K: Hash + Copy + Eq + Ord,
1180    N: Node<K, T>,
1181{
1182    type Bookmarks = W::Bookmarks;
1183
1184    #[inline]
1185    fn bookmarks(&self) -> &Self::Bookmarks {
1186        self.weave.bookmarks()
1187    }
1188    #[inline]
1189    fn contains_bookmark(&self, id: &K) -> bool {
1190        self.weave.contains_bookmark(id)
1191    }
1192    #[inline]
1193    fn set_node_bookmarked_status(&mut self, id: &K, value: bool) -> bool {
1194        if self.weave.set_node_bookmarked_status(id, value) {
1195            self.count.set_node_bookmarked_status =
1196                self.count.set_node_bookmarked_status.saturating_add(1);
1197            true
1198        } else {
1199            false
1200        }
1201    }
1202}
1203
1204impl<W, K, N, T> SortableWeave<K, N, T> for CountedWeave<W, K, N, T>
1205where
1206    W: SortableWeave<K, N, T>,
1207    K: Hash + Copy + Eq + Ord,
1208    N: Node<K, T>,
1209{
1210    #[inline]
1211    fn get_ordered_node_identifiers_mirrored(&mut self, output: &mut Vec<K>) {
1212        self.weave.get_ordered_node_identifiers_mirrored(output);
1213    }
1214    #[inline]
1215    fn get_ordered_node_identifiers_mirrored_from(&mut self, id: &K, output: &mut Vec<K>) {
1216        self.weave
1217            .get_ordered_node_identifiers_mirrored_from(id, output);
1218    }
1219    #[inline]
1220    fn sort_node_children_by(&mut self, id: &K, cmp: impl FnMut(&N, &N) -> Ordering) -> bool {
1221        if self.weave.sort_node_children_by(id, cmp) {
1222            self.count.sort_node_children = self.count.sort_node_children.saturating_add(1);
1223            true
1224        } else {
1225            false
1226        }
1227    }
1228    #[inline]
1229    fn sort_node_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
1230        if self.weave.sort_node_children_by_id(id, cmp) {
1231            self.count.sort_node_children = self.count.sort_node_children.saturating_add(1);
1232            true
1233        } else {
1234            false
1235        }
1236    }
1237    #[inline]
1238    fn sort_roots_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
1239        self.weave.sort_roots_by(cmp);
1240        self.count.sort_roots = self.count.sort_roots.saturating_add(1);
1241    }
1242    #[inline]
1243    fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1244        self.weave.sort_roots_by_id(cmp);
1245        self.count.sort_roots = self.count.sort_roots.saturating_add(1);
1246    }
1247}
1248
1249impl<W, K, N, T> SortableBookmarkableWeave<K, N, T> for CountedWeave<W, K, N, T>
1250where
1251    W: SortableBookmarkableWeave<K, N, T>,
1252    K: Hash + Copy + Eq + Ord,
1253    N: Node<K, T>,
1254{
1255    #[inline]
1256    fn sort_bookmarks_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
1257        self.weave.sort_bookmarks_by(cmp);
1258        self.count.sort_bookmarks = self.count.sort_bookmarks.saturating_add(1);
1259    }
1260    #[inline]
1261    fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1262        self.weave.sort_bookmarks_by_id(cmp);
1263        self.count.sort_bookmarks = self.count.sort_bookmarks.saturating_add(1);
1264    }
1265}
1266
1267impl<W, K, N, T> ActiveSingularWeave<K, N, T> for CountedWeave<W, K, N, T>
1268where
1269    W: ActiveSingularWeave<K, N, T>,
1270    K: Hash + Copy + Eq + Ord,
1271    N: Node<K, T>,
1272{
1273    #[inline]
1274    fn active(&self) -> Option<K> {
1275        self.weave.active()
1276    }
1277}
1278
1279impl<W, K, N, T> ActivePathWeave<K, N, T> for CountedWeave<W, K, N, T>
1280where
1281    W: ActivePathWeave<K, N, T>,
1282    K: Hash + Copy + Eq + Ord,
1283    N: Node<K, T>,
1284{
1285    type Active = W::Active;
1286
1287    #[inline]
1288    fn active(&self) -> &Self::Active {
1289        self.weave.active()
1290    }
1291    #[inline]
1292    fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
1293        self.weave.set_active_path(active);
1294        self.count.set_active_path = self.count.set_active_path.saturating_add(1);
1295    }
1296}
1297
1298impl<W, K, N, T> IndependentWeave<K, N, T> for CountedWeave<W, K, N, T>
1299where
1300    W: IndependentWeave<K, N, T>,
1301    K: Hash + Copy + Eq + Ord,
1302    N: Node<K, T>,
1303    T: IndependentContents,
1304{
1305    #[inline]
1306    fn move_node(&mut self, id: &K, new_parents: &[K]) -> bool {
1307        if self.weave.move_node(id, new_parents) {
1308            self.count.move_node = self.count.move_node.saturating_add(1);
1309            true
1310        } else {
1311            false
1312        }
1313    }
1314}
1315
1316impl<W, K, N, T> SemiIndependentWeave<K, N, T> for CountedWeave<W, K, N, T>
1317where
1318    W: SemiIndependentWeave<K, N, T>,
1319    K: Hash + Copy + Eq + Ord,
1320    N: Node<K, T>,
1321    T: IndependentContents,
1322{
1323    #[inline]
1324    fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
1325        self.weave.get_contents_mut(id, |contents| {
1326            let output = callback(contents);
1327            self.count.get_contents_mut = self.count.get_contents_mut.saturating_add(1);
1328            output
1329        })
1330    }
1331}
1332
1333impl<W, K, N, T> DiscreteWeave<K, N, T> for CountedWeave<W, K, N, T>
1334where
1335    W: DiscreteWeave<K, N, T>,
1336    K: Hash + Copy + Eq + Ord,
1337    N: Node<K, T>,
1338    T: DiscreteContents,
1339{
1340    #[inline]
1341    fn split_node(&mut self, id: &K, at: usize, new_id: K) -> bool {
1342        if self.weave.split_node(id, at, new_id) {
1343            self.count.split_node = self.count.split_node.saturating_add(1);
1344            true
1345        } else {
1346            false
1347        }
1348    }
1349    #[inline]
1350    fn merge_with_parent(&mut self, id: &K) -> Option<K> {
1351        match self.weave.merge_with_parent(id) {
1352            Some(new_id) => {
1353                self.count.merge_with_parent = self.count.merge_with_parent.saturating_add(1);
1354                Some(new_id)
1355            }
1356            None => None,
1357        }
1358    }
1359}
1360
1361impl<W, K, N, T> DeduplicatableWeave<K, N, T> for CountedWeave<W, K, N, T>
1362where
1363    W: DeduplicatableWeave<K, N, T>,
1364    K: Hash + Copy + Eq + Ord,
1365    N: Node<K, T>,
1366    T: DeduplicatableContents,
1367{
1368    #[inline]
1369    fn find_duplicates(&self, id: &K) -> impl Iterator<Item = K> {
1370        self.weave.find_duplicates(id)
1371    }
1372}