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, HashSet};
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    DiscreteContentResult, 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::insert()`]
139    Insert(N),
140    /// [`Weave::set_active()`]
141    SetActive { id: K, value: bool },
142    /// [`BookmarkableWeave::set_bookmarked()`]
143    SetBookmarked { id: K, value: bool },
144    /// [`Weave::remove()`] or [`Weave::remove_tracked()`]
145    Remove(K),
146    /// [`Weave::clear()`]
147    Clear,
148    /// [`MetadataWeave::metadata_mut()`]
149    SetMetadata(M),
150    /// Caused by [`SortableWeave::sort_children_by()`], [`SortableWeave::sort_children_by_id()`], [`SortableWeave::sort_roots_by()`], and [`SortableWeave::sort_roots_by_id()`]
151    SetChildOrdering { 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_to()`]
157    MoveTo { id: K, new_parents: Vec<K> },
158    /// Caused by [`SemiIndependentWeave::get_contents_mut()`]
159    SetContents { id: K, contents: T },
160    /// [`DiscreteWeave::split()`]
161    Split { id: K, at: usize, new_id: K },
162    /// [`DiscreteWeave::merge_with_parent()`]
163    MergeWithParent(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::insert()`]
277    pub insert: usize,
278    /// [`Weave::set_active()`]
279    pub set_active: usize,
280    /// [`BookmarkableWeave::set_bookmarked()`]
281    pub set_bookmarked: usize,
282    /// [`Weave::remove()`] or [`Weave::remove_tracked()`]
283    pub remove: usize,
284    /// [`Weave::clear()`]
285    pub clear: usize,
286    /// [`MetadataWeave::metadata_mut()`]
287    pub metadata_mut: usize,
288    /// [`SortableWeave::sort_children_by()`] or [`SortableWeave::sort_children_by_id()`]
289    pub sort_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_to()`]
297    pub move_to: usize,
298    /// [`SemiIndependentWeave::get_contents_mut()`]
299    pub get_contents_mut: usize,
300    /// [`DiscreteWeave::split()`]
301    pub split: 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.insert
323            .saturating_add(self.set_active)
324            .saturating_add(self.set_bookmarked)
325            .saturating_add(self.remove)
326            .saturating_add(self.clear)
327            .saturating_add(self.metadata_mut)
328            .saturating_add(self.sort_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_to)
333            .saturating_add(self.get_contents_mut)
334            .saturating_add(self.split)
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::Insert(_node) => self.insert = self.insert.saturating_add(1),
346            WeaveAction::SetActive { .. } => {
347                self.set_active = self.set_active.saturating_add(1);
348            }
349            WeaveAction::SetBookmarked { .. } => {
350                self.set_bookmarked = self.set_bookmarked.saturating_add(1);
351            }
352            WeaveAction::Remove(_id) => self.remove = self.remove.saturating_add(1),
353            WeaveAction::Clear => {
354                self.clear = self.clear.saturating_add(1);
355            }
356            WeaveAction::SetMetadata(_metadata) => {
357                self.metadata_mut = self.metadata_mut.saturating_add(1);
358            }
359            WeaveAction::SetChildOrdering { parent, .. } => match parent {
360                Some(_id) => self.sort_children = self.sort_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::MoveTo { .. } => self.move_to = self.move_to.saturating_add(1),
370            WeaveAction::SetContents { .. } => {
371                self.get_contents_mut = self.get_contents_mut.saturating_add(1);
372            }
373            WeaveAction::Split { .. } => self.split = self.split.saturating_add(1),
374            WeaveAction::MergeWithParent(_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::Insert(_node) => self.insert = self.insert.saturating_sub(1),
387            WeaveAction::SetActive { .. } => {
388                self.set_active = self.set_active.saturating_sub(1);
389            }
390            WeaveAction::SetBookmarked { .. } => {
391                self.set_bookmarked = self.set_bookmarked.saturating_sub(1);
392            }
393            WeaveAction::Remove(_id) => self.remove = self.remove.saturating_sub(1),
394            WeaveAction::Clear => {
395                self.clear = self.clear.saturating_sub(1);
396            }
397            WeaveAction::SetMetadata(_metadata) => {
398                self.metadata_mut = self.metadata_mut.saturating_sub(1);
399            }
400            WeaveAction::SetChildOrdering { parent, .. } => match parent {
401                Some(_id) => self.sort_children = self.sort_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::MoveTo { .. } => self.move_to = self.move_to.saturating_sub(1),
411            WeaveAction::SetContents { .. } => {
412                self.get_contents_mut = self.get_contents_mut.saturating_sub(1);
413            }
414            WeaveAction::Split { .. } => self.split = self.split.saturating_sub(1),
415            WeaveAction::MergeWithParent(_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::Insert(node) => {
456                assert!(self.insert(node), "Failed to apply Weave action");
457            }
458            WeaveAction::SetActive { id, value } => {
459                assert!(self.set_active(&id, value), "Failed to apply Weave action");
460            }
461            WeaveAction::SetBookmarked { id, value } => {
462                assert!(
463                    self.set_bookmarked(&id, value),
464                    "Failed to apply Weave action"
465                );
466            }
467            WeaveAction::Remove(id) => {
468                assert!(self.remove(&id).is_some(), "Failed to apply Weave action");
469            }
470            WeaveAction::Clear => self.clear(),
471            WeaveAction::SetMetadata(metadata) => {
472                self.metadata_mut(|m| *m = metadata);
473            }
474            WeaveAction::SetChildOrdering { parent, children } => {
475                let mut id_mapping =
476                    HashMap::with_capacity_and_hasher(children.len(), S::default());
477                id_mapping.extend(
478                    children
479                        .into_iter()
480                        .enumerate()
481                        .map(|(index, id)| (id, index)),
482                );
483
484                match parent {
485                    Some(id) => {
486                        assert!(
487                            self.sort_children_by_id(&id, |a, b| {
488                                id_mapping[a].cmp(&id_mapping[b])
489                            }),
490                            "Failed to apply Weave action"
491                        );
492                    }
493                    None => {
494                        self.sort_roots_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
495                    }
496                }
497            }
498            WeaveAction::SetBookmarkOrdering(ids) => {
499                let mut id_mapping = HashMap::with_capacity_and_hasher(ids.len(), S::default());
500                id_mapping.extend(ids.into_iter().enumerate().map(|(index, id)| (id, index)));
501
502                self.sort_bookmarks_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
503            }
504            WeaveAction::SetActivePath(active) => {
505                self.set_active_path(active.into_iter());
506            }
507            WeaveAction::MoveTo { id, new_parents } => assert!(
508                self.move_to(&id, &new_parents),
509                "Failed to apply Weave action"
510            ),
511            WeaveAction::SetContents { id, contents } => {
512                assert!(
513                    self.get_contents_mut(&id, |c| *c = contents).is_some(),
514                    "Failed to apply Weave action"
515                );
516            }
517            WeaveAction::Split { id, at, new_id } => {
518                assert!(self.split(&id, at, new_id), "Failed to apply Weave action");
519            }
520            WeaveAction::MergeWithParent(id) => assert!(
521                self.merge_with_parent(&id).is_some(),
522                "Failed to apply Weave action"
523            ),
524        }
525    }
526}*/
527
528// Replace this if/when specialization lands in stable
529impl<K, T, M, S> ActionableWeave<K, dependent::DependentNode<K, T, S>, T, M, S>
530    for dependent::DependentWeave<K, T, M, S>
531where
532    K: Hash + Copy + Eq + Ord,
533    T: IndependentContents + DiscreteContents,
534    S: BuildHasher + Default + Clone,
535{
536    #[allow(clippy::panic, reason = "Necessary due to API shape")]
537    fn apply(&mut self, action: WeaveAction<K, dependent::DependentNode<K, T, S>, T, M>) {
538        match action {
539            WeaveAction::Insert(node) => {
540                assert!(self.insert(node), "Failed to apply Weave action");
541            }
542            WeaveAction::SetActive { id, value } => {
543                assert!(self.set_active(&id, value), "Failed to apply Weave action");
544            }
545            WeaveAction::SetBookmarked { id, value } => {
546                assert!(
547                    self.set_bookmarked(&id, value),
548                    "Failed to apply Weave action"
549                );
550            }
551            WeaveAction::Remove(id) => {
552                assert!(self.remove(&id).is_some(), "Failed to apply Weave action");
553            }
554            WeaveAction::Clear => self.clear(),
555            WeaveAction::SetMetadata(metadata) => {
556                self.metadata_mut(|m| *m = metadata);
557            }
558            WeaveAction::SetChildOrdering { parent, children } => {
559                let mut id_mapping =
560                    HashMap::with_capacity_and_hasher(children.len(), S::default());
561                id_mapping.extend(
562                    children
563                        .into_iter()
564                        .enumerate()
565                        .map(|(index, id)| (id, index)),
566                );
567
568                match parent {
569                    Some(id) => {
570                        assert!(
571                            self.sort_children_by_id(&id, |a, b| {
572                                id_mapping[a].cmp(&id_mapping[b])
573                            }),
574                            "Failed to apply Weave action"
575                        );
576                    }
577                    None => {
578                        self.sort_roots_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
579                    }
580                }
581            }
582            WeaveAction::SetBookmarkOrdering(ids) => {
583                let mut id_mapping = HashMap::with_capacity_and_hasher(ids.len(), S::default());
584                id_mapping.extend(ids.into_iter().enumerate().map(|(index, id)| (id, index)));
585
586                self.sort_bookmarks_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
587            }
588            WeaveAction::SetActivePath(_) => {
589                panic!("Weave does not implement set_active_path()");
590            }
591            WeaveAction::MoveTo { .. } => {
592                panic!("Weave does not implement move_to()");
593            }
594            WeaveAction::SetContents { id, contents } => {
595                assert!(
596                    self.get_contents_mut(&id, |c| *c = contents).is_some(),
597                    "Failed to apply Weave action"
598                );
599            }
600            WeaveAction::Split { id, at, new_id } => {
601                assert!(self.split(&id, at, new_id), "Failed to apply Weave action");
602            }
603            WeaveAction::MergeWithParent(id) => assert!(
604                self.merge_with_parent(&id).is_some(),
605                "Failed to apply Weave action"
606            ),
607        }
608    }
609}
610
611// Replace this if/when specialization lands in stable
612impl<K, T, M, S> ActionableWeave<K, independent::IndependentNode<K, T, S>, T, M, S>
613    for independent::IndependentWeave<K, T, M, S>
614where
615    K: Hash + Copy + Eq + Ord,
616    T: IndependentContents + DiscreteContents,
617    S: BuildHasher + Default + Clone,
618{
619    fn apply(&mut self, action: WeaveAction<K, independent::IndependentNode<K, T, S>, T, M>) {
620        match action {
621            WeaveAction::Insert(node) => {
622                assert!(self.insert(node), "Failed to apply Weave action");
623            }
624            WeaveAction::SetActive { id, value } => {
625                assert!(self.set_active(&id, value), "Failed to apply Weave action");
626            }
627            WeaveAction::SetBookmarked { id, value } => {
628                assert!(
629                    self.set_bookmarked(&id, value),
630                    "Failed to apply Weave action"
631                );
632            }
633            WeaveAction::Remove(id) => {
634                assert!(self.remove(&id).is_some(), "Failed to apply Weave action");
635            }
636            WeaveAction::Clear => self.clear(),
637            WeaveAction::SetMetadata(metadata) => {
638                self.metadata_mut(|m| *m = metadata);
639            }
640            WeaveAction::SetChildOrdering { parent, children } => {
641                let mut id_mapping =
642                    HashMap::with_capacity_and_hasher(children.len(), S::default());
643                id_mapping.extend(
644                    children
645                        .into_iter()
646                        .enumerate()
647                        .map(|(index, id)| (id, index)),
648                );
649
650                match parent {
651                    Some(id) => {
652                        assert!(
653                            self.sort_children_by_id(&id, |a, b| {
654                                id_mapping[a].cmp(&id_mapping[b])
655                            }),
656                            "Failed to apply Weave action"
657                        );
658                    }
659                    None => {
660                        self.sort_roots_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
661                    }
662                }
663            }
664            WeaveAction::SetBookmarkOrdering(ids) => {
665                let mut id_mapping = HashMap::with_capacity_and_hasher(ids.len(), S::default());
666                id_mapping.extend(ids.into_iter().enumerate().map(|(index, id)| (id, index)));
667
668                self.sort_bookmarks_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
669            }
670            WeaveAction::SetActivePath(active) => {
671                self.set_active_path(active.into_iter());
672            }
673            WeaveAction::MoveTo { id, new_parents } => assert!(
674                self.move_to(&id, &new_parents),
675                "Failed to apply Weave action"
676            ),
677            WeaveAction::SetContents { id, contents } => {
678                assert!(
679                    self.get_contents_mut(&id, |c| *c = contents).is_some(),
680                    "Failed to apply Weave action"
681                );
682            }
683            WeaveAction::Split { id, at, new_id } => {
684                assert!(self.split(&id, at, new_id), "Failed to apply Weave action");
685            }
686            WeaveAction::MergeWithParent(id) => assert!(
687                self.merge_with_parent(&id).is_some(),
688                "Failed to apply Weave action"
689            ),
690        }
691    }
692}
693
694impl<W, K, N, T, M> Weave<K, N, T> for LoggedWeave<W, K, N, T, M>
695where
696    W: Weave<K, N, T>,
697    K: Hash + Copy + Eq + Ord,
698    N: Node<K, T> + Clone,
699{
700    type Nodes = W::Nodes;
701    type Roots = W::Roots;
702
703    #[inline]
704    fn len(&self) -> usize {
705        self.weave.len()
706    }
707    #[inline]
708    fn is_empty(&self) -> bool {
709        self.weave.is_empty()
710    }
711    #[inline]
712    fn nodes(&self) -> &Self::Nodes {
713        self.weave.nodes()
714    }
715    #[inline]
716    fn roots(&self) -> &Self::Roots {
717        self.weave.roots()
718    }
719    #[inline]
720    fn contains(&self, id: &K) -> bool {
721        self.weave.contains(id)
722    }
723    #[inline]
724    fn contains_active(&self, id: &K) -> bool {
725        self.weave.contains_active(id)
726    }
727    #[inline]
728    fn get(&self, id: &K) -> Option<&N> {
729        self.weave.get(id)
730    }
731    #[inline]
732    fn get_parents(&self, id: &K) -> Option<&N::From> {
733        self.weave.get_parents(id)
734    }
735    #[inline]
736    fn get_children(&self, id: &K) -> Option<&N::To> {
737        self.weave.get_children(id)
738    }
739    #[inline]
740    fn get_contents(&self, id: &K) -> Option<&T> {
741        self.weave.get_contents(id)
742    }
743    #[inline]
744    fn get_ordered_identifiers(&mut self, output: &mut Vec<K>) {
745        self.weave.get_ordered_identifiers(output);
746    }
747    #[inline]
748    fn get_ordered_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
749        self.weave.get_ordered_identifiers_from(id, output);
750    }
751    #[inline]
752    fn get_active_path(&mut self, output: &mut Vec<K>) {
753        self.weave.get_active_path(output);
754    }
755    #[inline]
756    fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
757        self.weave.get_path_from(id, output);
758    }
759    fn insert(&mut self, node: N) -> bool {
760        if self.weave.insert(node.clone()) {
761            self.actions.push_back(WeaveAction::Insert(node));
762            true
763        } else {
764            false
765        }
766    }
767    fn set_active(&mut self, id: &K, value: bool) -> bool {
768        if self.weave.set_active(id, value) {
769            self.actions
770                .push_back(WeaveAction::SetActive { id: *id, value });
771            true
772        } else {
773            false
774        }
775    }
776    fn remove(&mut self, id: &K) -> Option<N> {
777        if let Some(removed) = self.weave.remove(id) {
778            self.actions.push_back(WeaveAction::Remove(*id));
779            Some(removed)
780        } else {
781            None
782        }
783    }
784    fn remove_tracked(&mut self, id: &K, on_removal: impl FnMut(N)) -> bool {
785        if self.weave.remove_tracked(id, on_removal) {
786            self.actions.push_back(WeaveAction::Remove(*id));
787            true
788        } else {
789            false
790        }
791    }
792    fn clear(&mut self) {
793        self.weave.clear();
794        self.actions.push_back(WeaveAction::Clear);
795    }
796}
797
798impl<W, K, N, T, M> MetadataWeave<K, N, T, M> for LoggedWeave<W, K, N, T, M>
799where
800    W: MetadataWeave<K, N, T, M>,
801    K: Hash + Copy + Eq + Ord,
802    N: Node<K, T> + Clone,
803    M: Clone,
804{
805    #[inline]
806    fn metadata(&self) -> &M {
807        self.weave.metadata()
808    }
809    fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
810        self.weave.metadata_mut(|metadata| {
811            let output = callback(metadata);
812
813            self.actions
814                .push_back(WeaveAction::SetMetadata(metadata.clone()));
815
816            output
817        })
818    }
819}
820
821impl<W, K, N, T, M> BookmarkableWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
822where
823    W: BookmarkableWeave<K, N, T>,
824    K: Hash + Copy + Eq + Ord,
825    N: Node<K, T> + Clone,
826{
827    type Bookmarks = W::Bookmarks;
828
829    #[inline]
830    fn bookmarks(&self) -> &Self::Bookmarks {
831        self.weave.bookmarks()
832    }
833    #[inline]
834    fn contains_bookmark(&self, id: &K) -> bool {
835        self.weave.contains_bookmark(id)
836    }
837    fn set_bookmarked(&mut self, id: &K, value: bool) -> bool {
838        if self.weave.set_bookmarked(id, value) {
839            self.actions
840                .push_back(WeaveAction::SetBookmarked { id: *id, value });
841            true
842        } else {
843            false
844        }
845    }
846}
847
848impl<W, K, N, T, M> SortableWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
849where
850    W: SortableWeave<K, N, T>,
851    K: Hash + Copy + Eq + Ord,
852    N: Node<K, T> + Clone,
853    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
854    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
855{
856    fn sort_children_by(&mut self, id: &K, cmp: impl FnMut(&N, &N) -> Ordering) -> bool {
857        if self.weave.sort_children_by(id, cmp) {
858            self.actions.push_back(WeaveAction::SetChildOrdering {
859                parent: Some(*id),
860                children: self
861                    .weave
862                    .get_children(id)
863                    .unwrap()
864                    .into_iter()
865                    .copied()
866                    .collect(),
867            });
868            true
869        } else {
870            false
871        }
872    }
873    fn sort_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
874        if self.weave.sort_children_by_id(id, cmp) {
875            self.actions.push_back(WeaveAction::SetChildOrdering {
876                parent: Some(*id),
877                children: self
878                    .weave
879                    .get_children(id)
880                    .unwrap()
881                    .into_iter()
882                    .copied()
883                    .collect(),
884            });
885            true
886        } else {
887            false
888        }
889    }
890    fn sort_roots_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
891        self.weave.sort_roots_by(cmp);
892        self.actions.push_back(WeaveAction::SetChildOrdering {
893            parent: None,
894            children: self.weave.roots().into_iter().copied().collect(),
895        });
896    }
897    fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
898        self.weave.sort_roots_by_id(cmp);
899        self.actions.push_back(WeaveAction::SetChildOrdering {
900            parent: None,
901            children: self.weave.roots().into_iter().copied().collect(),
902        });
903    }
904}
905
906impl<W, K, N, T, M> SortableBookmarkableWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
907where
908    W: SortableBookmarkableWeave<K, N, T>,
909    K: Hash + Copy + Eq + Ord,
910    N: Node<K, T> + Clone,
911    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
912    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
913    for<'a> &'a W::Bookmarks: IntoIterator<Item = &'a K>,
914{
915    fn sort_bookmarks_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
916        self.weave.sort_bookmarks_by(cmp);
917        self.actions.push_back(WeaveAction::SetBookmarkOrdering(
918            self.weave.bookmarks().into_iter().copied().collect(),
919        ));
920    }
921    fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
922        self.weave.sort_bookmarks_by_id(cmp);
923        self.actions.push_back(WeaveAction::SetBookmarkOrdering(
924            self.weave.bookmarks().into_iter().copied().collect(),
925        ));
926    }
927}
928
929impl<W, K, N, T, M> ActiveSingularWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
930where
931    W: ActiveSingularWeave<K, N, T>,
932    K: Hash + Copy + Eq + Ord,
933    N: Node<K, T> + Clone,
934{
935    #[inline]
936    fn active(&self) -> Option<K> {
937        self.weave.active()
938    }
939}
940
941impl<W, K, N, T, M> ActivePathWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
942where
943    W: ActivePathWeave<K, N, T>,
944    K: Hash + Copy + Eq + Ord,
945    N: Node<K, T> + Clone,
946{
947    type Active = W::Active;
948
949    #[inline]
950    fn active(&self) -> &Self::Active {
951        self.weave.active()
952    }
953    fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
954        let active: Vec<K> = active.collect();
955
956        self.weave.set_active_path(active.iter().copied());
957        self.actions.push_back(WeaveAction::SetActivePath(active));
958    }
959}
960
961impl<W, K, N, T, M> IndependentWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
962where
963    W: IndependentWeave<K, N, T>,
964    K: Hash + Copy + Eq + Ord,
965    N: Node<K, T> + Clone,
966    T: IndependentContents + Clone,
967{
968    fn move_to(&mut self, id: &K, new_parents: &[K]) -> bool {
969        if self.weave.move_to(id, new_parents) {
970            self.actions.push_back(WeaveAction::MoveTo {
971                id: *id,
972                new_parents: new_parents.to_vec(),
973            });
974            true
975        } else {
976            false
977        }
978    }
979}
980
981impl<W, K, N, T, M> SemiIndependentWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
982where
983    W: SemiIndependentWeave<K, N, T>,
984    K: Hash + Copy + Eq + Ord,
985    N: Node<K, T> + Clone,
986    T: IndependentContents + Clone,
987{
988    fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
989        self.weave
990            .get_contents_mut(id, |contents| (callback(contents), contents.clone()))
991            .map(|(output, contents)| {
992                self.actions
993                    .push_back(WeaveAction::SetContents { id: *id, contents });
994
995                output
996            })
997    }
998}
999
1000impl<W, K, N, T, M> DiscreteWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
1001where
1002    W: DiscreteWeave<K, N, T>,
1003    K: Hash + Copy + Eq + Ord,
1004    N: Node<K, T> + Clone,
1005    T: DiscreteContents,
1006{
1007    fn split(&mut self, id: &K, at: usize, new_id: K) -> bool {
1008        if self.weave.split(id, at, new_id) {
1009            self.actions.push_back(WeaveAction::Split {
1010                id: *id,
1011                at,
1012                new_id,
1013            });
1014            true
1015        } else {
1016            false
1017        }
1018    }
1019    fn merge_with_parent(&mut self, id: &K) -> Option<K> {
1020        match self.weave.merge_with_parent(id) {
1021            Some(new_id) => {
1022                self.actions.push_back(WeaveAction::MergeWithParent(*id));
1023                Some(new_id)
1024            }
1025            None => None,
1026        }
1027    }
1028}
1029
1030impl<W, K, N, T> Weave<K, N, T> for CountedWeave<W, K, N, T>
1031where
1032    W: Weave<K, N, T>,
1033    K: Hash + Copy + Eq + Ord,
1034    N: Node<K, T>,
1035{
1036    type Nodes = W::Nodes;
1037    type Roots = W::Roots;
1038
1039    #[inline]
1040    fn len(&self) -> usize {
1041        self.weave.len()
1042    }
1043    #[inline]
1044    fn is_empty(&self) -> bool {
1045        self.weave.is_empty()
1046    }
1047    #[inline]
1048    fn nodes(&self) -> &Self::Nodes {
1049        self.weave.nodes()
1050    }
1051    #[inline]
1052    fn roots(&self) -> &Self::Roots {
1053        self.weave.roots()
1054    }
1055    #[inline]
1056    fn contains(&self, id: &K) -> bool {
1057        self.weave.contains(id)
1058    }
1059    #[inline]
1060    fn contains_active(&self, id: &K) -> bool {
1061        self.weave.contains_active(id)
1062    }
1063    #[inline]
1064    fn get(&self, id: &K) -> Option<&N> {
1065        self.weave.get(id)
1066    }
1067    #[inline]
1068    fn get_parents(&self, id: &K) -> Option<&N::From> {
1069        self.weave.get_parents(id)
1070    }
1071    #[inline]
1072    fn get_children(&self, id: &K) -> Option<&N::To> {
1073        self.weave.get_children(id)
1074    }
1075    #[inline]
1076    fn get_contents(&self, id: &K) -> Option<&T> {
1077        self.weave.get_contents(id)
1078    }
1079    #[inline]
1080    fn get_ordered_identifiers(&mut self, output: &mut Vec<K>) {
1081        self.weave.get_ordered_identifiers(output);
1082    }
1083    #[inline]
1084    fn get_ordered_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
1085        self.weave.get_ordered_identifiers_from(id, output);
1086    }
1087    #[inline]
1088    fn get_active_path(&mut self, output: &mut Vec<K>) {
1089        self.weave.get_active_path(output);
1090    }
1091    #[inline]
1092    fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
1093        self.weave.get_path_from(id, output);
1094    }
1095    #[inline]
1096    fn insert(&mut self, node: N) -> bool {
1097        if self.weave.insert(node) {
1098            self.count.insert = self.count.insert.saturating_add(1);
1099            true
1100        } else {
1101            false
1102        }
1103    }
1104    #[inline]
1105    fn set_active(&mut self, id: &K, value: bool) -> bool {
1106        if self.weave.set_active(id, value) {
1107            self.count.set_active = self.count.set_active.saturating_add(1);
1108            true
1109        } else {
1110            false
1111        }
1112    }
1113    #[inline]
1114    fn remove(&mut self, id: &K) -> Option<N> {
1115        if let Some(removed) = self.weave.remove(id) {
1116            self.count.remove = self.count.remove.saturating_add(1);
1117            Some(removed)
1118        } else {
1119            None
1120        }
1121    }
1122    #[inline]
1123    fn remove_tracked(&mut self, id: &K, on_removal: impl FnMut(N)) -> bool {
1124        if self.weave.remove_tracked(id, on_removal) {
1125            self.count.remove = self.count.remove.saturating_add(1);
1126            true
1127        } else {
1128            false
1129        }
1130    }
1131    #[inline]
1132    fn clear(&mut self) {
1133        self.weave.clear();
1134        self.count.clear = self.count.clear.saturating_add(1);
1135    }
1136}
1137
1138impl<W, K, N, T, M> MetadataWeave<K, N, T, M> for CountedWeave<W, K, N, T>
1139where
1140    W: MetadataWeave<K, N, T, M>,
1141    K: Hash + Copy + Eq + Ord,
1142    N: Node<K, T>,
1143{
1144    #[inline]
1145    fn metadata(&self) -> &M {
1146        self.weave.metadata()
1147    }
1148    #[inline]
1149    fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
1150        self.weave.metadata_mut(|metadata| {
1151            let output = callback(metadata);
1152            self.count.metadata_mut = self.count.metadata_mut.saturating_add(1);
1153            output
1154        })
1155    }
1156}
1157
1158impl<W, K, N, T> BookmarkableWeave<K, N, T> for CountedWeave<W, K, N, T>
1159where
1160    W: BookmarkableWeave<K, N, T>,
1161    K: Hash + Copy + Eq + Ord,
1162    N: Node<K, T>,
1163{
1164    type Bookmarks = W::Bookmarks;
1165
1166    #[inline]
1167    fn bookmarks(&self) -> &Self::Bookmarks {
1168        self.weave.bookmarks()
1169    }
1170    #[inline]
1171    fn contains_bookmark(&self, id: &K) -> bool {
1172        self.weave.contains_bookmark(id)
1173    }
1174    #[inline]
1175    fn set_bookmarked(&mut self, id: &K, value: bool) -> bool {
1176        if self.weave.set_bookmarked(id, value) {
1177            self.count.set_bookmarked = self.count.set_bookmarked.saturating_add(1);
1178            true
1179        } else {
1180            false
1181        }
1182    }
1183}
1184
1185impl<W, K, N, T> SortableWeave<K, N, T> for CountedWeave<W, K, N, T>
1186where
1187    W: SortableWeave<K, N, T>,
1188    K: Hash + Copy + Eq + Ord,
1189    N: Node<K, T>,
1190{
1191    #[inline]
1192    fn sort_children_by(&mut self, id: &K, cmp: impl FnMut(&N, &N) -> Ordering) -> bool {
1193        if self.weave.sort_children_by(id, cmp) {
1194            self.count.sort_children = self.count.sort_children.saturating_add(1);
1195            true
1196        } else {
1197            false
1198        }
1199    }
1200    #[inline]
1201    fn sort_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
1202        if self.weave.sort_children_by_id(id, cmp) {
1203            self.count.sort_children = self.count.sort_children.saturating_add(1);
1204            true
1205        } else {
1206            false
1207        }
1208    }
1209    #[inline]
1210    fn sort_roots_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
1211        self.weave.sort_roots_by(cmp);
1212        self.count.sort_roots = self.count.sort_roots.saturating_add(1);
1213    }
1214    #[inline]
1215    fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1216        self.weave.sort_roots_by_id(cmp);
1217        self.count.sort_roots = self.count.sort_roots.saturating_add(1);
1218    }
1219}
1220
1221impl<W, K, N, T> SortableBookmarkableWeave<K, N, T> for CountedWeave<W, K, N, T>
1222where
1223    W: SortableBookmarkableWeave<K, N, T>,
1224    K: Hash + Copy + Eq + Ord,
1225    N: Node<K, T>,
1226{
1227    #[inline]
1228    fn sort_bookmarks_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
1229        self.weave.sort_bookmarks_by(cmp);
1230        self.count.sort_bookmarks = self.count.sort_bookmarks.saturating_add(1);
1231    }
1232    #[inline]
1233    fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1234        self.weave.sort_bookmarks_by_id(cmp);
1235        self.count.sort_bookmarks = self.count.sort_bookmarks.saturating_add(1);
1236    }
1237}
1238
1239impl<W, K, N, T> ActiveSingularWeave<K, N, T> for CountedWeave<W, K, N, T>
1240where
1241    W: ActiveSingularWeave<K, N, T>,
1242    K: Hash + Copy + Eq + Ord,
1243    N: Node<K, T>,
1244{
1245    #[inline]
1246    fn active(&self) -> Option<K> {
1247        self.weave.active()
1248    }
1249}
1250
1251impl<W, K, N, T> ActivePathWeave<K, N, T> for CountedWeave<W, K, N, T>
1252where
1253    W: ActivePathWeave<K, N, T>,
1254    K: Hash + Copy + Eq + Ord,
1255    N: Node<K, T>,
1256{
1257    type Active = W::Active;
1258
1259    #[inline]
1260    fn active(&self) -> &Self::Active {
1261        self.weave.active()
1262    }
1263    #[inline]
1264    fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
1265        self.weave.set_active_path(active);
1266        self.count.set_active_path = self.count.set_active_path.saturating_add(1);
1267    }
1268}
1269
1270impl<W, K, N, T> IndependentWeave<K, N, T> for CountedWeave<W, K, N, T>
1271where
1272    W: IndependentWeave<K, N, T>,
1273    K: Hash + Copy + Eq + Ord,
1274    N: Node<K, T>,
1275    T: IndependentContents,
1276{
1277    #[inline]
1278    fn move_to(&mut self, id: &K, new_parents: &[K]) -> bool {
1279        if self.weave.move_to(id, new_parents) {
1280            self.count.move_to = self.count.move_to.saturating_add(1);
1281            true
1282        } else {
1283            false
1284        }
1285    }
1286}
1287
1288impl<W, K, N, T> SemiIndependentWeave<K, N, T> for CountedWeave<W, K, N, T>
1289where
1290    W: SemiIndependentWeave<K, N, T>,
1291    K: Hash + Copy + Eq + Ord,
1292    N: Node<K, T>,
1293    T: IndependentContents,
1294{
1295    #[inline]
1296    fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
1297        self.weave.get_contents_mut(id, callback).inspect(|_| {
1298            self.count.get_contents_mut = self.count.get_contents_mut.saturating_add(1);
1299        })
1300    }
1301}
1302
1303impl<W, K, N, T> DiscreteWeave<K, N, T> for CountedWeave<W, K, N, T>
1304where
1305    W: DiscreteWeave<K, N, T>,
1306    K: Hash + Copy + Eq + Ord,
1307    N: Node<K, T>,
1308    T: DiscreteContents,
1309{
1310    #[inline]
1311    fn split(&mut self, id: &K, at: usize, new_id: K) -> bool {
1312        if self.weave.split(id, at, new_id) {
1313            self.count.split = self.count.split.saturating_add(1);
1314            true
1315        } else {
1316            false
1317        }
1318    }
1319    #[inline]
1320    fn merge_with_parent(&mut self, id: &K) -> Option<K> {
1321        match self.weave.merge_with_parent(id) {
1322            Some(new_id) => {
1323                self.count.merge_with_parent = self.count.merge_with_parent.saturating_add(1);
1324                Some(new_id)
1325            }
1326            None => None,
1327        }
1328    }
1329}
1330
1331/// A [`Weave`] wrapper which prevents actions from creating siblings with duplicate contents.
1332///
1333/// Siblings which are also parents or children of the target node are excluded.
1334///
1335/// # Limitations
1336///
1337/// It is possible for [`Weave::insert()`], [`Weave::remove()`], and [`Weave::remove_tracked()`] to create duplicate siblings under circumstances specified in the function's documentation.
1338#[derive(Default, Debug, Clone, PartialEq, Eq)]
1339#[must_use]
1340pub struct DeduplicatedWeave<W, K, N, T, S>
1341where
1342    W: Weave<K, N, T>,
1343    K: Hash + Copy + Eq + Ord,
1344    T: DeduplicatableContents,
1345    N: Node<K, T>,
1346    S: BuildHasher + Default + Clone,
1347    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1348    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1349    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1350{
1351    /// The [`Weave`] being wrapped.
1352    ///
1353    /// Actions performed directly on the inner [`Weave`] (without using the wrapper's functions) are not checked.
1354    pub weave: W,
1355
1356    scratchpad: HashSet<K, S>,
1357    _phantom_n: PhantomData<N>,
1358    _phantom_t: PhantomData<T>,
1359}
1360
1361impl<W, K, N, T, S> DeduplicatedWeave<W, K, N, T, S>
1362where
1363    W: Weave<K, N, T>,
1364    K: Hash + Copy + Eq + Ord,
1365    T: DeduplicatableContents,
1366    N: Node<K, T>,
1367    S: BuildHasher + Default + Clone,
1368    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1369    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1370    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1371{
1372    /// Creates a [`DeduplicatedWeave`] from a [`Weave`].
1373    pub fn new(weave: W) -> Self {
1374        Self {
1375            scratchpad: HashSet::with_capacity_and_hasher(weave.len(), S::default()),
1376            weave,
1377            _phantom_n: PhantomData,
1378            _phantom_t: PhantomData,
1379        }
1380    }
1381    /// Converts a [`DeduplicatedWeave`] into it's inner [`Weave`].
1382    #[inline]
1383    pub fn into_inner(self) -> W {
1384        self.weave
1385    }
1386    /// Returns a reference to the inner [`Weave`].
1387    #[inline]
1388    pub const fn as_inner(&self) -> &W {
1389        &self.weave
1390    }
1391}
1392
1393fn has_duplicate_siblings<W, K, N, T, S, I, F, O>(
1394    weave: &W,
1395    ignored: &I,
1396    parents: &F,
1397    children: &O,
1398    contents: &T,
1399    scratchpad: &mut HashSet<K, S>,
1400) -> bool
1401where
1402    W: Weave<K, N, T>,
1403    K: Hash + Copy + Eq + Ord,
1404    T: DeduplicatableContents,
1405    N: Node<K, T>,
1406    S: BuildHasher + Default + Clone,
1407    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1408    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1409    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1410    for<'a> &'a I: IntoIterator<Item = &'a K>,
1411    for<'a> &'a F: IntoIterator<Item = &'a K>,
1412    for<'a> &'a O: IntoIterator<Item = &'a K>,
1413    F: ?Sized,
1414    O: ?Sized,
1415{
1416    if parents.into_iter().next().is_none() {
1417        scratchpad.extend(weave.roots().into_iter().copied());
1418    } else {
1419        for sibling in parents
1420            .into_iter()
1421            .filter_map(|id| weave.get_children(id))
1422            .flatten()
1423            .copied()
1424        {
1425            scratchpad.insert(sibling);
1426        }
1427    }
1428
1429    for parent in parents {
1430        scratchpad.remove(parent);
1431    }
1432
1433    for child in children {
1434        scratchpad.remove(child);
1435    }
1436
1437    for ignore in ignored {
1438        scratchpad.remove(ignore);
1439    }
1440
1441    scratchpad
1442        .drain()
1443        .filter_map(|id| weave.get_contents(&id))
1444        .any(|c| c.is_duplicate_of(contents))
1445}
1446
1447impl<W, K, N, T, S> Weave<K, N, T> for DeduplicatedWeave<W, K, N, T, S>
1448where
1449    W: Weave<K, N, T>,
1450    K: Hash + Copy + Eq + Ord,
1451    T: DeduplicatableContents,
1452    N: Node<K, T>,
1453    S: BuildHasher + Default + Clone,
1454    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1455    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1456    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1457{
1458    type Nodes = W::Nodes;
1459    type Roots = W::Roots;
1460
1461    #[inline]
1462    fn len(&self) -> usize {
1463        self.weave.len()
1464    }
1465    #[inline]
1466    fn is_empty(&self) -> bool {
1467        self.weave.is_empty()
1468    }
1469    #[inline]
1470    fn nodes(&self) -> &Self::Nodes {
1471        self.weave.nodes()
1472    }
1473    #[inline]
1474    fn roots(&self) -> &Self::Roots {
1475        self.weave.roots()
1476    }
1477    #[inline]
1478    fn contains(&self, id: &K) -> bool {
1479        self.weave.contains(id)
1480    }
1481    #[inline]
1482    fn contains_active(&self, id: &K) -> bool {
1483        self.weave.contains_active(id)
1484    }
1485    #[inline]
1486    fn get(&self, id: &K) -> Option<&N> {
1487        self.weave.get(id)
1488    }
1489    #[inline]
1490    fn get_parents(&self, id: &K) -> Option<&N::From> {
1491        self.weave.get_parents(id)
1492    }
1493    #[inline]
1494    fn get_children(&self, id: &K) -> Option<&N::To> {
1495        self.weave.get_children(id)
1496    }
1497    #[inline]
1498    fn get_contents(&self, id: &K) -> Option<&T> {
1499        self.weave.get_contents(id)
1500    }
1501    #[inline]
1502    fn get_ordered_identifiers(&mut self, output: &mut Vec<K>) {
1503        self.weave.get_ordered_identifiers(output);
1504    }
1505    #[inline]
1506    fn get_ordered_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
1507        self.weave.get_ordered_identifiers_from(id, output);
1508    }
1509    #[inline]
1510    fn get_active_path(&mut self, output: &mut Vec<K>) {
1511        self.weave.get_active_path(output);
1512    }
1513    #[inline]
1514    fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
1515        self.weave.get_path_from(id, output);
1516    }
1517    /// Inserts a node into the Weave, returning `true` if the insertion was successful.
1518    ///
1519    /// This function may change the active status of nodes if it is necessary to preserve internal consistency.
1520    ///
1521    /// # Deduplication
1522    ///
1523    /// This function does not deduplicate the node's children. As a result, it is possible (albeit uncommon) for this operation to create duplicate siblings.
1524    fn insert(&mut self, node: N) -> bool {
1525        if has_duplicate_siblings(
1526            &self.weave,
1527            &[node.id()],
1528            node.from(),
1529            node.to(),
1530            node.contents(),
1531            &mut self.scratchpad,
1532        ) {
1533            return false;
1534        }
1535
1536        self.weave.insert(node)
1537    }
1538    #[inline]
1539    fn set_active(&mut self, id: &K, value: bool) -> bool {
1540        self.weave.set_active(id, value)
1541    }
1542    /// Removes a node with the specified identifier, returning its value if it was present within the Weave.
1543    ///
1544    /// This function may remove or update other nodes if it is necessary to preserve internal consistency.
1545    ///
1546    /// This function uses the same removal logic as [`Weave::remove_tracked`].
1547    ///
1548    /// # Deduplication
1549    ///
1550    /// If the underlying [`Weave::remove()`] implementation reparents nodes, this operation may create duplicate siblings.
1551    #[inline]
1552    fn remove(&mut self, id: &K) -> Option<N> {
1553        self.weave.remove(id)
1554    }
1555    /// Removes a node with the specified identifier, returning `true` if it was present within the Weave.
1556    ///
1557    /// This function may remove or update other nodes if it is necessary to preserve internal consistency. Every removed node will be returned by the `on_removal` call, with removal ordering being defined by the `Weave` implementation.
1558    ///
1559    /// # Panics
1560    ///
1561    /// May panic if `on_removal` panics.
1562    ///
1563    /// # Deduplication
1564    ///
1565    /// If the underlying [`Weave::remove_tracked()`] implementation reparents nodes, this operation may create duplicate siblings.
1566    #[inline]
1567    fn remove_tracked(&mut self, id: &K, on_removal: impl FnMut(N)) -> bool {
1568        self.weave.remove_tracked(id, on_removal)
1569    }
1570    #[inline]
1571    fn clear(&mut self) {
1572        self.weave.clear();
1573    }
1574}
1575
1576impl<W, K, N, T, M, S> MetadataWeave<K, N, T, M> for DeduplicatedWeave<W, K, N, T, S>
1577where
1578    W: MetadataWeave<K, N, T, M>,
1579    K: Hash + Copy + Eq + Ord,
1580    T: DeduplicatableContents,
1581    N: Node<K, T>,
1582    S: BuildHasher + Default + Clone,
1583    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1584    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1585    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1586{
1587    #[inline]
1588    fn metadata(&self) -> &M {
1589        self.weave.metadata()
1590    }
1591    #[inline]
1592    fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
1593        self.weave.metadata_mut(callback)
1594    }
1595}
1596
1597impl<W, K, N, T, S> BookmarkableWeave<K, N, T> for DeduplicatedWeave<W, K, N, T, S>
1598where
1599    W: BookmarkableWeave<K, N, T>,
1600    K: Hash + Copy + Eq + Ord,
1601    T: DeduplicatableContents,
1602    N: Node<K, T>,
1603    S: BuildHasher + Default + Clone,
1604    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1605    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1606    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1607{
1608    type Bookmarks = W::Bookmarks;
1609
1610    #[inline]
1611    fn bookmarks(&self) -> &Self::Bookmarks {
1612        self.weave.bookmarks()
1613    }
1614    #[inline]
1615    fn contains_bookmark(&self, id: &K) -> bool {
1616        self.weave.contains_bookmark(id)
1617    }
1618    #[inline]
1619    fn set_bookmarked(&mut self, id: &K, value: bool) -> bool {
1620        self.weave.set_bookmarked(id, value)
1621    }
1622}
1623
1624impl<W, K, N, T, S> SortableWeave<K, N, T> for DeduplicatedWeave<W, K, N, T, S>
1625where
1626    W: SortableWeave<K, N, T>,
1627    K: Hash + Copy + Eq + Ord,
1628    T: DeduplicatableContents,
1629    N: Node<K, T>,
1630    S: BuildHasher + Default + Clone,
1631    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1632    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1633    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1634{
1635    #[inline]
1636    fn sort_children_by(&mut self, id: &K, cmp: impl FnMut(&N, &N) -> Ordering) -> bool {
1637        self.weave.sort_children_by(id, cmp)
1638    }
1639    #[inline]
1640    fn sort_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
1641        self.weave.sort_children_by_id(id, cmp)
1642    }
1643    #[inline]
1644    fn sort_roots_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
1645        self.weave.sort_roots_by(cmp);
1646    }
1647    #[inline]
1648    fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1649        self.weave.sort_roots_by_id(cmp);
1650    }
1651}
1652
1653impl<W, K, N, T, S> SortableBookmarkableWeave<K, N, T> for DeduplicatedWeave<W, K, N, T, S>
1654where
1655    W: SortableBookmarkableWeave<K, N, T>,
1656    K: Hash + Copy + Eq + Ord,
1657    T: DeduplicatableContents,
1658    N: Node<K, T>,
1659    S: BuildHasher + Default + Clone,
1660    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1661    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1662    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1663{
1664    #[inline]
1665    fn sort_bookmarks_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
1666        self.weave.sort_bookmarks_by(cmp);
1667    }
1668    #[inline]
1669    fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1670        self.weave.sort_bookmarks_by_id(cmp);
1671    }
1672}
1673
1674impl<W, K, N, T, S> ActiveSingularWeave<K, N, T> for DeduplicatedWeave<W, K, N, T, S>
1675where
1676    W: ActiveSingularWeave<K, N, T>,
1677    K: Hash + Copy + Eq + Ord,
1678    T: DeduplicatableContents,
1679    N: Node<K, T>,
1680    S: BuildHasher + Default + Clone,
1681    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1682    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1683    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1684{
1685    #[inline]
1686    fn active(&self) -> Option<K> {
1687        self.weave.active()
1688    }
1689}
1690
1691impl<W, K, N, T, S> ActivePathWeave<K, N, T> for DeduplicatedWeave<W, K, N, T, S>
1692where
1693    W: ActivePathWeave<K, N, T>,
1694    K: Hash + Copy + Eq + Ord,
1695    T: DeduplicatableContents,
1696    N: Node<K, T>,
1697    S: BuildHasher + Default + Clone,
1698    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1699    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1700    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1701{
1702    type Active = W::Active;
1703
1704    #[inline]
1705    fn active(&self) -> &Self::Active {
1706        self.weave.active()
1707    }
1708    #[inline]
1709    fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
1710        self.weave.set_active_path(active);
1711    }
1712}
1713
1714impl<W, K, N, T, S> IndependentWeave<K, N, T> for DeduplicatedWeave<W, K, N, T, S>
1715where
1716    W: IndependentWeave<K, N, T>,
1717    K: Hash + Copy + Eq + Ord,
1718    T: IndependentContents + DeduplicatableContents + Clone,
1719    N: Node<K, T>,
1720    S: BuildHasher + Default + Clone,
1721    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1722    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1723    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1724{
1725    fn move_to(&mut self, id: &K, new_parents: &[K]) -> bool {
1726        if let Some(node) = self.weave.get(id) {
1727            if has_duplicate_siblings(
1728                &self.weave,
1729                &[node.id()],
1730                new_parents,
1731                node.to(),
1732                node.contents(),
1733                &mut self.scratchpad,
1734            ) {
1735                return false;
1736            }
1737
1738            self.weave.move_to(id, new_parents)
1739        } else {
1740            false
1741        }
1742    }
1743}
1744
1745impl<W, K, N, T, S> SemiIndependentWeave<K, N, T> for DeduplicatedWeave<W, K, N, T, S>
1746where
1747    W: SemiIndependentWeave<K, N, T>,
1748    K: Hash + Copy + Eq + Ord,
1749    T: IndependentContents + DeduplicatableContents + Clone,
1750    N: Node<K, T>,
1751    S: BuildHasher + Default + Clone,
1752    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1753    for<'a> &'a N::From: IntoIterator<Item = &'a K>,
1754    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1755{
1756    /// Mutable access to the contents of a node with the specified identifier.
1757    ///
1758    /// `callback` may be executed without updating the node's contents.
1759    ///
1760    /// # Panics
1761    ///
1762    /// May panic if `callback` panics.
1763    fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
1764        if let Some(node) = self.weave.get(id) {
1765            let mut contents = node.contents().clone();
1766            let output = callback(&mut contents);
1767
1768            if has_duplicate_siblings(
1769                &self.weave,
1770                &[node.id()],
1771                node.from(),
1772                node.to(),
1773                &contents,
1774                &mut self.scratchpad,
1775            ) {
1776                None
1777            } else if self.weave.get_contents_mut(id, |c| *c = contents).is_some() {
1778                Some(output)
1779            } else {
1780                None
1781            }
1782        } else {
1783            None
1784        }
1785    }
1786}
1787
1788impl<W, K, N, T, S> DiscreteWeave<K, N, T> for DeduplicatedWeave<W, K, N, T, S>
1789where
1790    W: DiscreteWeave<K, N, T>,
1791    K: Hash + Copy + Eq + Ord,
1792    T: DiscreteContents + DeduplicatableContents + Clone,
1793    N: Node<K, T>,
1794    S: BuildHasher + Default + Clone,
1795    for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
1796    for<'a> &'a N::From: IntoIterator<Item = &'a K, IntoIter: ExactSizeIterator>,
1797    for<'a> &'a N::To: IntoIterator<Item = &'a K>,
1798{
1799    fn split(&mut self, id: &K, at: usize, new_id: K) -> bool {
1800        if let Some(node) = self.weave.get(id)
1801            && let DiscreteContentResult::Two(left, _right) = node.contents().clone().split(at)
1802            && has_duplicate_siblings(
1803                &self.weave,
1804                &[node.id()],
1805                node.from(),
1806                &[],
1807                &left,
1808                &mut self.scratchpad,
1809            )
1810        {
1811            return false;
1812        }
1813
1814        self.weave.split(id, at, new_id)
1815    }
1816    fn merge_with_parent(&mut self, id: &K) -> Option<K> {
1817        if let Some(node) = self.weave.get(id) {
1818            if node.from().into_iter().len() != 1 {
1819                return None;
1820            }
1821
1822            if let Some(parent_id) = node.from().into_iter().next()
1823                && let Some(parent) = self.weave.get(parent_id)
1824                && let DiscreteContentResult::One(merged) =
1825                    parent.contents().clone().merge(node.contents().clone())
1826                && has_duplicate_siblings(
1827                    &self.weave,
1828                    &[node.id(), *parent_id],
1829                    parent.from(),
1830                    node.to(),
1831                    &merged,
1832                    &mut self.scratchpad,
1833                )
1834            {
1835                return None;
1836            }
1837        }
1838
1839        self.weave.merge_with_parent(id)
1840    }
1841}