#![allow(missing_docs, reason = "False positives")]
use alloc::{collections::VecDeque, vec::Vec};
use core::{
cmp::Ordering,
hash::{BuildHasher, Hash},
marker::PhantomData,
};
use hashbrown::HashMap;
#[cfg(feature = "rkyv")]
use rkyv::{Archive, Deserialize, Serialize};
#[cfg(feature = "serde")]
use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};
use crate::{
ActivePathWeave, ActiveSingularWeave, BookmarkableWeave, DeduplicatableContents,
DeduplicatableWeave, DiscreteContents, DiscreteWeave, IndependentContents, IndependentWeave,
MetadataWeave, Node, SemiIndependentWeave, SortableBookmarkableWeave, SortableWeave, Weave,
dependent, independent,
};
#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
#[must_use]
pub struct LoggedWeave<W, K, N, T, M>
where
W: Weave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
pub weave: W,
pub actions: VecDeque<WeaveAction<K, N, T, M>>,
}
impl<W, K, N, T, M> AsRef<W> for LoggedWeave<W, K, N, T, M>
where
W: Weave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
#[inline]
fn as_ref(&self) -> &W {
&self.weave
}
}
impl<W, K, N, T, M> From<W> for LoggedWeave<W, K, N, T, M>
where
W: Weave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
#[inline]
fn from(value: W) -> Self {
Self {
weave: value,
actions: VecDeque::new(),
}
}
}
impl<W, K, N, T, M> LoggedWeave<W, K, N, T, M>
where
W: Weave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
#[inline]
pub fn with_capacity(weave: W, capacity: usize) -> Self {
Self {
actions: VecDeque::with_capacity(capacity),
weave,
}
}
#[inline]
pub fn into_weave(self) -> W {
self.weave
}
#[inline]
pub const fn as_weave(&self) -> &W {
&self.weave
}
#[inline]
pub const fn as_actions(&self) -> &VecDeque<WeaveAction<K, N, T, M>> {
&self.actions
}
#[inline]
pub fn clear_actions(&mut self) {
self.actions.clear();
}
pub fn count_actions(&self) -> WeaveActionCount {
let mut count = WeaveActionCount::new();
for action in &self.actions {
count.increment(action);
}
count
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
#[allow(clippy::doc_paragraphs_missing_punctuation, reason = "False positive")]
#[non_exhaustive]
#[must_use]
pub enum WeaveAction<K, N, T, M>
where
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
AddNode(N),
SetNodeActiveStatus { id: K, value: bool },
SetNodeBookmarkedStatus { id: K, value: bool },
RemoveNode(K),
RemoveAllNodes,
SetMetadata(M),
SetNodeChildOrdering { parent: Option<K>, children: Vec<K> },
SetBookmarkOrdering(Vec<K>),
SetActivePath(Vec<K>),
MoveNode { id: K, new_parents: Vec<K> },
SetNodeContent { id: K, contents: T },
SplitNode { id: K, at: usize, new_id: K },
MergeNodeWithParent(K),
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
#[must_use]
pub struct CountedWeave<W, K, N, T>
where
W: Weave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
pub weave: W,
pub count: WeaveActionCount,
_phantom_k: PhantomData<K>,
_phantom_n: PhantomData<N>,
_phantom_t: PhantomData<T>,
}
impl<W, K, N, T> AsRef<W> for CountedWeave<W, K, N, T>
where
W: Weave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
#[inline]
fn as_ref(&self) -> &W {
&self.weave
}
}
impl<W, K, N, T> From<W> for CountedWeave<W, K, N, T>
where
W: Weave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
#[inline]
fn from(value: W) -> Self {
Self {
weave: value,
count: WeaveActionCount::default(),
_phantom_k: PhantomData,
_phantom_n: PhantomData,
_phantom_t: PhantomData,
}
}
}
impl<W, K, N, T> CountedWeave<W, K, N, T>
where
W: Weave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
#[inline]
pub const fn new(weave: W, count: WeaveActionCount) -> Self {
Self {
weave,
count,
_phantom_k: PhantomData,
_phantom_n: PhantomData,
_phantom_t: PhantomData,
}
}
pub fn from_weave(weave: W) -> Self {
Self::new(weave, WeaveActionCount::new())
}
#[inline]
pub fn into_weave(self) -> W {
self.weave
}
#[inline]
pub const fn as_weave(&self) -> &W {
&self.weave
}
#[inline]
pub const fn as_count(&self) -> &WeaveActionCount {
&self.count
}
#[inline]
pub fn reset_count(&mut self) {
self.count.reset();
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
#[allow(clippy::doc_paragraphs_missing_punctuation, reason = "False positive")]
#[non_exhaustive]
#[must_use]
pub struct WeaveActionCount {
pub add_node: usize,
pub set_node_active_status: usize,
pub set_node_bookmarked_status: usize,
pub remove_node: usize,
pub remove_all_nodes: usize,
pub metadata_mut: usize,
pub sort_node_children: usize,
pub sort_roots: usize,
pub sort_bookmarks: usize,
pub set_active_path: usize,
pub move_node: usize,
pub get_contents_mut: usize,
pub split_node: usize,
pub merge_with_parent: usize,
pub other: usize,
}
impl WeaveActionCount {
#[inline]
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn reset(&mut self) {
*self = Self::default();
}
#[must_use]
pub const fn total_count(&self) -> usize {
self.add_node
.saturating_add(self.set_node_active_status)
.saturating_add(self.set_node_bookmarked_status)
.saturating_add(self.remove_node)
.saturating_add(self.remove_all_nodes)
.saturating_add(self.metadata_mut)
.saturating_add(self.sort_node_children)
.saturating_add(self.sort_roots)
.saturating_add(self.sort_bookmarks)
.saturating_add(self.set_active_path)
.saturating_add(self.move_node)
.saturating_add(self.get_contents_mut)
.saturating_add(self.split_node)
.saturating_add(self.merge_with_parent)
.saturating_add(self.other)
}
pub const fn increment<K, N, T, M>(&mut self, action: &WeaveAction<K, N, T, M>)
where
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
match action {
WeaveAction::AddNode(_node) => self.add_node = self.add_node.saturating_add(1),
WeaveAction::SetNodeActiveStatus { .. } => {
self.set_node_active_status = self.set_node_active_status.saturating_add(1);
}
WeaveAction::SetNodeBookmarkedStatus { .. } => {
self.set_node_bookmarked_status = self.set_node_bookmarked_status.saturating_add(1);
}
WeaveAction::RemoveNode(_id) => self.remove_node = self.remove_node.saturating_add(1),
WeaveAction::RemoveAllNodes => {
self.remove_all_nodes = self.remove_all_nodes.saturating_add(1);
}
WeaveAction::SetMetadata(_metadata) => {
self.metadata_mut = self.metadata_mut.saturating_add(1);
}
WeaveAction::SetNodeChildOrdering { parent, .. } => match parent {
Some(_id) => self.sort_node_children = self.sort_node_children.saturating_add(1),
None => self.sort_roots = self.sort_roots.saturating_add(1),
},
WeaveAction::SetBookmarkOrdering(_ids) => {
self.sort_bookmarks = self.sort_bookmarks.saturating_add(1);
}
WeaveAction::SetActivePath(_) => {
self.set_active_path = self.set_active_path.saturating_add(1);
}
WeaveAction::MoveNode { .. } => self.move_node = self.move_node.saturating_add(1),
WeaveAction::SetNodeContent { .. } => {
self.get_contents_mut = self.get_contents_mut.saturating_add(1);
}
WeaveAction::SplitNode { .. } => self.split_node = self.split_node.saturating_add(1),
WeaveAction::MergeNodeWithParent(_id) => {
self.merge_with_parent = self.merge_with_parent.saturating_add(1);
}
}
}
pub const fn decrement<K, N, T, M>(&mut self, action: &WeaveAction<K, N, T, M>)
where
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
match action {
WeaveAction::AddNode(_node) => self.add_node = self.add_node.saturating_sub(1),
WeaveAction::SetNodeActiveStatus { .. } => {
self.set_node_active_status = self.set_node_active_status.saturating_sub(1);
}
WeaveAction::SetNodeBookmarkedStatus { .. } => {
self.set_node_bookmarked_status = self.set_node_bookmarked_status.saturating_sub(1);
}
WeaveAction::RemoveNode(_id) => self.remove_node = self.remove_node.saturating_sub(1),
WeaveAction::RemoveAllNodes => {
self.remove_all_nodes = self.remove_all_nodes.saturating_sub(1);
}
WeaveAction::SetMetadata(_metadata) => {
self.metadata_mut = self.metadata_mut.saturating_sub(1);
}
WeaveAction::SetNodeChildOrdering { parent, .. } => match parent {
Some(_id) => self.sort_node_children = self.sort_node_children.saturating_sub(1),
None => self.sort_roots = self.sort_roots.saturating_sub(1),
},
WeaveAction::SetBookmarkOrdering(_ids) => {
self.sort_bookmarks = self.sort_bookmarks.saturating_sub(1);
}
WeaveAction::SetActivePath(_) => {
self.set_active_path = self.set_active_path.saturating_sub(1);
}
WeaveAction::MoveNode { .. } => self.move_node = self.move_node.saturating_sub(1),
WeaveAction::SetNodeContent { .. } => {
self.get_contents_mut = self.get_contents_mut.saturating_sub(1);
}
WeaveAction::SplitNode { .. } => self.split_node = self.split_node.saturating_sub(1),
WeaveAction::MergeNodeWithParent(_id) => {
self.merge_with_parent = self.merge_with_parent.saturating_sub(1);
}
}
}
}
pub trait ActionableWeave<K, N, T, M, S>
where
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
S: BuildHasher + Default + Clone,
{
fn apply(&mut self, action: WeaveAction<K, N, T, M>);
}
impl<K, T, M, S> ActionableWeave<K, dependent::DependentNode<K, T, S>, T, M, S>
for dependent::DependentWeave<K, T, M, S>
where
K: Hash + Copy + Eq + Ord,
T: IndependentContents + DiscreteContents,
S: BuildHasher + Default + Clone,
{
#[allow(clippy::panic, reason = "Necessary due to API shape")]
fn apply(&mut self, action: WeaveAction<K, dependent::DependentNode<K, T, S>, T, M>) {
match action {
WeaveAction::AddNode(node) => {
assert!(self.add_node(node), "Failed to apply Weave action");
}
WeaveAction::SetNodeActiveStatus { id, value } => {
assert!(
self.set_node_active_status(&id, value),
"Failed to apply Weave action"
);
}
WeaveAction::SetNodeBookmarkedStatus { id, value } => {
assert!(
self.set_node_bookmarked_status(&id, value),
"Failed to apply Weave action"
);
}
WeaveAction::RemoveNode(id) => assert!(
self.remove_node(&id).is_some(),
"Failed to apply Weave action"
),
WeaveAction::RemoveAllNodes => self.remove_all_nodes(),
WeaveAction::SetMetadata(metadata) => {
self.metadata_mut(|m| *m = metadata);
}
WeaveAction::SetNodeChildOrdering { parent, children } => {
let mut id_mapping =
HashMap::with_capacity_and_hasher(children.len(), S::default());
id_mapping.extend(
children
.into_iter()
.enumerate()
.map(|(index, id)| (id, index)),
);
match parent {
Some(id) => {
assert!(
self.sort_node_children_by_id(&id, |a, b| {
id_mapping[a].cmp(&id_mapping[b])
}),
"Failed to apply Weave action"
);
}
None => {
self.sort_roots_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
}
}
}
WeaveAction::SetBookmarkOrdering(ids) => {
let mut id_mapping = HashMap::with_capacity_and_hasher(ids.len(), S::default());
id_mapping.extend(ids.into_iter().enumerate().map(|(index, id)| (id, index)));
self.sort_bookmarks_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
}
WeaveAction::SetActivePath(_) => {
panic!("Weave does not implement set_active_path()");
}
WeaveAction::MoveNode { .. } => {
panic!("Weave does not implement move_node()");
}
WeaveAction::SetNodeContent { id, contents } => {
assert!(
self.get_contents_mut(&id, |c| *c = contents).is_some(),
"Failed to apply Weave action"
);
}
WeaveAction::SplitNode { id, at, new_id } => assert!(
self.split_node(&id, at, new_id),
"Failed to apply Weave action"
),
WeaveAction::MergeNodeWithParent(id) => assert!(
self.merge_with_parent(&id).is_some(),
"Failed to apply Weave action"
),
}
}
}
impl<K, T, M, S> ActionableWeave<K, independent::IndependentNode<K, T, S>, T, M, S>
for independent::IndependentWeave<K, T, M, S>
where
K: Hash + Copy + Eq + Ord,
T: IndependentContents + DiscreteContents,
S: BuildHasher + Default + Clone,
{
fn apply(&mut self, action: WeaveAction<K, independent::IndependentNode<K, T, S>, T, M>) {
match action {
WeaveAction::AddNode(node) => {
assert!(self.add_node(node), "Failed to apply Weave action");
}
WeaveAction::SetNodeActiveStatus { id, value } => {
assert!(
self.set_node_active_status(&id, value),
"Failed to apply Weave action"
);
}
WeaveAction::SetNodeBookmarkedStatus { id, value } => {
assert!(
self.set_node_bookmarked_status(&id, value),
"Failed to apply Weave action"
);
}
WeaveAction::RemoveNode(id) => assert!(
self.remove_node(&id).is_some(),
"Failed to apply Weave action"
),
WeaveAction::RemoveAllNodes => self.remove_all_nodes(),
WeaveAction::SetMetadata(metadata) => {
self.metadata_mut(|m| *m = metadata);
}
WeaveAction::SetNodeChildOrdering { parent, children } => {
let mut id_mapping =
HashMap::with_capacity_and_hasher(children.len(), S::default());
id_mapping.extend(
children
.into_iter()
.enumerate()
.map(|(index, id)| (id, index)),
);
match parent {
Some(id) => {
assert!(
self.sort_node_children_by_id(&id, |a, b| {
id_mapping[a].cmp(&id_mapping[b])
}),
"Failed to apply Weave action"
);
}
None => {
self.sort_roots_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
}
}
}
WeaveAction::SetBookmarkOrdering(ids) => {
let mut id_mapping = HashMap::with_capacity_and_hasher(ids.len(), S::default());
id_mapping.extend(ids.into_iter().enumerate().map(|(index, id)| (id, index)));
self.sort_bookmarks_by_id(|a, b| id_mapping[a].cmp(&id_mapping[b]));
}
WeaveAction::SetActivePath(active) => {
self.set_active_path(active.into_iter());
}
WeaveAction::MoveNode { id, new_parents } => assert!(
self.move_node(&id, &new_parents),
"Failed to apply Weave action"
),
WeaveAction::SetNodeContent { id, contents } => {
assert!(
self.get_contents_mut(&id, |c| *c = contents).is_some(),
"Failed to apply Weave action"
);
}
WeaveAction::SplitNode { id, at, new_id } => assert!(
self.split_node(&id, at, new_id),
"Failed to apply Weave action"
),
WeaveAction::MergeNodeWithParent(id) => assert!(
self.merge_with_parent(&id).is_some(),
"Failed to apply Weave action"
),
}
}
}
impl<W, K, N, T, M> Weave<K, N, T> for LoggedWeave<W, K, N, T, M>
where
W: Weave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T> + Clone,
{
type Nodes = W::Nodes;
type Roots = W::Roots;
#[inline]
fn len(&self) -> usize {
self.weave.len()
}
#[inline]
fn is_empty(&self) -> bool {
self.weave.is_empty()
}
#[inline]
fn nodes(&self) -> &Self::Nodes {
self.weave.nodes()
}
#[inline]
fn roots(&self) -> &Self::Roots {
self.weave.roots()
}
#[inline]
fn contains(&self, id: &K) -> bool {
self.weave.contains(id)
}
#[inline]
fn contains_active(&self, id: &K) -> bool {
self.weave.contains_active(id)
}
#[inline]
fn get_node(&self, id: &K) -> Option<&N> {
self.weave.get_node(id)
}
#[inline]
fn get_ordered_node_identifiers(&mut self, output: &mut Vec<K>) {
self.weave.get_ordered_node_identifiers(output);
}
#[inline]
fn get_ordered_node_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
self.weave.get_ordered_node_identifiers_from(id, output);
}
#[inline]
fn get_active_path(&mut self, output: &mut Vec<K>) {
self.weave.get_active_path(output);
}
#[inline]
fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
self.weave.get_path_from(id, output);
}
fn add_node(&mut self, node: N) -> bool {
if self.weave.add_node(node.clone()) {
self.actions.push_back(WeaveAction::AddNode(node));
true
} else {
false
}
}
fn set_node_active_status(&mut self, id: &K, value: bool) -> bool {
if self.weave.set_node_active_status(id, value) {
self.actions
.push_back(WeaveAction::SetNodeActiveStatus { id: *id, value });
true
} else {
false
}
}
fn remove_node(&mut self, id: &K) -> Option<N> {
if let Some(removed) = self.weave.remove_node(id) {
self.actions.push_back(WeaveAction::RemoveNode(*id));
Some(removed)
} else {
None
}
}
fn remove_node_tracked(&mut self, id: &K, on_removal: impl FnMut(N)) -> bool {
if self.weave.remove_node_tracked(id, on_removal) {
self.actions.push_back(WeaveAction::RemoveNode(*id));
true
} else {
false
}
}
fn remove_all_nodes(&mut self) {
self.weave.remove_all_nodes();
self.actions.push_back(WeaveAction::RemoveAllNodes);
}
}
impl<W, K, N, T, M> MetadataWeave<K, N, T, M> for LoggedWeave<W, K, N, T, M>
where
W: MetadataWeave<K, N, T, M>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T> + Clone,
M: Clone,
{
#[inline]
fn metadata(&self) -> &M {
self.weave.metadata()
}
fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
self.weave.metadata_mut(|metadata| {
let output = callback(metadata);
self.actions
.push_back(WeaveAction::SetMetadata(metadata.clone()));
output
})
}
}
impl<W, K, N, T, M> BookmarkableWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
where
W: BookmarkableWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T> + Clone,
{
type Bookmarks = W::Bookmarks;
#[inline]
fn bookmarks(&self) -> &Self::Bookmarks {
self.weave.bookmarks()
}
#[inline]
fn contains_bookmark(&self, id: &K) -> bool {
self.weave.contains_bookmark(id)
}
fn set_node_bookmarked_status(&mut self, id: &K, value: bool) -> bool {
if self.weave.set_node_bookmarked_status(id, value) {
self.actions
.push_back(WeaveAction::SetNodeBookmarkedStatus { id: *id, value });
true
} else {
false
}
}
}
impl<W, K, N, T, M> SortableWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
where
W: SortableWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T> + Clone,
for<'a> &'a N::To: IntoIterator<Item = &'a K>,
for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
{
#[inline]
fn get_ordered_node_identifiers_mirrored(&mut self, output: &mut Vec<K>) {
self.weave.get_ordered_node_identifiers_mirrored(output);
}
#[inline]
fn get_ordered_node_identifiers_mirrored_from(&mut self, id: &K, output: &mut Vec<K>) {
self.weave
.get_ordered_node_identifiers_mirrored_from(id, output);
}
fn sort_node_children_by(&mut self, id: &K, cmp: impl FnMut(&N, &N) -> Ordering) -> bool {
if self.weave.sort_node_children_by(id, cmp) {
self.actions.push_back(WeaveAction::SetNodeChildOrdering {
parent: Some(*id),
children: self
.weave
.get_node(id)
.unwrap()
.to()
.into_iter()
.copied()
.collect(),
});
true
} else {
false
}
}
fn sort_node_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
if self.weave.sort_node_children_by_id(id, cmp) {
self.actions.push_back(WeaveAction::SetNodeChildOrdering {
parent: Some(*id),
children: self
.weave
.get_node(id)
.unwrap()
.to()
.into_iter()
.copied()
.collect(),
});
true
} else {
false
}
}
fn sort_roots_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
self.weave.sort_roots_by(cmp);
self.actions.push_back(WeaveAction::SetNodeChildOrdering {
parent: None,
children: self.weave.roots().into_iter().copied().collect(),
});
}
fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
self.weave.sort_roots_by_id(cmp);
self.actions.push_back(WeaveAction::SetNodeChildOrdering {
parent: None,
children: self.weave.roots().into_iter().copied().collect(),
});
}
}
impl<W, K, N, T, M> SortableBookmarkableWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
where
W: SortableBookmarkableWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T> + Clone,
for<'a> &'a N::To: IntoIterator<Item = &'a K>,
for<'a> &'a W::Roots: IntoIterator<Item = &'a K>,
for<'a> &'a W::Bookmarks: IntoIterator<Item = &'a K>,
{
fn sort_bookmarks_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
self.weave.sort_bookmarks_by(cmp);
self.actions.push_back(WeaveAction::SetBookmarkOrdering(
self.weave.bookmarks().into_iter().copied().collect(),
));
}
fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
self.weave.sort_bookmarks_by_id(cmp);
self.actions.push_back(WeaveAction::SetBookmarkOrdering(
self.weave.bookmarks().into_iter().copied().collect(),
));
}
}
impl<W, K, N, T, M> ActiveSingularWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
where
W: ActiveSingularWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T> + Clone,
{
#[inline]
fn active(&self) -> Option<K> {
self.weave.active()
}
}
impl<W, K, N, T, M> ActivePathWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
where
W: ActivePathWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T> + Clone,
{
type Active = W::Active;
#[inline]
fn active(&self) -> &Self::Active {
self.weave.active()
}
fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
let active: Vec<K> = active.collect();
self.weave.set_active_path(active.iter().copied());
self.actions.push_back(WeaveAction::SetActivePath(active));
}
}
impl<W, K, N, T, M> IndependentWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
where
W: IndependentWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T> + Clone,
T: IndependentContents + Clone,
{
fn move_node(&mut self, id: &K, new_parents: &[K]) -> bool {
if self.weave.move_node(id, new_parents) {
self.actions.push_back(WeaveAction::MoveNode {
id: *id,
new_parents: new_parents.to_vec(),
});
true
} else {
false
}
}
}
impl<W, K, N, T, M> SemiIndependentWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
where
W: SemiIndependentWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T> + Clone,
T: IndependentContents + Clone,
{
fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
self.weave.get_contents_mut(id, |contents| {
let output = callback(contents);
self.actions.push_back(WeaveAction::SetNodeContent {
id: *id,
contents: contents.clone(),
});
output
})
}
}
impl<W, K, N, T, M> DiscreteWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
where
W: DiscreteWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T> + Clone,
T: DiscreteContents,
{
fn split_node(&mut self, id: &K, at: usize, new_id: K) -> bool {
if self.weave.split_node(id, at, new_id) {
self.actions.push_back(WeaveAction::SplitNode {
id: *id,
at,
new_id,
});
true
} else {
false
}
}
fn merge_with_parent(&mut self, id: &K) -> Option<K> {
match self.weave.merge_with_parent(id) {
Some(new_id) => {
self.actions
.push_back(WeaveAction::MergeNodeWithParent(*id));
Some(new_id)
}
None => None,
}
}
}
impl<W, K, N, T, M> DeduplicatableWeave<K, N, T> for LoggedWeave<W, K, N, T, M>
where
W: DeduplicatableWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T> + Clone,
T: DeduplicatableContents,
{
#[inline]
fn find_duplicates(&self, id: &K) -> impl Iterator<Item = K> {
self.weave.find_duplicates(id)
}
}
impl<W, K, N, T> Weave<K, N, T> for CountedWeave<W, K, N, T>
where
W: Weave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
type Nodes = W::Nodes;
type Roots = W::Roots;
#[inline]
fn len(&self) -> usize {
self.weave.len()
}
#[inline]
fn is_empty(&self) -> bool {
self.weave.is_empty()
}
#[inline]
fn nodes(&self) -> &Self::Nodes {
self.weave.nodes()
}
#[inline]
fn roots(&self) -> &Self::Roots {
self.weave.roots()
}
#[inline]
fn contains(&self, id: &K) -> bool {
self.weave.contains(id)
}
#[inline]
fn contains_active(&self, id: &K) -> bool {
self.weave.contains_active(id)
}
#[inline]
fn get_node(&self, id: &K) -> Option<&N> {
self.weave.get_node(id)
}
#[inline]
fn get_ordered_node_identifiers(&mut self, output: &mut Vec<K>) {
self.weave.get_ordered_node_identifiers(output);
}
#[inline]
fn get_ordered_node_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
self.weave.get_ordered_node_identifiers_from(id, output);
}
#[inline]
fn get_active_path(&mut self, output: &mut Vec<K>) {
self.weave.get_active_path(output);
}
#[inline]
fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
self.weave.get_path_from(id, output);
}
#[inline]
fn add_node(&mut self, node: N) -> bool {
if self.weave.add_node(node) {
self.count.add_node = self.count.add_node.saturating_add(1);
true
} else {
false
}
}
#[inline]
fn set_node_active_status(&mut self, id: &K, value: bool) -> bool {
if self.weave.set_node_active_status(id, value) {
self.count.set_node_active_status = self.count.set_node_active_status.saturating_add(1);
true
} else {
false
}
}
#[inline]
fn remove_node(&mut self, id: &K) -> Option<N> {
if let Some(removed) = self.weave.remove_node(id) {
self.count.remove_node = self.count.remove_node.saturating_add(1);
Some(removed)
} else {
None
}
}
#[inline]
fn remove_node_tracked(&mut self, id: &K, on_removal: impl FnMut(N)) -> bool {
if self.weave.remove_node_tracked(id, on_removal) {
self.count.remove_node = self.count.remove_node.saturating_add(1);
true
} else {
false
}
}
#[inline]
fn remove_all_nodes(&mut self) {
self.weave.remove_all_nodes();
self.count.remove_all_nodes = self.count.remove_all_nodes.saturating_add(1);
}
}
impl<W, K, N, T, M> MetadataWeave<K, N, T, M> for CountedWeave<W, K, N, T>
where
W: MetadataWeave<K, N, T, M>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
#[inline]
fn metadata(&self) -> &M {
self.weave.metadata()
}
#[inline]
fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
self.weave.metadata_mut(|metadata| {
let output = callback(metadata);
self.count.metadata_mut = self.count.metadata_mut.saturating_add(1);
output
})
}
}
impl<W, K, N, T> BookmarkableWeave<K, N, T> for CountedWeave<W, K, N, T>
where
W: BookmarkableWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
type Bookmarks = W::Bookmarks;
#[inline]
fn bookmarks(&self) -> &Self::Bookmarks {
self.weave.bookmarks()
}
#[inline]
fn contains_bookmark(&self, id: &K) -> bool {
self.weave.contains_bookmark(id)
}
#[inline]
fn set_node_bookmarked_status(&mut self, id: &K, value: bool) -> bool {
if self.weave.set_node_bookmarked_status(id, value) {
self.count.set_node_bookmarked_status =
self.count.set_node_bookmarked_status.saturating_add(1);
true
} else {
false
}
}
}
impl<W, K, N, T> SortableWeave<K, N, T> for CountedWeave<W, K, N, T>
where
W: SortableWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
#[inline]
fn get_ordered_node_identifiers_mirrored(&mut self, output: &mut Vec<K>) {
self.weave.get_ordered_node_identifiers_mirrored(output);
}
#[inline]
fn get_ordered_node_identifiers_mirrored_from(&mut self, id: &K, output: &mut Vec<K>) {
self.weave
.get_ordered_node_identifiers_mirrored_from(id, output);
}
#[inline]
fn sort_node_children_by(&mut self, id: &K, cmp: impl FnMut(&N, &N) -> Ordering) -> bool {
if self.weave.sort_node_children_by(id, cmp) {
self.count.sort_node_children = self.count.sort_node_children.saturating_add(1);
true
} else {
false
}
}
#[inline]
fn sort_node_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
if self.weave.sort_node_children_by_id(id, cmp) {
self.count.sort_node_children = self.count.sort_node_children.saturating_add(1);
true
} else {
false
}
}
#[inline]
fn sort_roots_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
self.weave.sort_roots_by(cmp);
self.count.sort_roots = self.count.sort_roots.saturating_add(1);
}
#[inline]
fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
self.weave.sort_roots_by_id(cmp);
self.count.sort_roots = self.count.sort_roots.saturating_add(1);
}
}
impl<W, K, N, T> SortableBookmarkableWeave<K, N, T> for CountedWeave<W, K, N, T>
where
W: SortableBookmarkableWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
#[inline]
fn sort_bookmarks_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering) {
self.weave.sort_bookmarks_by(cmp);
self.count.sort_bookmarks = self.count.sort_bookmarks.saturating_add(1);
}
#[inline]
fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
self.weave.sort_bookmarks_by_id(cmp);
self.count.sort_bookmarks = self.count.sort_bookmarks.saturating_add(1);
}
}
impl<W, K, N, T> ActiveSingularWeave<K, N, T> for CountedWeave<W, K, N, T>
where
W: ActiveSingularWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
#[inline]
fn active(&self) -> Option<K> {
self.weave.active()
}
}
impl<W, K, N, T> ActivePathWeave<K, N, T> for CountedWeave<W, K, N, T>
where
W: ActivePathWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
{
type Active = W::Active;
#[inline]
fn active(&self) -> &Self::Active {
self.weave.active()
}
#[inline]
fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
self.weave.set_active_path(active);
self.count.set_active_path = self.count.set_active_path.saturating_add(1);
}
}
impl<W, K, N, T> IndependentWeave<K, N, T> for CountedWeave<W, K, N, T>
where
W: IndependentWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
T: IndependentContents,
{
#[inline]
fn move_node(&mut self, id: &K, new_parents: &[K]) -> bool {
if self.weave.move_node(id, new_parents) {
self.count.move_node = self.count.move_node.saturating_add(1);
true
} else {
false
}
}
}
impl<W, K, N, T> SemiIndependentWeave<K, N, T> for CountedWeave<W, K, N, T>
where
W: SemiIndependentWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
T: IndependentContents,
{
#[inline]
fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
self.weave.get_contents_mut(id, |contents| {
let output = callback(contents);
self.count.get_contents_mut = self.count.get_contents_mut.saturating_add(1);
output
})
}
}
impl<W, K, N, T> DiscreteWeave<K, N, T> for CountedWeave<W, K, N, T>
where
W: DiscreteWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
T: DiscreteContents,
{
#[inline]
fn split_node(&mut self, id: &K, at: usize, new_id: K) -> bool {
if self.weave.split_node(id, at, new_id) {
self.count.split_node = self.count.split_node.saturating_add(1);
true
} else {
false
}
}
#[inline]
fn merge_with_parent(&mut self, id: &K) -> Option<K> {
match self.weave.merge_with_parent(id) {
Some(new_id) => {
self.count.merge_with_parent = self.count.merge_with_parent.saturating_add(1);
Some(new_id)
}
None => None,
}
}
}
impl<W, K, N, T> DeduplicatableWeave<K, N, T> for CountedWeave<W, K, N, T>
where
W: DeduplicatableWeave<K, N, T>,
K: Hash + Copy + Eq + Ord,
N: Node<K, T>,
T: DeduplicatableContents,
{
#[inline]
fn find_duplicates(&self, id: &K) -> impl Iterator<Item = K> {
self.weave.find_duplicates(id)
}
}