Extract from limo mono repo commit 6d5297c814588061ba58ec4b40f5e377956b1fe5.
This commit is contained in:
commit
ef90912bfa
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "limbo_graph"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# limbo_graph
|
||||
|
||||
An implementation of a directed graph in Rust.
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
//
|
||||
// Copyright 2023 James Pace
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
// defined by the Mozilla Public License, v. 2.0.
|
||||
//
|
||||
#![no_std]
|
||||
extern crate alloc;
|
||||
mod node;
|
||||
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
pub use node::*;
|
||||
|
||||
/// A generic graph type holding values connected to other values.
|
||||
/// Values can be added to the graph, but not removed.
|
||||
pub struct Graph<NodeValueT: NodeValue> {
|
||||
nodes: Vec<Node<NodeValueT>>,
|
||||
}
|
||||
|
||||
impl<NodeValueT: NodeValue> Graph<NodeValueT> {
|
||||
/// Make a new graph with a root node with value `root`.
|
||||
pub fn new(root: NodeValueT) -> Self {
|
||||
// Make root node from its value.
|
||||
let root_node = Node::new(root, None);
|
||||
// Make graph with root_node as the one value in the vec.
|
||||
Graph {
|
||||
nodes: vec![root_node],
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a child wth value `val` to the parent with Key `parent`.
|
||||
/// If the parent key is not in the graph, returns an error.
|
||||
/// Returns a result with the key of the new node or an error.
|
||||
pub fn add(&mut self, val: NodeValueT, parent: Key) -> Result<Key, GraphError> {
|
||||
// Make sure parent is valid.
|
||||
if parent >= self.nodes.len() {
|
||||
return Err(GraphError::from_msg("Parent node not in graph."));
|
||||
}
|
||||
// Add new node to graph, get it's key.
|
||||
let new_node = Node::new(val, Some(parent));
|
||||
self.nodes.push(new_node.clone());
|
||||
let new_node_key = self.nodes.len() - 1;
|
||||
// Add it's key to parent's children.
|
||||
self.nodes[parent].add_child(new_node_key);
|
||||
Ok(new_node_key)
|
||||
}
|
||||
|
||||
/// Get the value of key `key` if the key is valid.
|
||||
pub fn value_of(&self, key: &Key) -> Result<NodeValueT, GraphError> {
|
||||
if key >= &self.nodes.len() {
|
||||
return Err(GraphError::from_msg("Can't get value of invalid key."));
|
||||
}
|
||||
Ok(self.nodes[*key].value())
|
||||
}
|
||||
|
||||
/// Get the children (as a list of keys) of key `key` if the key is valid.
|
||||
pub fn children_of(&self, key: &Key) -> Result<Vec<Key>, GraphError> {
|
||||
if key >= &self.nodes.len() {
|
||||
return Err(GraphError::from_msg("Can't get children of invalid key."));
|
||||
}
|
||||
Ok(self.nodes[*key].children())
|
||||
}
|
||||
|
||||
/// Get the parent of key `key` if the key is valid.
|
||||
/// Will return None if the node at `key` as no parent (i.e. is the root node).
|
||||
pub fn parent_of(&self, key: &Key) -> Result<Option<Key>, GraphError> {
|
||||
if key >= &self.nodes.len() {
|
||||
return Err(GraphError::from_msg("Can't get parent of invalid key."));
|
||||
}
|
||||
Ok(self.nodes[*key].parent())
|
||||
}
|
||||
|
||||
/// Get the key for the root of the graph.
|
||||
pub fn root_key(&self) -> Key {
|
||||
// This is always 0.
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GraphError {
|
||||
pub msg: String,
|
||||
}
|
||||
|
||||
impl GraphError {
|
||||
pub fn from_msg(msg: &str) -> Self {
|
||||
GraphError {
|
||||
msg: msg.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for GraphError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "Error manipulating graph: {}", self.msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::error::Error for GraphError {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use core::cmp::PartialEq;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
struct NodeType {
|
||||
pub x: f64,
|
||||
}
|
||||
impl NodeValue for NodeType {}
|
||||
impl NodeType {
|
||||
fn new(val: f64) -> Self {
|
||||
NodeType { x: val }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn node_manipulation() {
|
||||
let mut node = Node::new(NodeType::new(1.0), None);
|
||||
assert!(node.parent().is_none());
|
||||
assert!(node.value() == NodeType::new(1.0));
|
||||
let child_key: Key = 1;
|
||||
node.add_child(child_key.clone());
|
||||
assert!(node.children().len() == 1);
|
||||
assert!(node.children()[0] == child_key);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn graph_manipulation() {
|
||||
let root_val = NodeType::new(1.0);
|
||||
let mut graph = Graph::new(root_val);
|
||||
|
||||
let second_val = NodeType::new(2.0);
|
||||
let second_add_res = graph.add(second_val, 0);
|
||||
assert!(second_add_res.is_ok());
|
||||
assert!(second_add_res.unwrap() == 1);
|
||||
|
||||
assert!(graph.value_of(&1).unwrap() == NodeType::new(2.0));
|
||||
assert!(graph.parent_of(&1).unwrap() == Some(0));
|
||||
assert!(graph.children_of(&1).unwrap().len() == 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// Copyright 2023 James Pace
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
// defined by the Mozilla Public License, v. 2.0.
|
||||
//
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
pub type Key = usize;
|
||||
|
||||
pub trait NodeValue: Clone {}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Node<NodeValueT: NodeValue> {
|
||||
value: NodeValueT,
|
||||
children: Vec<Key>,
|
||||
parent: Option<Key>,
|
||||
}
|
||||
|
||||
impl<NodeValueT: NodeValue> Node<NodeValueT> {
|
||||
pub fn new(value: NodeValueT, parent: Option<Key>) -> Self {
|
||||
Node {
|
||||
value: value,
|
||||
children: vec![],
|
||||
parent: parent,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_child(&mut self, child_key: Key) {
|
||||
self.children.push(child_key);
|
||||
}
|
||||
|
||||
pub fn children(&self) -> Vec<Key> {
|
||||
self.children.clone()
|
||||
}
|
||||
|
||||
pub fn parent(&self) -> Option<Key> {
|
||||
self.parent.clone()
|
||||
}
|
||||
|
||||
pub fn value(&self) -> NodeValueT {
|
||||
self.value.clone()
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue