Struct DepthFirstSequence

Source
pub struct DepthFirstSequence<T, I>(/* private fields */)
where
    I: IntoIterator<Item = (usize, T)>;
Expand description

A depth first sequence is a representation of a tree in a linear storage of (depth, value) tuples. This is useful in collecting trees from iterators, (de)-serializing trees or converting its variant from one to another.

DepthFirstSequence struct is nothing but a wrapper around a (usize, T) iterator in order to state explicitly that this iterator is expected to follow the depth-first-order of (depth, value) pairs.

A DepthFirstSequence can be created from any type that implements IntoIterator<Item = (usize, T)> using From (or Into) traits.

In order to create a valid tree from the iterator, the order of pairs must satisfy certain conditions. Assume (depth(i), value(i)) is the i-th item of the iterator. Then, the following conditions summarize the valid relation between successive elements of the iterator:

  • depth(0) = 0
    • since the first node of the depth-first traversal is the root
  • depth(i+1) < depth(i) is valid
    • we are moving from a leaf node with depth(i) to next child of one of its ancestors
  • depth(i+1) = depth(i) is valid
    • we are moving from a leaf node to its sibling which is immediately right to it
  • depth(i+1) = depth(i) + 1 is valid
    • we are moving from a non-leaf node to its first child

On the contrary, if either of the following two conditions hold, we cannot build a valid tree.

If either of these conditions hold, try_from or try_into methods will return the corresponding error instead of a valid tree.

§Examples

§Happy Paths

The following examples demonstrate the happy paths leading to successful collection of a tree from valid depth-first sequences.

use orx_tree::*;

// empty tree

let dfs = DepthFirstSequence::from([]);
let result: Result<DynTree<u32>, DepthFirstSequenceError> = dfs.try_into();
assert_eq!(result, Ok(Tree::empty()));

// non-empty tree

//      0
//     ╱ ╲
//    ╱   ╲
//   1     2
//  ╱     ╱ ╲
// 3     4   5
// |         |
// 6         7
let depth_value_pairs = [
    (0, 0),
    (1, 1),
    (2, 3),
    (3, 6),
    (1, 2),
    (2, 4),
    (2, 5),
    (3, 7),
];
let dfs = DepthFirstSequence::from(depth_value_pairs.clone());
let result: Result<DynTree<u32>, DepthFirstSequenceError> = dfs.try_into();

assert!(result.is_ok());
let tree = result.unwrap();

let bfs: Vec<_> = tree.root().walk::<Bfs>().copied().collect();
assert_eq!(bfs, [0, 1, 2, 3, 4, 5, 6, 7]);

// we can get back the dfs-sequence from constructed tree using walk_with

let mut t = Traversal.dfs().with_depth();
let dfs_back_from_tree: Vec<_> = tree
    .root()
    .walk_with(&mut t)
    .map(|(depth, val)| (depth, *val))
    .collect();
assert_eq!(dfs_back_from_tree, depth_value_pairs);

// we can construct back any fitting tree variant from the sequence

let result = DepthFirstSequence::from(dfs_back_from_tree).try_into();
assert!(result.is_ok());

let tree_back: BinaryTree<u32> = result.unwrap();
assert_eq!(tree, tree_back);

§Error Paths

The following examples illustrate the two potential error cases that can be observed due to the iterator not yielding a valid depth-first sequence.

use orx_tree::*;

// root with depth > 0

let dfs = DepthFirstSequence::from([(1, 1)]);
let result: Result<DynTree<u32>, DepthFirstSequenceError> = dfs.try_into();
assert_eq!(result, Err(DepthFirstSequenceError::NonZeroRootDepth));

// missing node (or forgotten depth) in the sequence

//       0
//      ╱ ╲
//     ╱   ╲
//    1     2
//   ╱     ╱ ╲
// ???    4   5
//  |         |
//  6         7
let depth_value_pairs = [
    (0, 0),
    (1, 1),
    // (2, 3), -> forgotten node leads to depth jump from 1 to 3
    (3, 6),
    (1, 2),
    (2, 4),
    (2, 5),
    (3, 7),
];
let dfs = DepthFirstSequence::from(depth_value_pairs.clone());
let result: Result<DynTree<u32>, DepthFirstSequenceError> = dfs.try_into();
assert_eq!(
    result,
    Err(DepthFirstSequenceError::DepthIncreaseGreaterThanOne {
        depth: 1,
        succeeding_depth: 3
    })
);

Trait Implementations§

Source§

impl<T: Clone, I> Clone for DepthFirstSequence<T, I>
where I: IntoIterator<Item = (usize, T)> + Clone,

Source§

fn clone(&self) -> DepthFirstSequence<T, I>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T, I> From<I> for DepthFirstSequence<T, I>
where I: IntoIterator<Item = (usize, T)>,

Source§

fn from(iter: I) -> Self

Converts to this type from the input type.
Source§

impl<I, V, M, P> TryFrom<DepthFirstSequence<<V as Variant>::Item, I>> for Tree<V, M, P>
where V: TreeVariant, M: MemoryPolicy, P: PinnedStorage, P::PinnedVec<V>: Default, I: IntoIterator<Item = (usize, V::Item)>,

Source§

fn try_from(value: DepthFirstSequence<V::Item, I>) -> Result<Self, Self::Error>

Tries to convert a depth-first sequence into a valid tree. Returns the corresponding DepthFirstSequenceError if the sequence is invalid.

Note that:

  • A DepthFirstSequence is just a wrapper of any IntoIterator<Item = (usize, T)> implementor that can be crated using the From trait => DepthFirstSequence::from([(0, "a"), (1, "b")]).
  • However, not all IntoIterator<Item = (usize, T)> instances represent a valid depth first sequence. Therefore, the conversion is fallible.
Source§

type Error = DepthFirstSequenceError

The type returned in the event of a conversion error.

Auto Trait Implementations§

§

impl<T, I> Freeze for DepthFirstSequence<T, I>
where I: Freeze,

§

impl<T, I> RefUnwindSafe for DepthFirstSequence<T, I>
where I: RefUnwindSafe,

§

impl<T, I> Send for DepthFirstSequence<T, I>
where I: Send,

§

impl<T, I> Sync for DepthFirstSequence<T, I>
where I: Sync,

§

impl<T, I> Unpin for DepthFirstSequence<T, I>
where I: Unpin,

§

impl<T, I> UnwindSafe for DepthFirstSequence<T, I>
where I: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> SoM<T> for T

Source§

fn get_ref(&self) -> &T

Returns a reference to self.
Source§

fn get_mut(&mut self) -> &mut T

Returns a mutable reference to self.
Source§

impl<T> SoR<T> for T

Source§

fn get_ref(&self) -> &T

Returns a reference to self.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.