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