1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
//! Navigate around a [`Kserd`].
//!
//! # Reading
//! It is cumbersome when trying to loop through a nested `Kserd` structure. There is a [`Navigator`]
//! structure that can be used that flattens the tree structure when constructed to make use of
//! indexing and iterators throughout the `Kserd`.
//!
//! [`Kserd`]: crate::Kserd
//! [`Navigator`]: crate::nav::Navigator
// TODO: Lifetimes should be scoped to the borrowed kserd as much as possible.
// TODO: Can probably remove the 'node lifetime, as it is borrowed from the Navigator
use super::*;

mod navigator;
mod node;
mod value;

/// A structure to efficiently navigate through a [`Kserd`].
///
/// When trying to interrogate a `Kserd` it can become cumbersome to loop through nested children.
/// The `Navigator` provides a structure around a root `Kserd` which then allows for efficient
/// looping through the structure.
///
/// When a `Navigator` is constructed it flattens the tree structure into a depth-first vector,
/// wrapping each `Kserd` into a [`Node`] which contains navigational information such are parent
/// or children.
///
/// [`Kserd`]: crate::Kserd
/// [`Node`]: crate::nav::Node
pub struct Navigator<'a, 'k> {
    inner: Vec<NodeInner<'a, 'k>>,
}

/// A node in the [`Kserd`] tree.
///
/// A `Node` wraps a pointer to the `Kserd` value, and carries positional information about itself
/// and surrounding family. As such `Node`s can walk the tree structures, and have uses when
/// interrogating a `Kserd` data structure.
///
/// Since a `Node` carries a reference to the `Navigator` and the `Kserd`, it is a read-only
/// structure and no mutation can occur.
///
/// [`Kserd`]: crate::Kserd
#[derive(Copy, Clone)]
pub struct Node<'a, 'k, 'nav, 'node> {
    nav: &'nav Navigator<'a, 'k>,
    node: &'node NodeInner<'a, 'k>,
}

struct NodeInner<'a, 'k> {
    kserd: &'a Kserd<'k>,
    idx: usize,
    parent: Option<usize>,
    value_idx_in_parent: Option<usize>,
    key_idx_in_parent: Option<usize>,
    value_children: Vec<usize>,
    key_children: Vec<usize>,
}

/// The node's value type.
///
/// Differs to [`Value`] in that it groups primitives, and provides
/// iterators over nested `Kserd`s that themselves return `Node`s, such that position information
/// is retained if walking through a `Kserd`.
///
/// [`Value`]: crate::Value
pub enum NodeValue<'a, 'k, 'nav, 'node> {
    /// A primitive value.
    Primitive,
    /// A tuple value.
    Tuple(SeqIter<'a, 'k, 'nav, 'node>),
    /// A container value.
    Cntr(NamedIter<'a, 'k, 'nav, 'node>),
    /// A sequence value.
    Seq(SeqIter<'a, 'k, 'nav, 'node>),
    /// A map value.
    Map(KeyedIter<'a, 'k, 'nav, 'node>),
}

/// Iterator of nodes.
pub struct NodeIter<'a, 'k, 'nav> {
    iter: std::slice::Iter<'nav, NodeInner<'a, 'k>>,
    nav: &'nav Navigator<'a, 'k>,
}

/// Iterator for sequential items like sequences.
/// Can be used for keys of maps as well.
pub struct SeqIter<'a, 'k, 'nav, 'node> {
    seq: std::slice::Iter<'node, usize>,
    nav: &'nav Navigator<'a, 'k>,
}

/// Iterator for named items like in containers.
pub struct NamedIter<'a, 'k, 'nav, 'node> {
    names: std::collections::btree_map::Keys<'node, Kstr<'k>, Kserd<'k>>,
    values: std::slice::Iter<'node, usize>,
    nav: &'nav Navigator<'a, 'k>,
}

/// Iterator for keyed items like in maps.
pub struct KeyedIter<'a, 'k, 'nav, 'node> {
    keys: std::slice::Iter<'node, usize>,
    values: std::slice::Iter<'node, usize>,
    nav: &'nav Navigator<'a, 'k>,
}