use crate::types::{Edge, Node, Path, Value};
#[derive(Debug, Clone)]
pub struct PathBuilder {
nodes: Vec<Node>,
edges: Vec<Edge>,
}
impl PathBuilder {
pub fn new(start_node: Node) -> Self {
Self {
nodes: vec![start_node],
edges: Vec::new(),
}
}
pub fn from_path(path: Path) -> Self {
Self {
nodes: path.nodes,
edges: path.edges,
}
}
pub fn add_hop(&mut self, edge: Edge, target: Node) {
self.edges.push(edge);
self.nodes.push(target);
}
pub fn current_node(&self) -> &Node {
self.nodes.last().expect("Path must have at least one node")
}
pub fn length(&self) -> usize {
self.edges.len()
}
pub fn build(self) -> Path {
Path {
nodes: self.nodes,
edges: self.edges,
}
}
pub fn build_value(self) -> Value {
Value::Path(self.build())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
use uni_common::core::id::{Eid, Vid};
fn make_node(vid: u64, label: &str, name: &str) -> Node {
let mut properties = HashMap::new();
properties.insert("name".to_string(), Value::String(name.to_string()));
Node {
vid: Vid::new(vid),
labels: vec![label.to_string()],
properties,
}
}
fn make_edge(eid: u64, edge_type: &str, src: u64, dst: u64) -> Edge {
Edge {
eid: Eid::new(eid),
edge_type: edge_type.to_string(),
src: Vid::new(src),
dst: Vid::new(dst),
properties: HashMap::new(),
}
}
#[test]
fn test_path_builder_single_hop() {
let node_a = make_node(1, "Person", "Alice");
let node_b = make_node(2, "Person", "Bob");
let edge_r = make_edge(100, "KNOWS", 1, 2);
let mut builder = PathBuilder::new(node_a.clone());
builder.add_hop(edge_r.clone(), node_b.clone());
let path = builder.build();
assert_eq!(path.nodes.len(), 2);
assert_eq!(path.edges.len(), 1);
assert_eq!(path.nodes[0].vid, Vid::new(1));
assert_eq!(path.nodes[1].vid, Vid::new(2));
assert_eq!(path.edges[0].eid, Eid::new(100));
}
#[test]
fn test_path_builder_multi_hop() {
let node_a = make_node(1, "Person", "Alice");
let node_b = make_node(2, "Person", "Bob");
let node_c = make_node(3, "Person", "Charlie");
let edge_r1 = make_edge(100, "KNOWS", 1, 2);
let edge_r2 = make_edge(101, "KNOWS", 2, 3);
let mut builder = PathBuilder::new(node_a.clone());
builder.add_hop(edge_r1.clone(), node_b.clone());
builder.add_hop(edge_r2.clone(), node_c.clone());
let path = builder.build();
assert_eq!(path.nodes.len(), 3);
assert_eq!(path.edges.len(), 2);
assert_eq!(path.nodes[0].vid, Vid::new(1));
assert_eq!(path.nodes[1].vid, Vid::new(2));
assert_eq!(path.nodes[2].vid, Vid::new(3));
assert_eq!(path.edges[0].eid, Eid::new(100));
assert_eq!(path.edges[1].eid, Eid::new(101));
}
#[test]
fn test_path_extension() {
let node_a = make_node(1, "Person", "Alice");
let node_b = make_node(2, "Person", "Bob");
let node_c = make_node(3, "Person", "Charlie");
let edge_r1 = make_edge(100, "KNOWS", 1, 2);
let edge_r2 = make_edge(101, "KNOWS", 2, 3);
let initial_path = Path {
nodes: vec![node_a.clone(), node_b.clone()],
edges: vec![edge_r1.clone()],
};
let mut builder = PathBuilder::from_path(initial_path);
builder.add_hop(edge_r2.clone(), node_c.clone());
let path = builder.build();
assert_eq!(path.nodes.len(), 3);
assert_eq!(path.edges.len(), 2);
}
#[test]
fn test_current_node() {
let node_a = make_node(1, "Person", "Alice");
let node_b = make_node(2, "Person", "Bob");
let edge_r = make_edge(100, "KNOWS", 1, 2);
let mut builder = PathBuilder::new(node_a.clone());
assert_eq!(builder.current_node().vid, Vid::new(1));
builder.add_hop(edge_r, node_b.clone());
assert_eq!(builder.current_node().vid, Vid::new(2));
}
#[test]
fn test_path_length() {
let node_a = make_node(1, "Person", "Alice");
let node_b = make_node(2, "Person", "Bob");
let node_c = make_node(3, "Person", "Charlie");
let edge_r1 = make_edge(100, "KNOWS", 1, 2);
let edge_r2 = make_edge(101, "KNOWS", 2, 3);
let mut builder = PathBuilder::new(node_a.clone());
assert_eq!(builder.length(), 0);
builder.add_hop(edge_r1, node_b.clone());
assert_eq!(builder.length(), 1);
builder.add_hop(edge_r2, node_c.clone());
assert_eq!(builder.length(), 2);
}
#[test]
fn test_build_value() {
let node_a = make_node(1, "Person", "Alice");
let node_b = make_node(2, "Person", "Bob");
let edge_r = make_edge(100, "KNOWS", 1, 2);
let mut builder = PathBuilder::new(node_a);
builder.add_hop(edge_r, node_b);
let value = builder.build_value();
match value {
Value::Path(path) => {
assert_eq!(path.nodes.len(), 2);
assert_eq!(path.edges.len(), 1);
}
_ => panic!("Expected Value::Path"),
}
}
}