use std::collections::HashMap;
use super::Value;
use crate::proto;
#[derive(Debug, Clone, PartialEq)]
pub struct Edge {
pub id: Vec<u8>,
pub labels: Vec<String>,
pub source_node_id: Vec<u8>,
pub target_node_id: Vec<u8>,
pub undirected: bool,
pub properties: HashMap<String, Value>,
}
impl Edge {
#[must_use]
pub fn directed(
id: impl Into<Vec<u8>>,
source: impl Into<Vec<u8>>,
target: impl Into<Vec<u8>>,
) -> Self {
Self {
id: id.into(),
labels: Vec::new(),
source_node_id: source.into(),
target_node_id: target.into(),
undirected: false,
properties: HashMap::new(),
}
}
#[must_use]
pub fn undirected(
id: impl Into<Vec<u8>>,
endpoint_a: impl Into<Vec<u8>>,
endpoint_b: impl Into<Vec<u8>>,
) -> Self {
Self {
id: id.into(),
labels: Vec::new(),
source_node_id: endpoint_a.into(),
target_node_id: endpoint_b.into(),
undirected: true,
properties: HashMap::new(),
}
}
#[must_use]
pub fn with_label(mut self, label: impl Into<String>) -> Self {
self.labels.push(label.into());
self
}
#[must_use]
pub fn with_property(mut self, name: impl Into<String>, value: impl Into<Value>) -> Self {
self.properties.insert(name.into(), value.into());
self
}
#[must_use]
pub fn property(&self, name: &str) -> Option<&Value> {
self.properties.get(name)
}
}
impl From<proto::Edge> for Edge {
fn from(p: proto::Edge) -> Self {
Self {
id: p.id,
labels: p.labels,
source_node_id: p.source_node_id,
target_node_id: p.target_node_id,
undirected: p.undirected,
properties: p
.properties
.into_iter()
.map(|(k, v)| (k, Value::from(v)))
.collect(),
}
}
}
impl From<Edge> for proto::Edge {
fn from(e: Edge) -> Self {
Self {
id: e.id,
labels: e.labels,
source_node_id: e.source_node_id,
target_node_id: e.target_node_id,
undirected: e.undirected,
properties: e
.properties
.into_iter()
.map(|(k, v)| (k, proto::Value::from(v)))
.collect(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn directed_edge() {
let edge = Edge::directed(vec![0x10], vec![0x01], vec![0x02])
.with_label("knows")
.with_property("since", 2020_i64);
assert!(!edge.undirected);
assert_eq!(edge.labels, vec!["knows"]);
assert_eq!(edge.property("since"), Some(&Value::Integer(2020)));
}
#[test]
fn undirected_edge() {
let edge = Edge::undirected(vec![0x10], vec![0x01], vec![0x02]).with_label("friends_with");
assert!(edge.undirected);
}
#[test]
fn round_trip() {
let edge = Edge::directed(vec![0x10], vec![0x01], vec![0x02])
.with_label("knows")
.with_property("weight", 0.5_f64);
let proto_edge: proto::Edge = edge.clone().into();
let back: Edge = proto_edge.into();
assert_eq!(edge, back);
}
}