1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use core::fmt;
5
6macro_rules! string_newtype {
7 ($(#[$meta:meta])* $name:ident) => {
8 $(#[$meta])*
9 #[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
10 pub struct $name(String);
11
12 impl $name {
13 pub fn new(value: impl Into<String>) -> Self {
15 Self(value.into())
16 }
17
18 pub fn as_str(&self) -> &str {
20 &self.0
21 }
22 }
23
24 impl AsRef<str> for $name {
25 fn as_ref(&self) -> &str {
26 self.as_str()
27 }
28 }
29
30 impl From<String> for $name {
31 fn from(value: String) -> Self {
32 Self::new(value)
33 }
34 }
35
36 impl From<&str> for $name {
37 fn from(value: &str) -> Self {
38 Self::new(value)
39 }
40 }
41
42 impl fmt::Display for $name {
43 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
44 formatter.write_str(self.as_str())
45 }
46 }
47 };
48}
49
50string_newtype! {
51 VertexId
53}
54string_newtype! {
55 EdgeId
57}
58string_newtype! {
59 VertexLabel
61}
62string_newtype! {
63 EdgeLabel
65}
66string_newtype! {
67 PropertyKey
69}
70string_newtype! {
71 PropertyValue
73}
74string_newtype! {
75 TraversalLabel
77}
78
79#[derive(Clone, Debug, Eq, Hash, PartialEq)]
81pub struct GraphProperty {
82 key: PropertyKey,
83 value: PropertyValue,
84}
85
86impl GraphProperty {
87 pub fn new(key: PropertyKey, value: PropertyValue) -> Self {
89 Self { key, value }
90 }
91
92 pub const fn key(&self) -> &PropertyKey {
94 &self.key
95 }
96
97 pub const fn value(&self) -> &PropertyValue {
99 &self.value
100 }
101}
102
103#[derive(Clone, Debug, Eq, PartialEq)]
105pub struct GraphVertex {
106 id: VertexId,
107 label: VertexLabel,
108 properties: Vec<GraphProperty>,
109}
110
111impl GraphVertex {
112 pub fn new(id: VertexId, label: VertexLabel) -> Self {
114 Self {
115 id,
116 label,
117 properties: Vec::new(),
118 }
119 }
120
121 pub fn with_property(mut self, property: GraphProperty) -> Self {
123 self.properties.push(property);
124 self
125 }
126
127 pub const fn id(&self) -> &VertexId {
129 &self.id
130 }
131
132 pub const fn label(&self) -> &VertexLabel {
134 &self.label
135 }
136
137 pub fn properties(&self) -> &[GraphProperty] {
139 &self.properties
140 }
141}
142
143#[derive(Clone, Debug, Eq, PartialEq)]
145pub struct GraphEdge {
146 id: EdgeId,
147 source: VertexId,
148 target: VertexId,
149 label: EdgeLabel,
150 properties: Vec<GraphProperty>,
151}
152
153impl GraphEdge {
154 pub fn new(id: EdgeId, source: VertexId, target: VertexId, label: EdgeLabel) -> Self {
156 Self {
157 id,
158 source,
159 target,
160 label,
161 properties: Vec::new(),
162 }
163 }
164
165 pub fn with_property(mut self, property: GraphProperty) -> Self {
167 self.properties.push(property);
168 self
169 }
170
171 pub const fn id(&self) -> &EdgeId {
173 &self.id
174 }
175
176 pub const fn source(&self) -> &VertexId {
178 &self.source
179 }
180
181 pub const fn target(&self) -> &VertexId {
183 &self.target
184 }
185
186 pub const fn label(&self) -> &EdgeLabel {
188 &self.label
189 }
190
191 pub fn properties(&self) -> &[GraphProperty] {
193 &self.properties
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use super::{
200 EdgeId, EdgeLabel, GraphEdge, GraphProperty, GraphVertex, PropertyKey, PropertyValue,
201 TraversalLabel, VertexId, VertexLabel,
202 };
203
204 #[test]
205 fn constructs_graph_store_labels() {
206 assert_eq!(VertexId::new("v1").to_string(), "v1");
207 assert_eq!(TraversalLabel::new("friends").as_ref(), "friends");
208 }
209
210 #[test]
211 fn builds_vertices_and_edges() {
212 let property = GraphProperty::new(PropertyKey::new("name"), PropertyValue::new("Ada"));
213 let vertex = GraphVertex::new(VertexId::new("person_1"), VertexLabel::new("Person"))
214 .with_property(property.clone());
215 let edge = GraphEdge::new(
216 EdgeId::new("edge_1"),
217 VertexId::new("person_1"),
218 VertexId::new("person_2"),
219 EdgeLabel::new("knows"),
220 )
221 .with_property(property);
222
223 assert_eq!(vertex.properties().len(), 1);
224 assert_eq!(edge.source().as_str(), "person_1");
225 assert_eq!(edge.properties().len(), 1);
226 }
227}