bag/
lib.rs

1//! # Bag
2//! `bag` is a simple, insert only graph. It is simple to understand conceptually, and modify if needed.
3//! Data is represented as `NodeID`s, which can be used to retrieve pointers to `Node`s stored in the `GraphStore`.
4//! These `Node`s point to their parents and children by holding their `NodeID`s.
5//! These `Node`s also hold a datatype `<T>` (the type of the node and graph), which you can use to store your program
6//! specific data.
7
8pub type NodeID = usize;
9
10///
11/// A generic container for a node
12///
13/// A `Node<T>` contains the following:
14///     - An optional identifier for a parent `Node<T>`
15///     - A `Vec` of identifiers for children `Node<T>`s
16///     - A publicly visible member of type `T` to hold program specific data
17///
18#[derive(Debug)]
19pub struct Node<T> {
20    parent: Option<NodeID>,
21    children: Vec<NodeID>,
22    pub data: T,
23}
24
25impl<T> Node<T> {
26    ///
27    /// Constructs a new `Node<T>`
28    ///
29    /// Accepts the node's data of type `T`. By default,
30    /// `Node<T>`s have no parent, this is set on insertion
31    /// into the graph.
32    ///
33    /// # Example
34    ///
35    /// ```
36    /// use bag::Node;
37    /// #[derive(Debug,Eq,PartialEq)]
38    /// struct InternalData {
39    ///     name: String,
40    ///     id: i32
41    /// }
42    /// let node = Node::new(InternalData{name: "NodeTest".to_string(), id: 42});
43    /// assert_eq!(*node.parent(), None);
44    /// assert_eq!(*node.children(), Vec::new());
45    /// assert_eq!(node.data, InternalData{name: "NodeTest".to_string(), id:42});
46    /// ```
47    ///
48    pub fn new(data: T) -> Self {
49        Node { parent: None, children: Vec::new(), data }
50    }
51    pub fn parent(&self) -> &Option<NodeID> {
52        &self.parent
53    }
54    pub fn children(&self) -> &Vec<NodeID> {
55        &self.children
56    }
57}
58
59///
60/// A generic container for a graph
61///
62/// A `GraphStore<T>` is a struct that contains the actual graph representation.
63/// Try not to loose it.
64///
65///
66/// # Example
67///
68/// ```
69/// use bag::{GraphStore, Node};
70/// let root_node = Node::new("String".to_string());
71/// let (mut graph, root_node_id) = GraphStore::new(root_node);
72/// assert_eq!(*graph.get(root_node_id).unwrap().parent(), None);
73/// ```
74///
75#[derive(Debug)]
76pub struct GraphStore<T> {
77    graph: Vec<Node<T>>
78}
79
80impl<T> GraphStore<T> {
81    ///
82    /// Constructs a new `GraphStore<T>` and handle to the root `Node<T>`
83    ///
84    /// Accepts a root node of type `Node<T>` (this is the only node held in the graph that can have a `None`
85    /// for it's parent (though it may have a `Some(parent)` if the graph is cyclic at the root.
86    ///
87    pub fn new(root_node: Node<T>) -> (Self, NodeID) {
88        let mut tree = GraphStore { graph: Vec::new() };
89        let root_nodeid = tree.insert(root_node);
90        (tree, root_nodeid)
91    }
92
93    ///
94    /// Returns an option with a reference to the node represented by `NodeID`, if found
95    ///
96    /// `get` searches the `GraphStore<T>` for a node with the `NodeID` passed as `node`.
97    /// If it is found, a non-mutable reference to it is returned in a `Some`, otherwise a `None` is returned.
98    pub fn get(&self, node: NodeID) -> Option<&Node<T>> {
99        self.graph.get(node)
100    }
101
102    ///
103    /// Returns an option with a mutable reference to the node represented by `NodeID`, if found
104    ///
105    /// `get_mut` searches the `GraphStore<T>` for a node with the `NodeID` passed as `node`.
106    /// If it is found, a mutable reference to it is returned in a `Some`, otherwise a `None` is returned.
107    pub fn get_mut(&mut self, node: NodeID) -> Option<&mut Node<T>> {
108        self.graph.get_mut(node)
109    }
110
111    ///
112    /// Returns an option with a reference to a Vec of a `Node<T>`s sublings, if found
113    ///
114    /// `get_siblings_id` searches the `GraphStore<T>` for a node with the `NodeID` passed as `node`.
115    /// If it is found, a non-mutable reference to it's parent's children is returned in a `Some`, otherwise a `None` is returned.
116    /// Note that `node` is itself included in the returned `Vec<NodeID>`.
117    pub fn get_siblings_id(&self, node: NodeID) -> Option<&Vec<NodeID>> {
118        match self.get(node) {
119            Some(node) => {
120                match node.parent {
121                    Some(parent_id) => Some(self.get(parent_id).unwrap().children()),
122                    None => return None
123                }
124            }
125            None => None
126        }
127    }
128    /*
129        Inserts a node into the tree and returns it's `NodeID`
130    */
131    fn insert(&mut self, node: Node<T>) -> NodeID {
132        self.graph.push(node);
133        self.graph.len() - 1
134    }
135    ///
136    /// Inserts a node into the graph
137    ///
138    /// `insert_child` accepts a parent `NodeID` and takes ownership of an inserted `Node<T>`.
139    /// If the parent `NodeID` is valid, the `Node<T>` is inserted into the graph. The child's parent
140    /// pointer is then set to the `NodeID` of the parent, and the parent's child `Vec<NodeID` is updated
141    /// to include the `NodeID` of the child. Returns a `Result<NodeID, &'static str` representing success or failure
142    /// of the insertion.
143    pub fn insert_child(&mut self, parent_id: &NodeID, mut inserted: Node<T>) -> Result<NodeID, &'static str> {
144        /*
145            This is an unusual piece of code, but seems to be the simplest way to get around mutable and immutable borrows.
146            The tree_len is the index of the item to be inserted (because the item is not yet inserted, and the Vec<Node<T>> is 0 indexed).
147            Once this is immutable held in tree_len, we can mutably borrow the Vec to insert the element into the parent node.
148            We then insert the child into the Vec<Node<T>>.
149        */
150        let tree_len = self.graph.len();
151        match self.get_mut(*parent_id) {
152            Some(parent) => {
153                inserted.parent = Some(*parent_id);
154                parent.children.push(tree_len)
155            }
156            None => return Err("Parent not found by NodeID")
157        };
158        self.insert(inserted);
159        Ok(tree_len)
160    }
161}
162
163#[cfg(test)]
164mod tests {
165    #[test]
166    fn create_new_node_and_test_invariants() {
167        use Node;
168        #[derive(Debug, Eq, PartialEq)]
169        struct InternalData {
170            name: String,
171            id: i32,
172        }
173        let node = Node::new(InternalData { name: "NodeTest".to_string(), id: 42 });
174        assert_eq!(*node.parent(), None);
175        assert_eq!(*node.children(), Vec::new());
176        assert_eq!(node.data, InternalData { name: "NodeTest".to_string(), id: 42 });
177    }
178
179    #[test]
180    fn create_new_graph_store_and_test_invariants() {
181        use {GraphStore, Node};
182        let root_node = Node::new("String".to_string());
183        let (graph, root_node_id) = GraphStore::new(root_node);
184        assert_eq!(*graph.get(root_node_id).unwrap().parent(), None);
185    }
186}