#![forbid(unsafe_code)]
#![doc = include_str!("../README.md")]
use core::fmt;
macro_rules! string_newtype {
($(#[$meta:meta])* $name:ident) => {
$(#[$meta])*
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct $name(String);
impl $name {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl AsRef<str> for $name {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl From<String> for $name {
fn from(value: String) -> Self {
Self::new(value)
}
}
impl From<&str> for $name {
fn from(value: &str) -> Self {
Self::new(value)
}
}
impl fmt::Display for $name {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.as_str())
}
}
};
}
string_newtype! {
VertexId
}
string_newtype! {
EdgeId
}
string_newtype! {
VertexLabel
}
string_newtype! {
EdgeLabel
}
string_newtype! {
PropertyKey
}
string_newtype! {
PropertyValue
}
string_newtype! {
TraversalLabel
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct GraphProperty {
key: PropertyKey,
value: PropertyValue,
}
impl GraphProperty {
pub fn new(key: PropertyKey, value: PropertyValue) -> Self {
Self { key, value }
}
pub const fn key(&self) -> &PropertyKey {
&self.key
}
pub const fn value(&self) -> &PropertyValue {
&self.value
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct GraphVertex {
id: VertexId,
label: VertexLabel,
properties: Vec<GraphProperty>,
}
impl GraphVertex {
pub fn new(id: VertexId, label: VertexLabel) -> Self {
Self {
id,
label,
properties: Vec::new(),
}
}
pub fn with_property(mut self, property: GraphProperty) -> Self {
self.properties.push(property);
self
}
pub const fn id(&self) -> &VertexId {
&self.id
}
pub const fn label(&self) -> &VertexLabel {
&self.label
}
pub fn properties(&self) -> &[GraphProperty] {
&self.properties
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct GraphEdge {
id: EdgeId,
source: VertexId,
target: VertexId,
label: EdgeLabel,
properties: Vec<GraphProperty>,
}
impl GraphEdge {
pub fn new(id: EdgeId, source: VertexId, target: VertexId, label: EdgeLabel) -> Self {
Self {
id,
source,
target,
label,
properties: Vec::new(),
}
}
pub fn with_property(mut self, property: GraphProperty) -> Self {
self.properties.push(property);
self
}
pub const fn id(&self) -> &EdgeId {
&self.id
}
pub const fn source(&self) -> &VertexId {
&self.source
}
pub const fn target(&self) -> &VertexId {
&self.target
}
pub const fn label(&self) -> &EdgeLabel {
&self.label
}
pub fn properties(&self) -> &[GraphProperty] {
&self.properties
}
}
#[cfg(test)]
mod tests {
use super::{
EdgeId, EdgeLabel, GraphEdge, GraphProperty, GraphVertex, PropertyKey, PropertyValue,
TraversalLabel, VertexId, VertexLabel,
};
#[test]
fn constructs_graph_store_labels() {
assert_eq!(VertexId::new("v1").to_string(), "v1");
assert_eq!(TraversalLabel::new("friends").as_ref(), "friends");
}
#[test]
fn builds_vertices_and_edges() {
let property = GraphProperty::new(PropertyKey::new("name"), PropertyValue::new("Ada"));
let vertex = GraphVertex::new(VertexId::new("person_1"), VertexLabel::new("Person"))
.with_property(property.clone());
let edge = GraphEdge::new(
EdgeId::new("edge_1"),
VertexId::new("person_1"),
VertexId::new("person_2"),
EdgeLabel::new("knows"),
)
.with_property(property);
assert_eq!(vertex.properties().len(), 1);
assert_eq!(edge.source().as_str(), "person_1");
assert_eq!(edge.properties().len(), 1);
}
}