1
0
Fork 0

Compare commits

...

3 Commits

32 changed files with 3841 additions and 154 deletions

1
Cargo.lock generated
View File

@ -311,7 +311,6 @@ dependencies = [
[[package]]
name = "slab_tree"
version = "0.3.2"
source = "git+https://github.com/jsinger67/slab-tree.git?branch=set_root_fix#75a8dfa3b1f96f76ebe09e2e988deeffe6db54b6"
dependencies = [
"snowflake",
]

View File

@ -21,5 +21,4 @@ slab_tree = "0.3.2"
users = "0.11"
[patch.crates-io.slab_tree]
git = "https://github.com/jsinger67/slab-tree.git"
branch = "set_root_fix"
path = "./lib/slab-tree"

View File

@ -42,3 +42,9 @@ Run `docker build --output out .` to build a release binary into the `out/` fold
This project exists 1) because I couldn't find any tree-based file manager I liked and 2) because I wanted to have fun writing Rust, and I don't really want to spend time reading and reviewing pull requests.
For now, issues are closed, and I'm not accepting any major contributions — especially ones related to the roadmap. If you have a small idea, issue, or pull request, feel free to start a [discussion](https://github.com/chylex/Bark-Browser/discussions).
# Dependencies
For a full list of dependencies, see [Cargo.toml](Cargo.toml).
This repository includes the sources of [slab-tree](https://github.com/iwburns/slab-tree) (by [iwburns](https://github.com/iwburns)) with a [bug fix for `set_root`](https://github.com/iwburns/slab-tree/pull/28) (by [jsinger67](https://github.com/jsinger67)) and additional modifications from me.

2
lib/slab-tree/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/.idea/
/target/

16
lib/slab-tree/Cargo.lock generated Normal file
View File

@ -0,0 +1,16 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "slab_tree"
version = "0.3.2"
dependencies = [
"snowflake",
]
[[package]]
name = "snowflake"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27207bb65232eda1f588cf46db2fee75c0808d557f6b3cf19a75f5d6d7c94df1"

15
lib/slab-tree/Cargo.toml Normal file
View File

@ -0,0 +1,15 @@
[package]
name = "slab_tree"
version = "0.3.2"
authors = ["Ian <iwburns8@gmail.com>"]
description = "A vec-backed tree structure with tree-specific generational indexes."
documentation = "https://docs.rs/slab_tree"
repository = "https://github.com/iwburns/slab-tree"
readme = "README.md"
keywords = ["tree", "slab", "slab-tree"]
categories = ["data-structures"]
license = "MIT"
edition = "2018"
[dependencies]
snowflake = "1.3.0"

69
lib/slab-tree/README.md Normal file
View File

@ -0,0 +1,69 @@
# slab_tree
[![Build Status](https://travis-ci.org/iwburns/slab-tree.svg?branch=master)](https://travis-ci.org/iwburns/slab-tree)
[![](https://tokei.rs/b1/github/iwburns/slab-tree)](https://github.com/iwburns/slab-tree)
A vec-backed tree structure with tree-specific generational indexes.
## Overview
This library provides a `Tree<T>` struct which allows the creation and manipulation of in-memory trees.
The tree itself is backed by a vector and the tree's node relationships are managed by tree-specific
generational indexes called `NodeId`s (more below). In addition, "views" of tree nodes are handed out
which are either immutable (`NodeRef`) or mutable (`NodeMut`) instead of handing out references
directly. Most tree mutations are achieved by modifying `NodeMut`s instead of talking to the tree
itself.
`Tree`s in this crate are "just" trees. They do not allow cycles, and they do not allow arbitrary
graph structures to be created. Each node in the tree can have an arbitrary number of children, and
there is no weight associated with edges between the nodes in the tree.
**Please Note:** this crate does not support comparison-based data insertion. In other words, this is
not a binary search tree (or any other kind of search tree) crate. It is purely a crate for storing
data in a hierarchical manner. The caller must know the structure that they wish to build and then use
this crate to do so; this library will not make those structural decisions for you.
## Safety
This crate uses `#![forbid(unsafe_code)]` to prevent any and all `unsafe` code usage.
## Example Usage
```rust
use slab_tree::*;
fn main() {
// "hello"
// / \
// "world" "trees"
// |
// "are"
// |
// "cool"
let mut tree = TreeBuilder::new().with_root("hello").build();
let root_id = tree.root_id().expect("root doesn't exist?");
let mut hello = tree.get_mut(root_id).unwrap();
hello.append("world");
hello
.append("trees")
.append("are")
.append("cool");
}
```
## `NodeId`s
`NodeId`s are tree-specific generational indexes. Using generational indexes means that we can re-use
space inside the tree (after nodes have been removed) without also having to re-use the same tree
indexes which could potentially cause confusion and bugs. The "tree-specific" part means that indexes
from one tree cannot be confused for indexes for another tree. This is because each index contains a
process-unique-id which is shared by the tree from which that index originated.
## Project Goals
* Allow caller control of as many allocations as possible (through pre-allocation)
* Fast and Ergonomic Node insertion and removal
* Arbitrary Tree structure creation and manipulation
## Non-Goals
* Arbitrary _Graph_ structure creation and manipulation
* Comparison-based node insertion of any kind

View File

@ -0,0 +1,22 @@
///
/// Describes all the possible ways to remove a Node from a Tree.
///
pub enum RemoveBehavior {
///
/// All children of the removed Node will be dropped from the Tree. All children (and all
/// Nodes in each of their sub-trees) will no longer exist in the Tree after this operation.
///
/// This is slower than `OrphanChildren` but frees up space inside the Tree.
///
DropChildren,
///
/// All children of the removed Node will be left in the Tree (still accessible via NodeIds).
/// However, each child (and their sub-trees) will no longer be connected to the rest of the
/// Nodes in the Tree.
///
/// Orphaned nodes will live in the Tree until they are manually removed or until the Tree is
/// Dropped. This is faster than `DropChildren` but doesn't free up any space inside the Tree.
///
OrphanChildren,
}

View File

@ -0,0 +1,136 @@
use crate::node::Node;
use crate::slab;
use crate::NodeId;
use snowflake::ProcessUniqueId;
///
/// A wrapper around a Slab containing Node<T> values.
///
/// Groups a collection of Node<T>s with a process unique id.
///
#[derive(Debug, PartialEq)]
pub(crate) struct CoreTree<T> {
id: ProcessUniqueId,
slab: slab::Slab<Node<T>>,
}
impl<T> CoreTree<T> {
pub(crate) fn new(capacity: usize) -> CoreTree<T> {
CoreTree {
id: ProcessUniqueId::new(),
slab: slab::Slab::new(capacity),
}
}
pub(crate) fn capacity(&self) -> usize {
self.slab.capacity()
}
pub(crate) fn insert(&mut self, data: T) -> NodeId {
let key = self.slab.insert(Node::new(data));
self.new_node_id(key)
}
pub(crate) fn remove(&mut self, node_id: NodeId) -> Option<T> {
self.filter_by_tree_id(node_id)
.and_then(|id| self.slab.remove(id.index))
.map(|node| node.data)
}
pub(crate) fn get(&self, node_id: NodeId) -> Option<&Node<T>> {
self.filter_by_tree_id(node_id)
.and_then(|id| self.slab.get(id.index))
}
pub(crate) fn get_mut(&mut self, node_id: NodeId) -> Option<&mut Node<T>> {
self.filter_by_tree_id(node_id)
.and_then(move |id| self.slab.get_mut(id.index))
}
fn new_node_id(&self, index: slab::Index) -> NodeId {
NodeId {
tree_id: self.id,
index,
}
}
fn filter_by_tree_id(&self, node_id: NodeId) -> Option<NodeId> {
if node_id.tree_id != self.id {
return None;
}
Some(node_id)
}
}
#[cfg_attr(tarpaulin, skip)]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn capacity() {
let capacity = 5;
let tree = CoreTree::<i32>::new(capacity);
assert_eq!(tree.capacity(), capacity);
}
#[test]
fn insert() {
let mut tree = CoreTree::new(0);
let id = tree.insert(1);
let id2 = tree.insert(3);
assert_eq!(tree.get(id).unwrap().data, 1);
assert_eq!(tree.get(id2).unwrap().data, 3);
}
#[test]
fn remove() {
let mut tree = CoreTree::new(0);
let id = tree.insert(1);
assert_eq!(tree.get(id).unwrap().data, 1);
let one = tree.remove(id);
assert!(one.is_some());
let one = one.unwrap();
assert_eq!(one, 1);
}
#[test]
fn get() {
let mut tree = CoreTree::new(0);
let id = tree.insert(1);
let id2 = tree.insert(3);
assert_eq!(tree.get(id).unwrap().data, 1);
assert_eq!(tree.get(id2).unwrap().data, 3);
}
#[test]
fn get_mut() {
let mut tree = CoreTree::new(0);
let id = tree.insert(1);
let id2 = tree.insert(3);
assert_eq!(tree.get_mut(id).unwrap().data, 1);
assert_eq!(tree.get_mut(id2).unwrap().data, 3);
}
#[test]
fn get_with_bad_id() {
let mut tree = CoreTree::new(0);
let tree2: CoreTree<i32> = CoreTree::new(0);
let mut id = tree.insert(1);
id.tree_id = tree2.id; // oops, wrong tree id.
let result = tree.get(id);
assert!(result.is_none());
}
}

223
lib/slab-tree/src/iter.rs Normal file
View File

@ -0,0 +1,223 @@
use crate::node::*;
use crate::tree::Tree;
use crate::NodeId;
// todo: document this
pub struct Ancestors<'a, T> {
node_id: Option<NodeId>,
tree: &'a Tree<T>,
}
impl<'a, T> Ancestors<'a, T> {
pub(crate) fn new(node_id: Option<NodeId>, tree: &'a Tree<T>) -> Ancestors<T> {
Ancestors { node_id, tree }
}
}
impl<'a, T> Iterator for Ancestors<'a, T> {
type Item = NodeRef<'a, T>;
fn next(&mut self) -> Option<NodeRef<'a, T>> {
self.node_id
.take()
.and_then(|node_id| self.tree.get_node_relatives(node_id).parent)
.map(|id| {
self.node_id = Some(id);
NodeRef::new(id, self.tree)
})
}
}
// possibly re-name this, not sure how I feel about it
pub struct NextSiblings<'a, T> {
node_id: Option<NodeId>,
tree: &'a Tree<T>,
}
impl<'a, T> NextSiblings<'a, T> {
pub(crate) fn new(node_id: Option<NodeId>, tree: &'a Tree<T>) -> NextSiblings<T> {
NextSiblings { node_id, tree }
}
}
impl<'a, T> Iterator for NextSiblings<'a, T> {
type Item = NodeRef<'a, T>;
fn next(&mut self) -> Option<NodeRef<'a, T>> {
self.node_id.take().map(|node_id| {
self.node_id = self.tree.get_node_relatives(node_id).next_sibling;
NodeRef::new(node_id, self.tree)
})
}
}
/// Depth-first pre-order iterator
pub struct PreOrder<'a, T> {
start: Option<NodeRef<'a, T>>,
children: Vec<NextSiblings<'a, T>>,
tree: &'a Tree<T>,
}
impl<'a, T> PreOrder<'a, T> {
pub(crate) fn new(node: &NodeRef<'a, T>, tree: &'a Tree<T>) -> PreOrder<'a, T> {
let children = vec![];
let start = tree.get(node.node_id());
PreOrder {
start,
children,
tree,
}
}
}
impl<'a, T> Iterator for PreOrder<'a, T> {
type Item = NodeRef<'a, T>;
fn next(&mut self) -> Option<NodeRef<'a, T>> {
if let Some(node) = self.start.take() {
let first_child_id = node.first_child().map(|child_ref| child_ref.node_id());
self.children
.push(NextSiblings::new(first_child_id, self.tree));
Some(node)
} else {
while !self.children.is_empty() {
if let Some(node_ref) = self.children.last_mut().and_then(Iterator::next) {
if let Some(first_child) = node_ref.first_child() {
self.children
.push(NextSiblings::new(Some(first_child.node_id()), self.tree));
}
return Some(node_ref);
}
self.children.pop();
}
None
}
}
}
/// Depth-first post-order iterator
pub struct PostOrder<'a, T> {
nodes: Vec<(NodeRef<'a, T>, NextSiblings<'a, T>)>,
tree: &'a Tree<T>,
}
impl<'a, T> PostOrder<'a, T> {
pub(crate) fn new(node: &NodeRef<'a, T>, tree: &'a Tree<T>) -> PostOrder<'a, T> {
let node = tree
.get(node.node_id())
.expect("getting node of node ref id");
let first_child_id = node.first_child().map(|first_child| first_child.node_id());
let nodes = vec![(node, NextSiblings::new(first_child_id, tree))];
PostOrder { nodes, tree }
}
}
impl<'a, T> Iterator for PostOrder<'a, T> {
type Item = NodeRef<'a, T>;
fn next(&mut self) -> Option<NodeRef<'a, T>> {
if let Some((node, mut children)) = self.nodes.pop() {
if let Some(next) = children.next() {
self.nodes.push((node, children));
let mut node_id = next.node_id();
loop {
let node = self.tree.get(node_id).expect("getting node of node ref id");
if let Some(first_child) = node.first_child() {
node_id = first_child.node_id();
let mut children = NextSiblings::new(Some(node_id), self.tree);
assert!(children.next().is_some(), "skipping first child");
self.nodes.push((node, children));
} else {
break Some(node);
}
}
} else {
Some(node)
}
} else {
None
}
}
}
/// Depth-first level-order iterator
pub struct LevelOrder<'a, T> {
start: NodeRef<'a, T>,
levels: Vec<(NodeId, NextSiblings<'a, T>)>,
tree: &'a Tree<T>,
}
impl<'a, T> LevelOrder<'a, T> {
pub(crate) fn new(node: &NodeRef<'a, T>, tree: &'a Tree<T>) -> LevelOrder<'a, T> {
let start = tree
.get(node.node_id())
.expect("getting node of node ref id");
let levels = Vec::new();
LevelOrder {
start,
levels,
tree,
}
}
}
impl<'a, T> Iterator for LevelOrder<'a, T> {
type Item = NodeRef<'a, T>;
fn next(&mut self) -> Option<NodeRef<'a, T>> {
if self.levels.is_empty() {
let first_child_id = self.start.first_child().map(|child| child.node_id());
self.levels.push((
self.start.node_id(),
NextSiblings::new(first_child_id, self.tree),
));
let node = self
.tree
.get(self.start.node_id())
.expect("getting node of existing node ref id");
Some(node)
} else {
let mut on_level = self.levels.len();
let next_level = on_level + 1;
let mut level = on_level;
while level > 0 {
if let Some(node) = self.levels.last_mut().expect("non-empty levels").1.next() {
if level >= on_level {
return Some(node);
} else {
let first_child_id = node.first_child().map(|child| child.node_id());
self.levels
.push((node.node_id(), NextSiblings::new(first_child_id, self.tree)));
level += 1;
}
} else {
let (node_id, _) = self.levels.pop().expect("on level > 0");
if let Some(next) = self.levels.last_mut().and_then(|level| level.1.next()) {
let first_child_id = next.first_child().map(|child| child.node_id());
self.levels
.push((next.node_id(), NextSiblings::new(first_child_id, self.tree)));
} else if level == 1 {
if on_level < next_level {
on_level += 1;
let node = self
.tree
.get(node_id)
.expect("getting node of existing node ref id");
let first_child_id = node.first_child().map(|child| child.node_id());
self.levels.push((
node.node_id(),
NextSiblings::new(first_child_id, self.tree),
));
} else {
break;
}
} else {
level -= 1;
}
}
}
None
}
}
}

96
lib/slab-tree/src/lib.rs Normal file
View File

@ -0,0 +1,96 @@
#![forbid(unsafe_code)]
//!
//! # slab_tree
//!
//! [![Build Status](https://travis-ci.org/iwburns/slab-tree.svg?branch=master)](https://travis-ci.org/iwburns/slab-tree)
//! [![](https://tokei.rs/b1/github/iwburns/slab-tree)](https://github.com/iwburns/slab-tree)
//!
//! A vec-backed tree structure with tree-specific generational indexes.
//!
//! ## Overview
//!
//! This library provides a `Tree<T>` struct which allows the creation and manipulation of in-memory trees.
//! The tree itself is backed by a vector and the tree's node relationships are managed by tree-specific
//! generational indexes called `NodeId`s (more below). In addition, "views" of tree nodes are handed out
//! which are either immutable (`NodeRef`) or mutable (`NodeMut`) instead of handing out references
//! directly. Most tree mutations are achieved by modifying `NodeMut`s instead of talking to the tree
//! itself.
//!
//! `Tree`s in this crate are "just" trees. They do not allow cycles, and they do not allow arbitrary
//! graph structures to be created. Each node in the tree can have an arbitrary number of children, and
//! there is no weight associated with edges between the nodes in the tree.
//!
//! **Please Note:** this crate does not support comparison-based data insertion. In other words, this is
//! not a binary search tree (or any other kind of search tree) crate. It is purely a crate for storing
//! data in a hierarchical manner. The caller must know the structure that they wish to build and then use
//! this crate to do so; this library will not make those structural decisions for you.
//!
//! ## Safety
//! This crate uses `#![forbid(unsafe_code)]` to prevent any and all `unsafe` code usage.
//!
//! ## Example Usage
//! ```
//! use slab_tree::*;
//!
//! // "hello"
//! // / \
//! // "world" "trees"
//! // |
//! // "are"
//! // |
//! // "cool"
//!
//! let mut tree = TreeBuilder::new().with_root("hello").build();
//! let root_id = tree.root_id().expect("root doesn't exist?");
//! let mut hello = tree.get_mut(root_id).unwrap();
//!
//! hello.append("world");
//! hello
//! .append("trees")
//! .append("are")
//! .append("cool");
//! ```
//!
//! ## `NodeId`s
//! `NodeId`s are tree-specific generational indexes. Using generational indexes means that we can re-use
//! space inside the tree (after nodes have been removed) without also having to re-use the same tree
//! indexes which could potentially cause confusion and bugs. The "tree-specific" part means that indexes
//! from one tree cannot be confused for indexes for another tree. This is because each index contains a
//! process-unique-id which is shared by the tree from which that index originated.
//!
//! ## Project Goals
//! * Allow caller control of as many allocations as possible (through pre-allocation)
//! * Fast and Ergonomic Node insertion and removal
//! * Arbitrary Tree structure creation and manipulation
//!
//! ## Non-Goals
//! * Arbitrary _Graph_ structure creation and manipulation
//! * Comparison-based node insertion of any kind
//!
pub mod behaviors;
mod core_tree;
pub mod iter;
pub mod node;
mod slab;
pub mod tree;
pub use crate::behaviors::RemoveBehavior;
pub use crate::iter::Ancestors;
pub use crate::iter::NextSiblings;
pub use crate::node::NodeMut;
pub use crate::node::NodeRef;
pub use crate::tree::Tree;
pub use crate::tree::TreeBuilder;
use snowflake::ProcessUniqueId;
///
/// An identifier used to differentiate between Nodes and tie
/// them to a specific tree.
///
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub struct NodeId {
tree_id: ProcessUniqueId,
index: slab::Index,
}

39
lib/slab-tree/src/node.rs Normal file
View File

@ -0,0 +1,39 @@
mod bark_extensions;
mod node_mut;
mod node_ref;
pub use self::bark_extensions::*;
pub use self::node_mut::NodeMut;
pub use self::node_ref::NodeRef;
use crate::NodeId;
#[derive(Copy, Clone, Debug, PartialEq)]
pub(crate) struct Relatives {
pub(crate) parent: Option<NodeId>,
pub(crate) prev_sibling: Option<NodeId>,
pub(crate) next_sibling: Option<NodeId>,
pub(crate) first_child: Option<NodeId>,
pub(crate) last_child: Option<NodeId>,
}
#[derive(Debug, PartialEq)]
pub(crate) struct Node<T> {
pub(crate) data: T,
pub(crate) relatives: Relatives,
}
impl<T> Node<T> {
pub(crate) fn new(data: T) -> Node<T> {
Node {
data,
relatives: Relatives {
parent: None,
prev_sibling: None,
next_sibling: None,
first_child: None,
last_child: None,
},
}
}
}

View File

@ -0,0 +1,79 @@
use crate::NodeId;
use crate::NodeMut;
use crate::NodeRef;
impl<'a, T> NodeRef<'a, T> {
pub fn parent_id(&self) -> Option<NodeId> {
self.parent().map(|node| node.node_id())
}
pub fn first_child_id(&self) -> Option<NodeId> {
self.first_child().map(|node| node.node_id())
}
pub fn last_child_id(&self) -> Option<NodeId> {
self.last_child().map(|node| node.node_id())
}
pub fn prev_sibling_id(&self) -> Option<NodeId> {
self.prev_sibling().map(|node| node.node_id())
}
pub fn next_sibling_id(&self) -> Option<NodeId> {
self.next_sibling().map(|node| node.node_id())
}
pub fn last_descendant_or_self(&self) -> NodeRef<'a, T> {
let mut node = NodeRef::new(self.node_id(), self.tree);
while let Some(id) = node.get_self_as_node().relatives.last_child {
node = NodeRef::new(id, self.tree);
}
node
}
pub fn above(&self) -> Option<NodeRef<T>> {
if let Some(prev_sibling) = self.prev_sibling() {
Some(prev_sibling.last_descendant_or_self())
} else {
self.parent()
}
}
pub fn above_id(&self) -> Option<NodeId> {
self.above().map(|node| node.node_id())
}
pub fn below(&self) -> Option<NodeRef<T>> {
self.first_child()
.or_else(|| self.next_sibling())
.or_else(|| self.ancestors().find_map(|ancestor| ancestor.next_sibling_id()).map(|id| NodeRef::new(id, self.tree)))
}
pub fn below_id(&self) -> Option<NodeId> {
self.below().map(|node| node.node_id())
}
}
impl<'a, T> NodeMut<'a, T> {
pub fn parent_id(&mut self) -> Option<NodeId> {
self.parent().map(|node| node.node_id())
}
pub fn first_child_id(&mut self) -> Option<NodeId> {
self.first_child().map(|node| node.node_id())
}
pub fn last_child_id(&mut self) -> Option<NodeId> {
self.last_child().map(|node| node.node_id())
}
pub fn prev_sibling_id(&mut self) -> Option<NodeId> {
self.prev_sibling().map(|node| node.node_id())
}
pub fn next_sibling_id(&mut self) -> Option<NodeId> {
self.next_sibling().map(|node| node.node_id())
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,381 @@
use crate::iter::Ancestors;
use crate::iter::LevelOrder;
use crate::iter::NextSiblings;
use crate::iter::PostOrder;
use crate::iter::PreOrder;
use crate::node::Node;
use crate::tree::Tree;
use crate::NodeId;
///
/// An immutable reference to a given `Node`'s data and its relatives.
///
pub struct NodeRef<'a, T> {
pub(super) node_id: NodeId,
pub(super) tree: &'a Tree<T>,
}
impl<'a, T> NodeRef<'a, T> {
pub(crate) fn new(node_id: NodeId, tree: &'a Tree<T>) -> NodeRef<T> {
NodeRef { node_id, tree }
}
///
/// Returns the `NodeId` that identifies this `Node` in the tree.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(1).build();
/// let root_id = tree.root_id().expect("root doesn't exist?");
/// let root = tree.root_mut().expect("root doesn't exist?");
///
/// let root_id_again = root.as_ref().node_id();
///
/// assert_eq!(root_id_again, root_id);
/// ```
///
pub fn node_id(&self) -> NodeId {
self.node_id
}
///
/// Returns a reference to the data contained by the given `Node`.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(1).build();
///
/// let root = tree.root().expect("root doesn't exist?");
///
/// assert_eq!(root.data(), &1);
/// ```
///
pub fn data(&self) -> &'a T {
if let Some(node) = self.tree.get_node(self.node_id) {
&node.data
} else {
unreachable!()
}
}
///
/// Returns a `NodeRef` pointing to this `Node`'s parent. Returns a `Some`-value containing
/// the `NodeRef` if this `Node` has a parent; otherwise returns a `None`.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(1).build();
///
/// let root = tree.root().expect("root doesn't exist?");
///
/// assert!(root.parent().is_none());
/// ```
///
pub fn parent(&self) -> Option<NodeRef<T>> {
self.get_self_as_node()
.relatives
.parent
.map(|id| NodeRef::new(id, self.tree))
}
///
/// Returns a `NodeRef` pointing to this `Node`'s previous sibling. Returns a `Some`-value
/// containing the `NodeRef` if this `Node` has a previous sibling; otherwise returns a `None`.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(1).build();
///
/// let root = tree.root().expect("root doesn't exist?");
///
/// assert!(root.prev_sibling().is_none());
/// ```
///
pub fn prev_sibling(&self) -> Option<NodeRef<T>> {
self.get_self_as_node()
.relatives
.prev_sibling
.map(|id| NodeRef::new(id, self.tree))
}
///
/// Returns a `NodeRef` pointing to this `Node`'s next sibling. Returns a `Some`-value
/// containing the `NodeRef` if this `Node` has a next sibling; otherwise returns a `None`.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(1).build();
///
/// let root = tree.root().expect("root doesn't exist?");
///
/// assert!(root.next_sibling().is_none());
/// ```
///
pub fn next_sibling(&self) -> Option<NodeRef<T>> {
self.get_self_as_node()
.relatives
.next_sibling
.map(|id| NodeRef::new(id, self.tree))
}
///
/// Returns a `NodeRef` pointing to this `Node`'s first child. Returns a `Some`-value
/// containing the `NodeRef` if this `Node` has a first child; otherwise returns a `None`.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(1).build();
///
/// let root = tree.root().expect("root doesn't exist?");
///
/// assert!(root.first_child().is_none());
/// ```
///
pub fn first_child(&self) -> Option<NodeRef<T>> {
self.get_self_as_node()
.relatives
.first_child
.map(|id| NodeRef::new(id, self.tree))
}
///
/// Returns a `NodeRef` pointing to this `Node`'s last child. Returns a `Some`-value
/// containing the `NodeRef` if this `Node` has a last child; otherwise returns a `None`.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(1).build();
///
/// let root = tree.root().expect("root doesn't exist?");
///
/// assert!(root.last_child().is_none());
/// ```
///
pub fn last_child(&self) -> Option<NodeRef<T>> {
self.get_self_as_node()
.relatives
.last_child
.map(|id| NodeRef::new(id, self.tree))
}
///
/// Returns a `Iterator` over the given `Node`'s ancestors. Each call to `Iterator::next()`
/// returns a `NodeRef` pointing to the current `Node`'s parent.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(1).build();
///
/// let leaf_id = tree.root_mut().expect("root doesn't exist?")
/// .append(2)
/// .append(3)
/// .append(4)
/// .node_id();
///
/// let leaf = tree.get(leaf_id).unwrap();
///
/// let values = [3, 2, 1];
/// for (i, ancestor) in leaf.ancestors().enumerate() {
/// assert_eq!(ancestor.data(), &values[i]);
/// }
/// ```
///
pub fn ancestors(&self) -> Ancestors<'a, T> {
Ancestors::new(Some(self.node_id), self.tree)
}
///
/// Returns a `Iterator` over the given `Node`'s children. Each call to `Iterator::next()`
/// returns a `NodeRef` pointing to the next child of the given `Node`.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(1).build();
///
/// let mut root = tree.root_mut().expect("root doesn't exist?");
/// root.append(2);
/// root.append(3);
/// root.append(4);
///
/// let root = root.as_ref();
///
/// let values = [2, 3, 4];
/// for (i, child) in root.children().enumerate() {
/// assert_eq!(child.data(), &values[i]);
/// }
/// ```
///
pub fn children(&self) -> NextSiblings<'a, T> {
let first_child_id = self.tree.get_node_relatives(self.node_id).first_child;
NextSiblings::new(first_child_id, self.tree)
}
/// Depth-first pre-order traversal.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(0i64).build();
/// let root_id = tree.root().unwrap().node_id();
/// let one_id = tree.get_mut(root_id).unwrap().append(1).node_id();
/// tree.get_mut(one_id).unwrap().append(2);
/// tree.get_mut(one_id).unwrap().append(3);
/// tree.get_mut(root_id).unwrap().append(4);
/// let pre_order = tree.root().unwrap().traverse_pre_order()
/// .map(|node_ref| node_ref.data().clone()).collect::<Vec<i64>>();
/// assert_eq!(pre_order, vec![0, 1, 2, 3, 4]);
/// ```
pub fn traverse_pre_order(&self) -> PreOrder<'a, T> {
PreOrder::new(self, self.tree)
}
/// Depth-first post-order traversal.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(0i64).build();
/// let root_id = tree.root().unwrap().node_id();
/// let one_id = tree.get_mut(root_id).unwrap().append(1).node_id();
/// tree.get_mut(one_id).unwrap().append(2);
/// tree.get_mut(one_id).unwrap().append(3);
/// tree.get_mut(root_id).unwrap().append(4);
/// let post_order = tree.root().unwrap().traverse_post_order()
/// .map(|node_ref| node_ref.data().clone()).collect::<Vec<i64>>();
/// assert_eq!(post_order, vec![2, 3, 1, 4, 0]);
/// ```
pub fn traverse_post_order(&self) -> PostOrder<'a, T> {
PostOrder::new(self, self.tree)
}
/// Depth-first level-order traversal.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(0i64).build();
/// let root_id = tree.root().unwrap().node_id();
/// let one_id = tree.get_mut(root_id).unwrap().append(1).node_id();
/// tree.get_mut(one_id).unwrap().append(2);
/// tree.get_mut(one_id).unwrap().append(3);
/// tree.get_mut(root_id).unwrap().append(4);
/// let level_order = tree.root().unwrap().traverse_level_order()
/// .map(|node_ref| node_ref.data().clone()).collect::<Vec<i64>>();
/// assert_eq!(level_order, vec![0, 1, 4, 2, 3]);
/// ```
pub fn traverse_level_order(&self) -> LevelOrder<'a, T> {
LevelOrder::new(self, self.tree)
}
pub(super) fn get_self_as_node(&self) -> &Node<T> {
if let Some(node) = self.tree.get_node(self.node_id) {
&node
} else {
unreachable!()
}
}
}
#[cfg_attr(tarpaulin, skip)]
#[cfg(test)]
mod node_ref_tests {
use crate::tree::Tree;
#[test]
fn data() {
let mut tree = Tree::new();
tree.set_root(1);
let root_id = tree.root_id().expect("root doesn't exist?");
let root_ref = tree.get(root_id).unwrap();
assert_eq!(root_ref.data(), &1);
}
#[test]
fn parent() {
let mut tree = Tree::new();
tree.set_root(1);
let root_id = tree.root_id().expect("root doesn't exist?");
let root_ref = tree.get(root_id).unwrap();
assert!(root_ref.parent().is_none());
}
#[test]
fn prev_sibling() {
let mut tree = Tree::new();
tree.set_root(1);
let root_id = tree.root_id().expect("root doesn't exist?");
let root_ref = tree.get(root_id).unwrap();
assert!(root_ref.prev_sibling().is_none());
}
#[test]
fn next_sibling() {
let mut tree = Tree::new();
tree.set_root(1);
let root_id = tree.root_id().expect("root doesn't exist?");
let root_ref = tree.get(root_id).unwrap();
assert!(root_ref.next_sibling().is_none());
}
#[test]
fn first_child() {
let mut tree = Tree::new();
tree.set_root(1);
let root_id = tree.root_id().expect("root doesn't exist?");
let root_ref = tree.get(root_id).unwrap();
assert!(root_ref.first_child().is_none());
}
#[test]
fn last_child() {
let mut tree = Tree::new();
tree.set_root(1);
let root_id = tree.root_id().expect("root doesn't exist?");
let root_ref = tree.get(root_id).unwrap();
assert!(root_ref.last_child().is_none());
}
#[test]
fn ancestors() {
let mut tree = Tree::new();
tree.set_root(1);
let mut root_mut = tree.root_mut().expect("root doesn't exist");
let node_id = root_mut.append(2).append(3).append(4).append(5).node_id();
let values = [4, 3, 2, 1];
let bottom_node = tree.get(node_id).unwrap();
for (i, node_ref) in bottom_node.ancestors().enumerate() {
assert_eq!(node_ref.data(), &values[i]);
}
}
#[test]
fn children() {
let mut tree = Tree::new();
tree.set_root(1);
let mut root = tree.root_mut().expect("root doesn't exist");
root.append(2);
root.append(3);
root.append(4);
root.append(5);
let values = [2, 3, 4, 5];
let root = root.as_ref();
for (i, node_ref) in root.children().enumerate() {
assert_eq!(node_ref.data(), &values[i]);
}
}
}

497
lib/slab-tree/src/slab.rs Normal file
View File

@ -0,0 +1,497 @@
use std::mem;
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub(super) struct Index {
index: usize,
generation: u64,
}
#[derive(Debug, PartialEq)]
enum Slot<T> {
Empty { next_free_slot: Option<usize> },
Filled { item: T, generation: u64 },
}
#[derive(Debug, PartialEq)]
pub(super) struct Slab<T> {
data: Vec<Slot<T>>,
first_free_slot: Option<usize>,
generation: u64,
}
impl<T> Slab<T> {
pub(super) fn new(capacity: usize) -> Slab<T> {
Slab {
data: Vec::with_capacity(capacity),
first_free_slot: None,
generation: 0,
}
}
pub(super) fn capacity(&self) -> usize {
self.data.capacity()
}
pub(super) fn insert(&mut self, item: T) -> Index {
let new_slot = Slot::Filled {
item,
generation: self.generation,
};
if let Some(index) = self.first_free_slot {
match mem::replace(&mut self.data[index], new_slot) {
Slot::Empty { next_free_slot } => {
self.first_free_slot = next_free_slot;
}
_ => unreachable!(),
};
Index {
index,
generation: self.generation,
}
} else {
self.data.push(new_slot);
Index {
index: self.data.len() - 1,
generation: self.generation,
}
}
}
pub(super) fn remove(&mut self, index: Index) -> Option<T> {
if index.index >= self.data.len() {
return None;
}
let slot = mem::replace(
&mut self.data[index.index],
Slot::Empty {
next_free_slot: self.first_free_slot,
},
);
match slot {
Slot::Filled { item, generation } => {
if index.generation == generation {
self.generation += 1;
self.first_free_slot = Some(index.index);
Some(item)
} else {
self.data[index.index] = Slot::Filled { item, generation };
None
}
}
s => {
self.data[index.index] = s;
None
}
}
}
pub(super) fn get(&self, index: Index) -> Option<&T> {
self.data.get(index.index).and_then(|slot| match slot {
Slot::Filled { item, generation } => {
if index.generation == *generation {
return Some(item);
}
None
}
_ => None,
})
}
pub(super) fn get_mut(&mut self, index: Index) -> Option<&mut T> {
self.data.get_mut(index.index).and_then(|slot| match slot {
Slot::Filled { item, generation } => {
if index.generation == *generation {
return Some(item);
}
None
}
_ => None,
})
}
}
#[cfg_attr(tarpaulin, skip)]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn capacity() {
let capacity = 5;
let slab = Slab::<i32>::new(capacity);
assert_eq!(slab.capacity(), capacity);
assert!(slab.first_free_slot.is_none());
assert_eq!(slab.generation, 0);
}
#[test]
fn insert() {
let capacity = 2;
let mut slab = Slab::new(capacity);
let six = slab.insert(6);
assert!(slab.first_free_slot.is_none());
assert_eq!(slab.generation, 0);
assert_eq!(slab.data.len(), 1);
assert_eq!(slab.data.capacity(), capacity);
assert_eq!(six.generation, 0);
assert_eq!(six.index, 0);
let seven = slab.insert(7);
assert!(slab.first_free_slot.is_none());
assert_eq!(slab.generation, 0);
assert_eq!(slab.data.len(), 2);
assert_eq!(slab.data.capacity(), capacity);
assert_eq!(seven.generation, 0);
assert_eq!(seven.index, 1);
let eight = slab.insert(8);
assert!(slab.first_free_slot.is_none());
assert_eq!(slab.generation, 0);
assert_eq!(slab.data.len(), 3);
assert!(slab.data.capacity() >= capacity);
assert_eq!(eight.generation, 0);
assert_eq!(eight.index, 2);
}
#[test]
fn remove_basic() {
let mut slab = Slab::new(5);
let _six = slab.insert(6);
let seven = slab.insert(7);
let _eight = slab.insert(8);
// |6|7|8|
let seven_rem = slab.remove(seven);
// |6|.|8|
assert!(seven_rem.is_some());
assert_eq!(seven_rem.unwrap(), 7);
assert_eq!(slab.first_free_slot.unwrap_or(10), 1);
assert_eq!(slab.generation, 1);
let six_slot = slab.data.get(0);
assert!(six_slot.is_some());
match six_slot.unwrap() {
Slot::Empty { .. } => {
panic!("Slot should be filled after call to insert.");
}
Slot::Filled { item, generation } => {
assert_eq!(item, &6);
assert_eq!(generation, &0);
}
}
let seven_slot = slab.data.get(1);
assert!(seven_slot.is_some());
match seven_slot.unwrap() {
Slot::Empty { next_free_slot } => {
assert!(next_free_slot.is_none());
}
Slot::Filled { .. } => {
panic!("Slot should be empty after call to remove.");
}
}
let eight_slot = slab.data.get(2);
assert!(eight_slot.is_some());
match eight_slot.unwrap() {
Slot::Empty { .. } => {
panic!("Slot should be filled after call to insert.");
}
Slot::Filled { item, generation } => {
assert_eq!(item, &8);
assert_eq!(generation, &0);
}
}
}
#[test]
fn double_remove() {
let mut slab = Slab::new(5);
let _six = slab.insert(6);
let seven = slab.insert(7);
let _eight = slab.insert(8);
// |6|7|8|
let seven_rem = slab.remove(seven);
// |6|.|8|
assert!(seven_rem.is_some());
assert_eq!(seven_rem.unwrap(), 7);
let seven_again = slab.remove(seven);
assert!(seven_again.is_none());
}
#[test]
fn remove_multiple() {
let mut slab = Slab::new(5);
let _six = slab.insert(6);
let seven = slab.insert(7);
let eight = slab.insert(8);
// |6|7|8|
let seven_rem = slab.remove(seven);
// |6|.|8|
assert!(seven_rem.is_some());
assert_eq!(seven_rem.unwrap(), 7);
assert_eq!(slab.first_free_slot.unwrap_or(10), 1);
assert_eq!(slab.generation, 1);
let six_slot = slab.data.get(0);
assert!(six_slot.is_some());
match six_slot.unwrap() {
Slot::Empty { .. } => {
panic!("Slot should be filled after call to insert.");
}
Slot::Filled { item, generation } => {
assert_eq!(item, &6);
assert_eq!(generation, &0);
}
}
let seven_slot = slab.data.get(1);
assert!(seven_slot.is_some());
match seven_slot.unwrap() {
Slot::Empty { next_free_slot } => {
assert!(next_free_slot.is_none());
}
Slot::Filled { .. } => {
panic!("Slot should be empty after call to remove.");
}
}
let eight_slot = slab.data.get(2);
assert!(eight_slot.is_some());
match eight_slot.unwrap() {
Slot::Empty { .. } => {
panic!("Slot should be filled after call to insert.");
}
Slot::Filled { item, generation } => {
assert_eq!(item, &8);
assert_eq!(generation, &0);
}
}
let eight_rem = slab.remove(eight);
// |6|.|.|
assert!(eight_rem.is_some());
assert_eq!(eight_rem.unwrap(), 8);
assert_eq!(slab.first_free_slot.unwrap_or(10), 2);
assert_eq!(slab.generation, 2);
let six_slot = slab.data.get(0);
assert!(six_slot.is_some());
match six_slot.unwrap() {
Slot::Empty { .. } => {
panic!("Slot should be filled after call to insert.");
}
Slot::Filled { item, generation } => {
assert_eq!(item, &6);
assert_eq!(generation, &0);
}
}
let seven_slot = slab.data.get(1);
assert!(seven_slot.is_some());
match seven_slot.unwrap() {
Slot::Empty { next_free_slot } => {
assert!(next_free_slot.is_none());
}
Slot::Filled { .. } => {
panic!("Slot should be empty after call to remove.");
}
}
let eight_slot = slab.data.get(2);
assert!(eight_slot.is_some());
match eight_slot.unwrap() {
Slot::Empty { next_free_slot } => {
assert!(next_free_slot.is_some());
assert_eq!(next_free_slot.unwrap(), 1);
}
Slot::Filled { .. } => {
panic!("Slot should be empty after call to remove.");
}
}
}
#[test]
fn remove_and_reinsert() {
let mut slab = Slab::new(5);
let _six = slab.insert(6);
let seven = slab.insert(7);
let eight = slab.insert(8);
// |6|7|8|
let seven_rem = slab.remove(seven);
// |6|.|8|
assert!(seven_rem.is_some());
assert_eq!(seven_rem.unwrap(), 7);
assert_eq!(slab.first_free_slot.unwrap_or(10), 1);
assert_eq!(slab.generation, 1);
let eight_rem = slab.remove(eight);
// |6|.|.|
assert!(eight_rem.is_some());
assert_eq!(eight_rem.unwrap(), 8);
assert_eq!(slab.first_free_slot.unwrap_or(10), 2);
assert_eq!(slab.generation, 2);
let nine = slab.insert(9);
// |6|.|9|
assert_eq!(nine.index, 2);
assert_eq!(nine.generation, 2);
let eight_again = slab.remove(eight);
assert!(eight_again.is_none());
let six_slot = slab.data.get(0);
assert!(six_slot.is_some());
match six_slot.unwrap() {
Slot::Empty { .. } => {
panic!("Slot should be filled after call to insert.");
}
Slot::Filled { item, generation } => {
assert_eq!(item, &6);
assert_eq!(generation, &0);
}
}
let seven_slot = slab.data.get(1);
assert!(seven_slot.is_some());
match seven_slot.unwrap() {
Slot::Empty { next_free_slot } => {
assert!(next_free_slot.is_none());
}
Slot::Filled { .. } => {
panic!("Slot should be empty after call to remove.");
}
}
let nine_slot = slab.data.get(2);
assert!(nine_slot.is_some());
match nine_slot.unwrap() {
Slot::Empty { .. } => {
panic!("Slot should be filled after call to insert.");
}
Slot::Filled { item, generation } => {
assert_eq!(item, &9);
assert_eq!(generation, &2);
}
}
}
#[test]
fn remove_with_bad_index() {
let mut slab = Slab::new(5);
let _six = slab.insert(6);
let _seven = slab.insert(7);
let mut eight = slab.insert(8);
// |0|1|2| index
// |6|7|8| value
eight.index = 3; // oops, this should be 2
let eight_rem = slab.remove(eight);
assert!(eight_rem.is_none());
}
#[test]
fn get() {
let mut slab = Slab::new(5);
let six = slab.insert(6);
assert_eq!(six.index, 0);
assert_eq!(six.generation, 0);
let seven = slab.insert(7);
assert_eq!(seven.index, 1);
assert_eq!(seven.generation, 0);
let six_ref = slab.get(six);
assert!(six_ref.is_some());
assert_eq!(six_ref.unwrap(), &6);
slab.remove(six);
let six_ref = slab.get(six);
assert!(six_ref.is_none());
let eight = slab.insert(8);
assert_eq!(eight.index, 0);
assert_eq!(eight.generation, 1);
let eight_ref = slab.get(eight);
assert!(eight_ref.is_some());
assert_eq!(eight_ref.unwrap(), &8);
let six_ref = slab.get(six);
assert!(six_ref.is_none());
}
#[test]
fn get_mut() {
let mut slab = Slab::new(5);
let six = slab.insert(6);
assert_eq!(six.index, 0);
assert_eq!(six.generation, 0);
let seven = slab.insert(7);
assert_eq!(seven.index, 1);
assert_eq!(seven.generation, 0);
let six_mut = slab.get_mut(six);
assert!(six_mut.is_some());
let six_mut = six_mut.unwrap();
assert_eq!(six_mut, &mut 6);
*six_mut = 60;
assert_eq!(six_mut, &mut 60);
slab.remove(six);
let six_ref = slab.get_mut(six);
assert!(six_ref.is_none());
let eight = slab.insert(8);
assert_eq!(eight.index, 0);
assert_eq!(eight.generation, 1);
let eight_ref = slab.get_mut(eight);
assert!(eight_ref.is_some());
assert_eq!(eight_ref.unwrap(), &mut 8);
let six_ref = slab.get_mut(six);
assert!(six_ref.is_none());
}
}

813
lib/slab-tree/src/tree.rs Normal file
View File

@ -0,0 +1,813 @@
use crate::behaviors::*;
use crate::core_tree::CoreTree;
use crate::node::*;
use crate::NodeId;
///
/// A `Tree` builder. Provides more control over how a `Tree` is created.
///
pub struct TreeBuilder<T> {
root: Option<T>,
capacity: Option<usize>,
}
impl<T> Default for TreeBuilder<T> {
fn default() -> Self {
TreeBuilder::new()
}
}
impl<T> TreeBuilder<T> {
///
/// Creates a new `TreeBuilder` with the default settings.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let _tree_builder = TreeBuilder::new();
///
/// # _tree_builder.with_root(1);
/// ```
///
pub fn new() -> TreeBuilder<T> {
TreeBuilder {
root: None,
capacity: None,
}
}
///
/// Sets the root `Node` of the `TreeBuilder`.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let _tree_builder = TreeBuilder::new().with_root(1);
/// ```
///
pub fn with_root(self, root: T) -> TreeBuilder<T> {
TreeBuilder {
root: Some(root),
capacity: self.capacity,
}
}
///
/// Sets the capacity of the `TreeBuilder`.
///
/// This can be used to pre-allocate space in the `Tree` if you know you'll be adding a large
/// number of `Node`s to the `Tree`.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let _tree_builder = TreeBuilder::new().with_capacity(10);
///
/// # _tree_builder.with_root(1);
/// ```
///
pub fn with_capacity(self, capacity: usize) -> TreeBuilder<T> {
TreeBuilder {
root: self.root,
capacity: Some(capacity),
}
}
///
/// Build a `Tree` based upon the current settings in the `TreeBuilder`.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let _tree = TreeBuilder::new().with_root(1).with_capacity(10).build();
/// ```
///
pub fn build(self) -> Tree<T> {
let capacity = self.capacity.unwrap_or(0);
let mut core_tree: CoreTree<T> = CoreTree::new(capacity);
let root_id = self.root.map(|val| core_tree.insert(val));
Tree { root_id, core_tree }
}
}
///
/// A tree structure containing `Node`s.
///
#[derive(Debug, PartialEq)]
pub struct Tree<T> {
pub(crate) root_id: Option<NodeId>,
pub(crate) core_tree: CoreTree<T>,
}
impl<T> Tree<T> {
///
/// Creates a new `Tree` with a capacity of 0.
///
/// ```
/// use slab_tree::tree::Tree;
///
/// let tree: Tree<i32> = Tree::new();
///
/// # assert_eq!(tree.capacity(), 0);
/// ```
///
pub fn new() -> Tree<T> {
TreeBuilder::new().build()
}
//todo: write test for this
///
/// Sets the "root" of the `Tree` to be `root`.
///
/// If there is already a "root" node in the `Tree`, that node is shifted down and the new
/// one takes its place.
///
/// ```
/// use slab_tree::tree::Tree;
///
/// let mut tree = Tree::new();
///
/// let root_id = tree.set_root(1);
///
/// assert_eq!(tree.root_id().unwrap(), root_id);
/// ```
///
pub fn set_root(&mut self, root: T) -> NodeId {
let old_root_id = self.root_id.take();
let new_root_id = self.core_tree.insert(root);
self.root_id = Some(new_root_id);
self.set_first_child(new_root_id, old_root_id);
self.set_last_child(new_root_id, old_root_id);
if let Some(node_id) = old_root_id {
self.set_parent(node_id, self.root_id);
}
new_root_id
}
///
/// Returns the `Tree`'s current capacity. Capacity is defined as the number of times new
/// `Node`s can be added to the `Tree` before it must allocate more memory.
///
/// ```
/// use slab_tree::tree::Tree;
///
/// let tree: Tree<i32> = Tree::new();
///
/// assert_eq!(tree.capacity(), 0);
/// ```
///
pub fn capacity(&self) -> usize {
self.core_tree.capacity()
}
///
/// Returns the `NodeId` of the root node of the `Tree`.
///
/// ```
/// use slab_tree::tree::Tree;
///
/// let mut tree = Tree::new();
/// tree.set_root(1);
///
/// let root_id = tree.root_id().expect("root doesn't exist?");
///
/// assert_eq!(tree.get(root_id).unwrap().data(), &1);
/// ```
///
pub fn root_id(&self) -> Option<NodeId> {
self.root_id
}
///
/// Returns a `NodeRef` pointing to the root `Node` of the `Tree`.
///
/// ```
/// use slab_tree::tree::Tree;
///
/// let mut tree = Tree::new();
/// tree.set_root(1);
///
/// let root = tree.root().expect("root doesn't exist?");
///
/// assert_eq!(root.data(), &1);
/// ```
///
pub fn root(&self) -> Option<NodeRef<T>> {
self.root_id.map(|id| self.new_node_ref(id))
}
///
/// Returns a `NodeMut` pointing to the root `Node` of the `Tree`.
///
/// ```
/// use slab_tree::tree::Tree;
///
/// let mut tree = Tree::new();
/// tree.set_root(1);
///
/// let mut root = tree.root_mut().expect("root doesn't exist?");
/// assert_eq!(root.data(), &mut 1);
///
/// *root.data() = 2;
/// assert_eq!(root.data(), &mut 2);
/// ```
///
pub fn root_mut(&mut self) -> Option<NodeMut<T>> {
self.root_id.map(move |id| self.new_node_mut(id))
}
///
/// Returns the `NodeRef` pointing to the `Node` that the given `NodeId` identifies. If the
/// `NodeId` in question points to nothing (or belongs to a different `Tree`) a `None`-value
/// will be returned; otherwise, a `Some`-value will be returned.
///
/// ```
/// use slab_tree::tree::Tree;
///
/// let mut tree = Tree::new();
/// tree.set_root(1);
/// let root_id = tree.root_id().expect("root doesn't exist?");
///
/// let root = tree.get(root_id);
/// assert!(root.is_some());
///
/// let root = root.unwrap();
/// assert_eq!(root.data(), &1);
/// ```
///
pub fn get(&self, node_id: NodeId) -> Option<NodeRef<T>> {
let _ = self.core_tree.get(node_id)?;
Some(self.new_node_ref(node_id))
}
///
/// Returns the `NodeMut` pointing to the `Node` that the given `NodeId` identifies. If the
/// `NodeId` in question points to nothing (or belongs to a different `Tree`) a `None`-value
/// will be returned; otherwise, a `Some`-value will be returned.
///
/// ```
/// use slab_tree::tree::Tree;
///
/// let mut tree = Tree::new();
/// tree.set_root(1);
/// let root_id = tree.root_id().expect("root doesn't exist?");
///
/// let root = tree.get_mut(root_id);
/// assert!(root.is_some());
///
/// let mut root = root.unwrap();
///
/// *root.data() = 2;
/// assert_eq!(root.data(), &mut 2);
/// ```
///
pub fn get_mut(&mut self, node_id: NodeId) -> Option<NodeMut<T>> {
let _ = self.core_tree.get_mut(node_id)?;
Some(self.new_node_mut(node_id))
}
///
/// Remove a `Node` by its `NodeId` and return the data that it contained.
/// Returns a `Some`-value if the `Node` exists; returns a `None`-value otherwise.
///
/// Children of the removed `Node` can either be dropped with `DropChildren` or orphaned with
/// `OrphanChildren`.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
/// use slab_tree::behaviors::RemoveBehavior::*;
///
/// let mut tree = TreeBuilder::new().with_root(1).build();
/// let two_id = {
/// let mut root = tree.root_mut().expect("root doesn't exist?");
/// let two_id = root.append(2).node_id();
/// root.append(3);
/// two_id
/// };
///
/// let two = tree.remove(two_id, DropChildren);
///
/// assert!(two.is_some());
/// assert_eq!(two.unwrap(), 2);
///
/// let root = tree.root().expect("root doesn't exist?");
/// assert!(root.first_child().is_some());
/// assert_eq!(root.first_child().unwrap().data(), &mut 3);
///
/// assert!(root.last_child().is_some());
/// assert_eq!(root.last_child().unwrap().data(), &mut 3);
/// ```
///
pub fn remove(&mut self, node_id: NodeId, behavior: RemoveBehavior) -> Option<T> {
if let Some(node) = self.get_node(node_id) {
let Relatives {
parent,
prev_sibling,
next_sibling,
..
} = node.relatives;
let (is_first_child, is_last_child) = self.is_node_first_last_child(node_id);
if is_first_child {
// parent first child = my next sibling
self.set_first_child(parent.expect("parent must exist"), next_sibling);
}
if is_last_child {
// parent last child = my prev sibling
self.set_last_child(parent.expect("parent must exist"), prev_sibling);
}
if let Some(prev) = prev_sibling {
self.set_next_sibling(prev, next_sibling);
}
if let Some(next) = next_sibling {
self.set_prev_sibling(next, prev_sibling);
}
match behavior {
RemoveBehavior::DropChildren => self.drop_children(node_id),
RemoveBehavior::OrphanChildren => self.orphan_children(node_id),
};
if self.root_id == Some(node_id) {
self.root_id = None;
}
self.core_tree.remove(node_id)
} else {
None
}
}
pub(crate) fn get_node(&self, node_id: NodeId) -> Option<&Node<T>> {
self.core_tree.get(node_id)
}
pub(crate) fn get_node_mut(&mut self, node_id: NodeId) -> Option<&mut Node<T>> {
self.core_tree.get_mut(node_id)
}
pub(crate) fn set_prev_siblings_next_sibling(
&mut self,
current_id: NodeId,
next_sibling: Option<NodeId>,
) {
if let Some(prev_sibling_id) = self.get_node_prev_sibling_id(current_id) {
self.set_next_sibling(prev_sibling_id, next_sibling);
}
}
pub(crate) fn set_next_siblings_prev_sibling(
&mut self,
current_id: NodeId,
prev_sibling: Option<NodeId>,
) {
if let Some(next_sibling_id) = self.get_node_next_sibling_id(current_id) {
self.set_prev_sibling(next_sibling_id, prev_sibling);
}
}
pub(crate) fn set_parent(&mut self, node_id: NodeId, parent_id: Option<NodeId>) {
if let Some(node) = self.get_node_mut(node_id) {
node.relatives.parent = parent_id;
} else {
unreachable!()
}
}
pub(crate) fn set_prev_sibling(&mut self, node_id: NodeId, prev_sibling: Option<NodeId>) {
if let Some(node) = self.get_node_mut(node_id) {
node.relatives.prev_sibling = prev_sibling;
} else {
unreachable!()
}
}
pub(crate) fn set_next_sibling(&mut self, node_id: NodeId, next_sibling: Option<NodeId>) {
if let Some(node) = self.get_node_mut(node_id) {
node.relatives.next_sibling = next_sibling;
} else {
unreachable!()
}
}
pub(crate) fn set_first_child(&mut self, node_id: NodeId, first_child: Option<NodeId>) {
if let Some(node) = self.get_node_mut(node_id) {
node.relatives.first_child = first_child;
} else {
unreachable!()
}
}
pub(crate) fn set_last_child(&mut self, node_id: NodeId, last_child: Option<NodeId>) {
if let Some(node) = self.get_node_mut(node_id) {
node.relatives.last_child = last_child;
} else {
unreachable!()
}
}
pub(crate) fn get_node_prev_sibling_id(&self, node_id: NodeId) -> Option<NodeId> {
if let Some(node) = self.get_node(node_id) {
node.relatives.prev_sibling
} else {
unreachable!()
}
}
pub(crate) fn get_node_next_sibling_id(&self, node_id: NodeId) -> Option<NodeId> {
if let Some(node) = self.get_node(node_id) {
node.relatives.next_sibling
} else {
unreachable!()
}
}
pub(crate) fn get_node_relatives(&self, node_id: NodeId) -> Relatives {
if let Some(node) = self.get_node(node_id) {
node.relatives
} else {
unreachable!()
}
}
fn drop_children(&mut self, node_id: NodeId) {
let sub_tree_ids: Vec<NodeId> = self
.get(node_id)
.expect("node must exist")
.traverse_level_order()
.skip(1) // skip the "root" of the sub-tree, which is the "current" node
.map(|node_ref| node_ref.node_id())
.collect();
for id in sub_tree_ids {
self.core_tree.remove(id);
}
}
fn orphan_children(&mut self, node_id: NodeId) {
let child_ids: Vec<NodeId> = self
.get(node_id)
.expect("node must exist")
.children()
.map(|node_ref| node_ref.node_id())
.collect();
for id in child_ids {
self.set_parent(id, None);
}
}
fn new_node_ref(&self, node_id: NodeId) -> NodeRef<T> {
NodeRef::new(node_id, self)
}
fn new_node_mut(&mut self, node_id: NodeId) -> NodeMut<T> {
NodeMut::new(node_id, self)
}
fn is_node_first_last_child(&self, node_id: NodeId) -> (bool, bool) {
if let Some(node) = self.get_node(node_id) {
node.relatives
.parent
.and_then(|parent_id| self.get_node(parent_id))
.map(|parent| {
let Relatives {
first_child: first,
last_child: last,
..
} = parent.relatives;
(
first.map(|child_id| child_id == node_id).unwrap_or(false),
last.map(|child_id| child_id == node_id).unwrap_or(false),
)
})
.unwrap_or((false, false))
} else {
(false, false)
}
}
}
impl<T> Default for Tree<T> {
fn default() -> Self {
TreeBuilder::new().build()
}
}
impl<T: std::fmt::Debug> Tree<T> {
/// Write formatted tree representation and nodes with debug formatting.
///
/// Example:
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let mut tree = TreeBuilder::new().with_root(0).build();
/// let mut root = tree.root_mut().unwrap();
/// root.append(1)
/// .append(2);
/// root.append(3);
/// let mut s = String::new();
/// tree.write_formatted(&mut s).unwrap();
/// assert_eq!(&s, "\
/// 0
/// ├── 1
/// │ └── 2
/// └── 3
/// ");
/// ```
///
/// Writes nothing if the tree is empty.
///
/// ```
/// use slab_tree::tree::TreeBuilder;
///
/// let tree = TreeBuilder::<i32>::new().build();
/// let mut s = String::new();
/// tree.write_formatted(&mut s).unwrap();
/// assert_eq!(&s, "");
/// ```
pub fn write_formatted<W: std::fmt::Write>(&self, w: &mut W) -> std::fmt::Result {
if let Some(root) = self.root() {
let node_id = root.node_id();
let childn = 0;
let level = 0;
let last = vec![];
let mut stack = vec![(node_id, childn, level, last)];
while let Some((node_id, childn, level, last)) = stack.pop() {
debug_assert_eq!(
last.len(),
level,
"each previous level should indicate whether it has reached the last node"
);
let node = self
.get(node_id)
.expect("getting node of existing node ref id");
if childn == 0 {
for i in 1..level {
if last[i - 1] {
write!(w, " ")?;
} else {
write!(w, "")?;
}
}
if level > 0 {
if last[level - 1] {
write!(w, "└── ")?;
} else {
write!(w, "├── ")?;
}
}
writeln!(w, "{:?}", node.data())?;
}
let mut children = node.children().skip(childn);
if let Some(child) = children.next() {
let mut next_last = last.clone();
if children.next().is_some() {
stack.push((node_id, childn + 1, level, last));
next_last.push(false);
} else {
next_last.push(true);
}
stack.push((child.node_id(), 0, level + 1, next_last));
}
}
}
Ok(())
}
}
#[cfg_attr(tarpaulin, skip)]
#[cfg(test)]
mod tree_tests {
use super::*;
use crate::behaviors::RemoveBehavior::{DropChildren, OrphanChildren};
#[test]
fn capacity() {
let tree = TreeBuilder::new().with_root(1).with_capacity(5).build();
assert_eq!(tree.capacity(), 5);
}
#[test]
fn root_id() {
let tree = TreeBuilder::new().with_root(1).build();
let root_id = tree.root_id().expect("root doesn't exist?");
let root = tree.get(root_id).unwrap();
assert_eq!(root.data(), &1);
}
#[test]
fn remove_root_drop() {
let mut tree = TreeBuilder::new().with_root(1).build();
let root_id = tree.root_id().expect("root doesn't exist?");
tree.remove(root_id, RemoveBehavior::DropChildren);
assert!(tree.root().is_none());
}
#[test]
fn remove_root_orphan() {
let mut tree = TreeBuilder::new().with_root(1).build();
let root_id = tree.root_id().expect("root doesn't exist?");
tree.remove(root_id, RemoveBehavior::OrphanChildren);
assert!(tree.root().is_none());
}
#[test]
fn root() {
let tree = TreeBuilder::new().with_root(1).build();
let root = tree.root().expect("root doesn't exist?");
assert_eq!(root.data(), &1);
}
#[test]
fn root_mut() {
let mut tree = TreeBuilder::new().with_root(1).build();
let mut root = tree.root_mut().expect("root doesn't exist?");
assert_eq!(root.data(), &mut 1);
*root.data() = 2;
assert_eq!(root.data(), &mut 2);
}
#[test]
fn get() {
let tree = TreeBuilder::new().with_root(1).build();
let root_id = tree.root_id().expect("root doesn't exist?");
let root = tree.get(root_id);
assert!(root.is_some());
let root = root.unwrap();
assert_eq!(root.data(), &1);
}
#[test]
fn get_mut() {
let mut tree = TreeBuilder::new().with_root(1).build();
let root_id = tree.root_id().expect("root doesn't exist?");
let root = tree.get_mut(root_id);
assert!(root.is_some());
let mut root = root.unwrap();
assert_eq!(root.data(), &mut 1);
*root.data() = 2;
assert_eq!(root.data(), &mut 2);
}
#[test]
fn get_node() {
let tree = TreeBuilder::new().with_root(1).build();
let root_id = tree.root_id().expect("root doesn't exist?");
let root = tree.get_node(root_id);
assert!(root.is_some());
let root = root.unwrap();
assert_eq!(root.data, 1);
}
#[test]
fn get_node_mut() {
let mut tree = TreeBuilder::new().with_root(1).build();
let root_id = tree.root_id().expect("root doesn't exist?");
let root = tree.get_node_mut(root_id);
assert!(root.is_some());
let root = root.unwrap();
assert_eq!(root.data, 1);
root.data = 2;
assert_eq!(root.data, 2);
}
#[test]
fn remove_drop() {
let mut tree = TreeBuilder::new().with_root(1).build();
let two_id;
let three_id;
let four_id;
let five_id;
{
let mut root = tree.root_mut().expect("root doesn't exist?");
two_id = root.append(2).node_id();
three_id = root.append(3).node_id();
four_id = root.append(4).node_id();
}
{
five_id = tree
.get_mut(three_id)
.expect("three doesn't exist?")
.append(5)
.node_id();
}
// 1
// / | \
// 2 3 4
// |
// 5
tree.remove(three_id, DropChildren);
let root = tree
.get_node(tree.root_id().expect("tree doesn't exist?"))
.unwrap();
assert!(root.relatives.first_child.is_some());
assert!(root.relatives.last_child.is_some());
assert_eq!(root.relatives.first_child.unwrap(), two_id);
assert_eq!(root.relatives.last_child.unwrap(), four_id);
let two = tree.get_node(two_id);
assert!(two.is_some());
let two = two.unwrap();
assert_eq!(two.relatives.next_sibling, Some(four_id));
let four = tree.get_node(four_id);
assert!(four.is_some());
let four = four.unwrap();
assert_eq!(four.relatives.prev_sibling, Some(two_id));
let five = tree.get_node(five_id);
assert!(five.is_none());
}
/// Test that there is no panic if caller tries to remove a removed node
#[test]
fn address_dropped() {
let mut tree = TreeBuilder::new().with_root(1).build();
let two_id = tree.root_mut().expect("root doesn't exist").node_id();
tree.remove(two_id, DropChildren);
tree.remove(two_id, DropChildren);
}
#[test]
fn remove_orphan() {
let mut tree = TreeBuilder::new().with_root(1).build();
let two_id;
let three_id;
let four_id;
let five_id;
{
let mut root = tree.root_mut().expect("root doesn't exist?");
two_id = root.append(2).node_id();
three_id = root.append(3).node_id();
four_id = root.append(4).node_id();
}
{
five_id = tree
.get_mut(three_id)
.expect("three doesn't exist?")
.append(5)
.node_id();
}
// 1
// / | \
// 2 3 4
// |
// 5
tree.remove(three_id, OrphanChildren);
let root = tree
.get_node(tree.root_id().expect("tree doesn't exist?"))
.unwrap();
assert!(root.relatives.first_child.is_some());
assert!(root.relatives.last_child.is_some());
assert_eq!(root.relatives.first_child.unwrap(), two_id);
assert_eq!(root.relatives.last_child.unwrap(), four_id);
let two = tree.get_node(two_id);
assert!(two.is_some());
let two = two.unwrap();
assert_eq!(two.relatives.next_sibling, Some(four_id));
let four = tree.get_node(four_id);
assert!(four.is_some());
let four = four.unwrap();
assert_eq!(four.relatives.prev_sibling, Some(two_id));
let five = tree.get_node(five_id);
assert!(five.is_some());
let five = five.unwrap();
assert_eq!(five.relatives.parent, None);
}
}

View File

@ -2,6 +2,7 @@ use std::{fs, io};
use std::path::{Path, PathBuf};
use ratatui::style::Color;
use slab_tree::NodeId;
use crate::component::dialog::input::InputFieldDialogLayer;
@ -11,7 +12,6 @@ use crate::component::filesystem::FsLayer;
use crate::file::FileKind;
use crate::state::action::{Action, ActionResult};
use crate::state::Environment;
use crate::util::slab_tree::NodeRefExtensions;
trait CreateEntry {
fn title() -> &'static str;

View File

@ -13,7 +13,6 @@ use crate::component::filesystem::tree::FsTreeViewNode;
use crate::state::action::{Action, ActionResult};
use crate::state::Environment;
use crate::state::event::EventResult;
use crate::util::slab_tree::NodeRefExtensions;
pub struct EditSelectedEntry;

View File

@ -3,6 +3,7 @@ use std::{fs, io};
use std::path::PathBuf;
use ratatui::style::Color;
use slab_tree::NodeRef;
use crate::component::dialog::input::InputFieldDialogLayer;
@ -13,7 +14,6 @@ use crate::component::filesystem::tree::FsTreeViewNode;
use crate::file::FileEntry;
use crate::state::action::{Action, ActionResult};
use crate::state::Environment;
use crate::util::slab_tree::NodeRefExtensions;
pub struct RenameSelectedEntry {
pub prefill: bool,

View File

@ -2,14 +2,13 @@ use slab_tree::{NodeId, NodeRef};
use crate::component::filesystem::action::movement::{MovementAction, perform_movement_with_count_from_register, SimpleMovementAction};
use crate::component::filesystem::FsLayer;
use crate::component::filesystem::tree::{FsTree, FsTreeView, FsTreeViewNode};
use crate::component::filesystem::tree::{FsTree, FsTreeViewNode};
use crate::state::Environment;
use crate::util::slab_tree::NodeRefExtensions;
pub struct MoveToNextSibling;
impl SimpleMovementAction for MoveToNextSibling {
fn get_target(_view: &FsTreeView, selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
fn get_target(selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
selected_node.next_sibling_id()
}
}
@ -17,7 +16,7 @@ impl SimpleMovementAction for MoveToNextSibling {
pub struct MoveToPreviousSibling;
impl SimpleMovementAction for MoveToPreviousSibling {
fn get_target(_view: &FsTreeView, selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
fn get_target(selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
selected_node.prev_sibling_id()
}
}
@ -25,7 +24,7 @@ impl SimpleMovementAction for MoveToPreviousSibling {
pub struct MoveBetweenFirstAndLastSibling;
impl SimpleMovementAction for MoveBetweenFirstAndLastSibling {
fn get_target(_view: &FsTreeView, selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
fn get_target(selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
if selected_node.next_sibling().is_none() {
selected_node.parent().and_then(|node| node.first_child_id())
} else {
@ -37,7 +36,7 @@ impl SimpleMovementAction for MoveBetweenFirstAndLastSibling {
pub struct MoveToParent;
impl SimpleMovementAction for MoveToParent {
fn get_target(_view: &FsTreeView, selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
fn get_target(selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
selected_node.parent_id()
}
}
@ -52,8 +51,8 @@ impl MovementAction for MoveOrTraverseUpParent {
impl MoveOrTraverseUpParent {
fn get_target(tree: &mut FsTree, node_id: NodeId) -> Option<NodeId> {
if let Some(node) = tree.view.get(node_id) {
let target_node_id = <MoveToParent as SimpleMovementAction>::get_target(&tree.view, &node);
if let Some(node) = tree.get_view_node(node_id) {
let target_node_id = <MoveToParent as SimpleMovementAction>::get_target(&node);
if target_node_id.is_some() {
return target_node_id;
} else if let Some(target_node_id) = tree.traverse_up_root() {

View File

@ -2,15 +2,15 @@ use slab_tree::{NodeId, NodeRef};
use crate::component::filesystem::action::movement::{get_simple_movement_target, MovementAction, MoveToParent, perform_movement_with_count_from, SimpleMovementAction};
use crate::component::filesystem::FsLayer;
use crate::component::filesystem::tree::{FsTree, FsTreeView, FsTreeViewNode};
use crate::component::filesystem::tree::{FsTree, FsTreeViewNode};
use crate::state::Environment;
/// Moves up `count` lines (1 line by default).
pub struct MoveUp;
impl SimpleMovementAction for MoveUp {
fn get_target(tree: &FsTreeView, selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
tree.get_node_above(selected_node)
fn get_target(selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
selected_node.above_id()
}
}
@ -18,8 +18,8 @@ impl SimpleMovementAction for MoveUp {
pub struct MoveDown;
impl SimpleMovementAction for MoveDown {
fn get_target(tree: &FsTreeView, selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> {
tree.get_node_below(selected_node)
fn get_target(selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> {
selected_node.below_id()
}
}
@ -36,7 +36,7 @@ impl MoveToFirst {
fn get_target(tree: &mut FsTree) -> NodeId where Self: Sized {
let mut target_node_id = tree.selected_view_node_id;
while let Some(node_id) = tree.view.get(target_node_id).and_then(|node| <MoveToParent as SimpleMovementAction>::get_target(&tree.view, &node)) {
while let Some(node_id) = tree.get_view_node(target_node_id).and_then(|node| <MoveToParent as SimpleMovementAction>::get_target(&node)) {
target_node_id = node_id;
}
@ -50,8 +50,8 @@ pub struct MoveToLast;
impl MovementAction for MoveToLast {
fn get_target(&self, layer: &mut FsLayer, _environment: &Environment) -> Option<NodeId> where Self: Sized {
let first_node_id = MoveToFirst::get_target(&mut layer.tree);
let last_node_id = layer.tree.view.get_last_descendant_or_self(first_node_id);
Some(last_node_id)
let last_node_id = layer.tree.get_view_node(first_node_id).map(|node| node.last_descendant_or_self().node_id());
last_node_id
}
}

View File

@ -1,7 +1,7 @@
use slab_tree::{NodeId, NodeRef};
use crate::component::filesystem::FsLayer;
use crate::component::filesystem::tree::{FsTree, FsTreeView, FsTreeViewNode};
use crate::component::filesystem::tree::{FsTree, FsTreeViewNode};
use crate::state::action::{Action, ActionResult};
use crate::state::Environment;
@ -56,7 +56,7 @@ fn perform_movement_with_count_from<F>(tree: &mut FsTree, count: Option<usize>,
}
pub trait SimpleMovementAction {
fn get_target(view: &FsTreeView, selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized;
fn get_target(selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized;
}
impl<T: SimpleMovementAction> MovementAction for T {
@ -66,5 +66,5 @@ impl<T: SimpleMovementAction> MovementAction for T {
}
fn get_simple_movement_target<T: SimpleMovementAction>(tree: &mut FsTree, node_id: NodeId) -> Option<NodeId> {
tree.view.get(node_id).and_then(|node| T::get_target(&tree.view, &node))
tree.get_view_node(node_id).and_then(|node| T::get_target(&node))
}

View File

@ -3,7 +3,7 @@ use std::marker::PhantomData;
use slab_tree::{NodeId, NodeRef};
use crate::component::filesystem::action::movement::SimpleMovementAction;
use crate::component::filesystem::tree::{FsTreeView, FsTreeViewNode};
use crate::component::filesystem::tree::FsTreeViewNode;
/// A movement action with fallback.
pub struct MovementWithFallback<A: SimpleMovementAction, F: SimpleMovementAction>(PhantomData<A>, PhantomData<F>);
@ -21,7 +21,7 @@ impl<A: SimpleMovementAction, F: SimpleMovementAction> MovementWithFallbackFacto
}
impl<A: SimpleMovementAction, F: SimpleMovementAction> SimpleMovementAction for MovementWithFallback<A, F> {
fn get_target(view: &FsTreeView, selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
A::get_target(view, selected_node).or_else(|| F::get_target(view, selected_node))
fn get_target(selected_node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> where Self: Sized {
A::get_target(selected_node).or_else(|| F::get_target(selected_node))
}
}

View File

@ -7,7 +7,7 @@ use ratatui::widgets::{Clear, Widget};
use slab_tree::{NodeId, NodeRef};
use crate::component::filesystem::{ColumnWidths, FsLayer};
use crate::component::filesystem::tree::{FsTree, FsTreeView, FsTreeViewNode};
use crate::component::filesystem::tree::{FsTree, FsTreeViewNode};
use crate::file::{FileEntry, FileKind, FileOwnerNameCache};
use crate::state::view::Frame;
@ -37,7 +37,7 @@ fn get_or_update_column_widths(layer: &mut FsLayer, cols: u16) -> ColumnWidths {
let mut user: usize = 0;
let mut group: usize = 0;
for node in &layer.tree.view {
for node in layer.tree.view_iter() {
let entry = layer.tree.get_entry(&node).unwrap_or_else(|| FileEntry::dummy_as_ref());
name = max(name, get_node_level(&node).saturating_add(Span::from(entry.name().str()).width()));
@ -63,7 +63,7 @@ fn collect_displayed_rows(tree: &FsTree, selected_node_id: NodeId, terminal_rows
let mut displayed_rows = Vec::with_capacity(terminal_rows);
let mut cursor_y: u16 = 0;
if let Some(middle_node) = tree.selected_node().or_else(|| tree.view.root()) {
if let Some(middle_node) = tree.selected_node().or_else(|| tree.view_root_node()) {
let middle_node_id = middle_node.node_id();
displayed_rows.push(NodeRow::from(&middle_node, tree, middle_node_id == selected_node_id));
@ -72,7 +72,7 @@ fn collect_displayed_rows(tree: &FsTree, selected_node_id: NodeId, terminal_rows
let mut cursor_down_id = Some(middle_node_id);
while displayed_rows.len() < terminal_rows {
if let Some(next_node_up) = move_cursor(tree, &mut cursor_up_id, FsTreeView::get_node_above) {
if let Some(next_node_up) = move_cursor(tree, &mut cursor_up_id, |node| node.above_id()) {
displayed_rows.insert(0, NodeRow::from(&next_node_up, tree, false));
cursor_y = cursor_y.saturating_add(1);
}
@ -81,7 +81,7 @@ fn collect_displayed_rows(tree: &FsTree, selected_node_id: NodeId, terminal_rows
break;
}
if let Some(next_node_down) = move_cursor(tree, &mut cursor_down_id, FsTreeView::get_node_below) {
if let Some(next_node_down) = move_cursor(tree, &mut cursor_down_id, |node| node.below_id()) {
displayed_rows.push(NodeRow::from(&next_node_down, tree, false));
}
@ -94,12 +94,11 @@ fn collect_displayed_rows(tree: &FsTree, selected_node_id: NodeId, terminal_rows
(displayed_rows, cursor_y)
}
fn move_cursor<'a, F>(tree: &'a FsTree, cursor: &mut Option<NodeId>, func: F) -> Option<NodeRef<'a, FsTreeViewNode>> where F: FnOnce(&FsTreeView, &NodeRef<FsTreeViewNode>) -> Option<NodeId> {
let view = &tree.view;
fn move_cursor<'a, F>(tree: &'a FsTree, cursor: &mut Option<NodeId>, func: F) -> Option<NodeRef<'a, FsTreeViewNode>> where F: FnOnce(NodeRef<FsTreeViewNode>) -> Option<NodeId> {
let next_node = cursor
.and_then(|id| view.get(id))
.and_then(|node| func(view, &node))
.and_then(|id| view.get(id));
.and_then(|id| tree.get_view_node(id))
.and_then(func)
.and_then(|id| tree.get_view_node(id));
*cursor = next_node.as_ref().map(NodeRef::node_id);

View File

@ -2,6 +2,7 @@ use std::path::Path;
use slab_tree::{NodeId, NodeRef};
use crate::component::filesystem::tree::view::FsTreeViewIterator;
use crate::file::FileEntry;
pub use self::model::FsTreeModel;
@ -14,7 +15,7 @@ mod view;
pub struct FsTree {
model: FsTreeModel,
pub view: FsTreeView,
view: FsTreeView,
pub selected_view_node_id: NodeId,
structure_version: u32,
}
@ -44,6 +45,14 @@ impl FsTree {
return self.view.get(self.selected_view_node_id);
}
pub fn view_root_node(&self) -> Option<NodeRef<FsTreeViewNode>> {
self.view.root()
}
pub fn view_iter(&self) -> FsTreeViewIterator {
self.view.into_iter()
}
pub fn get_view_node(&self, view_node_id: NodeId) -> Option<NodeRef<FsTreeViewNode>> {
self.view.get(view_node_id)
}
@ -105,7 +114,7 @@ impl FsTree {
let view = &mut self.view;
if self.selected_view_node_id == view_node_id {
self.selected_view_node_id = view.get_node_below_id(view_node_id).or_else(|| view.get_node_above_id(view_node_id)).unwrap_or_else(|| view.root_id());
self.selected_view_node_id = view.get(view_node_id).and_then(|node| node.below_id().or_else(|| node.above_id())).unwrap_or_else(|| view.root_id());
}
if let Some(view_node) = view.remove(view_node_id) {

View File

@ -5,7 +5,6 @@ use slab_tree::NodeId;
use crate::component::filesystem::tree::{FsTreeModel, FsTreeModelNode};
use crate::file::FileEntry;
use crate::util::slab_tree::{NodeMutExtensions, NodeRefExtensions};
impl FsTreeModel {
pub fn resolve_children(&mut self, node_id: NodeId) -> Option<Vec<NodeId>> {

View File

@ -1,48 +0,0 @@
use slab_tree::{NodeId, NodeRef};
use crate::component::filesystem::tree::{FsTreeView, FsTreeViewNode};
use crate::util::slab_tree::NodeRefExtensions;
impl FsTreeView {
pub fn get_node_above(&self, node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> {
if let Some(prev_sibling_id) = node.prev_sibling_id() {
Some(self.get_last_descendant_or_self(prev_sibling_id))
} else {
node.parent_id()
}
}
#[allow(clippy::unused_self)]
pub fn get_node_below(&self, node: &NodeRef<FsTreeViewNode>) -> Option<NodeId> {
if let Some(next_id) = node.first_child_id() {
Some(next_id)
} else if let Some(next_id) = node.next_sibling_id() {
Some(next_id)
} else {
for ancestor in node.ancestors() {
if let Some(next_id) = ancestor.next_sibling_id() {
return Some(next_id);
}
}
None
}
}
pub fn get_node_above_id(&self, node_id: NodeId) -> Option<NodeId> {
self.get(node_id).and_then(|node| self.get_node_above(&node))
}
pub fn get_node_below_id(&self, node_id: NodeId) -> Option<NodeId> {
self.get(node_id).and_then(|node| self.get_node_below(&node))
}
pub fn get_last_descendant_or_self(&self, id: NodeId) -> NodeId {
let mut id = id;
while let Some(node_id) = self.get(id).and_then(|node| node.last_child_id()) {
id = node_id;
}
id
}
}

View File

@ -2,7 +2,8 @@ use slab_tree::{NodeId, NodeMut, NodeRef, RemoveBehavior, Tree};
use crate::component::filesystem::tree::FsTreeModel;
mod above_below;
pub use self::iterator::FsTreeViewIterator;
mod expand_collapse;
mod iterator;
mod refresh;

View File

@ -4,13 +4,13 @@ use crate::component::filesystem::tree::{FsTreeModel, FsTreeView, FsTreeViewNode
impl FsTreeView {
pub fn traverse_up_root(&mut self, model: &mut FsTreeModel) -> Option<NodeId> {
let old_moodel_root_id = model.root_id();
let old_model_root_id = model.root_id();
if let Some(new_model_root_id) = model.traverse_up_root() {
self.set_root(new_model_root_id);
if let Some(mut new_view_root) = self.get_mut(self.root_id) {
Self::resolve_new_root_children(&mut new_view_root, model, old_moodel_root_id, new_model_root_id);
Self::resolve_new_root_children(&mut new_view_root, model, old_model_root_id, new_model_root_id);
Some(self.root_id)
} else {
None

View File

@ -1,4 +1,3 @@
pub use integer_length::int_len;
mod integer_length;
pub mod slab_tree;

View File

@ -1,61 +0,0 @@
use slab_tree::{NodeId, NodeMut, NodeRef};
pub trait NodeRefExtensions {
fn parent_id(&self) -> Option<NodeId>;
fn first_child_id(&self) -> Option<NodeId>;
fn last_child_id(&self) -> Option<NodeId>;
fn prev_sibling_id(&self) -> Option<NodeId>;
fn next_sibling_id(&self) -> Option<NodeId>;
}
pub trait NodeMutExtensions {
fn parent_id(&mut self) -> Option<NodeId>;
fn first_child_id(&mut self) -> Option<NodeId>;
fn last_child_id(&mut self) -> Option<NodeId>;
fn prev_sibling_id(&mut self) -> Option<NodeId>;
fn next_sibling_id(&mut self) -> Option<NodeId>;
}
impl<'a, T> NodeRefExtensions for NodeRef<'a, T> {
fn parent_id(&self) -> Option<NodeId> {
self.parent().map(|node| node.node_id())
}
fn first_child_id(&self) -> Option<NodeId> {
self.first_child().map(|node| node.node_id())
}
fn last_child_id(&self) -> Option<NodeId> {
self.last_child().map(|node| node.node_id())
}
fn prev_sibling_id(&self) -> Option<NodeId> {
self.prev_sibling().map(|node| node.node_id())
}
fn next_sibling_id(&self) -> Option<NodeId> {
self.next_sibling().map(|node| node.node_id())
}
}
impl<'a, T> NodeMutExtensions for NodeMut<'a, T> {
fn parent_id(&mut self) -> Option<NodeId> {
self.parent().map(|node| node.node_id())
}
fn first_child_id(&mut self) -> Option<NodeId> {
self.first_child().map(|node| node.node_id())
}
fn last_child_id(&mut self) -> Option<NodeId> {
self.last_child().map(|node| node.node_id())
}
fn prev_sibling_id(&mut self) -> Option<NodeId> {
self.prev_sibling().map(|node| node.node_id())
}
fn next_sibling_id(&mut self) -> Option<NodeId> {
self.next_sibling().map(|node| node.node_id())
}
}