Skip to main content

cairn_knowledge_graph/graph/
vertex.rs

1use crate::error::GraphComputingError;
2use crate::error::{LogicError, LogicErrorType};
3use crate::error::{SystemError, SystemErrorType};
4use crate::graph::graph::Graph;
5
6use super::graph::ElementIndex;
7
8pub type VertexKey = String;
9pub type VertexKeyRef = str;
10
11// Use a struct instead of a type to discourage using and/or generating indices that are not coming from the pblic API.
12#[derive(Clone, Copy, Debug, PartialEq)]
13pub struct VertexIndex {
14    index: ElementIndex,
15}
16
17impl VertexIndex {
18    pub(crate) fn new(index: ElementIndex) -> Self {
19        VertexIndex { index }
20    }
21    pub(crate) fn index(self) -> ElementIndex {
22        self.index
23    }
24    pub(crate) fn index_ref(&self) -> &ElementIndex {
25        &self.index
26    }
27}
28
29// TODO: Implementation leaks VertexIndex instantiation out of pub(crate) scope
30// impl From<ElementIndex> for VertexIndex {
31//     fn from(index: ElementIndex) -> Self {
32//         VertexIndex::new(index)
33//     }
34// }
35// impl From<VertexIndex> for ElementIndex {
36//     fn from(index: VertexIndex) -> Self {
37//         index.index()
38//     }
39// }
40
41// TODO: implementation implies Vertices from different graphs can be equal.
42// TODO: The implementation defines a Vertex coordindate defined by a key.
43// Whereas the coordinate can be a key, or an index. Is this struct a
44// consistent definition of a Vertex?
45#[derive(Clone, Debug, PartialEq, PartialOrd)]
46pub struct Vertex {
47    key: VertexKey,
48    value: VertexValue,
49}
50
51impl From<Vertex> for VertexKey {
52    fn from(vertex: Vertex) -> Self {
53        vertex.key_ref().to_owned()
54    }
55}
56
57/// ```
58/// # use cairn_knowledge_graph::graph::vertex::Vertex;
59/// let vertex: Vertex = (String::from("Vertex key"), 1u8.into()).into();
60/// assert_eq!(vertex.key_ref().to_owned(), String::from("Vertex key"));
61/// assert_eq!(vertex.value(), 1u8.into());
62/// ```
63impl From<(VertexKey, VertexValue)> for Vertex {
64    fn from(as_tuple: (VertexKey, VertexValue)) -> Self {
65        Vertex::new(as_tuple.0, as_tuple.1)
66    }
67}
68
69// REVIEW: if a StoredVertex takes about a much space as a VertexProperty,
70// then the IndexDataStorage doesn't bring a benefit.
71// pub(crate) struct StoredVertex {
72//     store_index: StoreIndex, // a pointer has the same size as usize (~8byte)
73//     vertex_property_type: VertexPropertyType, // enum of size isize (~8byte)
74// }
75// in total, StoredVertex takes 16 bytes, the same as a VertexProperty. Thereby,
76// the use of an IndexedDataStore could only be efficient if data is stored with a larger size.
77
78impl Vertex {
79    pub fn new(key: VertexKey, value: VertexValue) -> Self {
80        Self { key, value }
81    }
82    // pub fn key(&self) -> &VertexKey {
83    //     &self.key
84    // }
85    pub fn key_ref(&self) -> &VertexKeyRef {
86        &self.key
87    }
88    pub fn value_ref(&self) -> &VertexValue {
89        &self.value
90    }
91    pub fn value(self) -> VertexValue {
92        self.value
93    }
94
95    pub fn update_value(&mut self, new_value: VertexValue) {
96        self.value = new_value;
97    }
98    pub fn update_key(&mut self, new_key: VertexKey) {
99        self.key = new_key;
100    }
101
102    // TO REVIEW: converting Vertex to an enum would make the vertex immutable, but introduce runtime cost
103    // It should not be possible to access/reach a deleted vertex
104    // pub(crate) fn mark_as_removed(&mut self) {
105    //     self.key = String::from("_deleted");
106    //     self.value = VertexValue::None;
107    // }
108}
109
110#[derive(Clone, Debug, PartialEq, PartialOrd)]
111pub enum VertexValueType {
112    None, // TODO: is this useful, necessary, and a good idea?
113    String,
114    Boolean,
115    Integer8Bit,
116    Integer16Bit,
117    Integer32Bit,
118    Integer64Bit,
119    Integer128Bit,
120    UnsignedInteger8Bit,
121    UnsignedInteger16Bit,
122    UnsignedInteger32Bit,
123    UnsignedInteger64Bit,
124    UnsignedInteger128Bit,
125    FloatingPoint32Bit,
126    FloatingPoint64Bit,
127}
128
129#[derive(Clone, Debug, PartialEq, PartialOrd)]
130pub enum VertexValue {
131    None, // REVIEW: is this useful, necessary, and a good idea?
132    String(String),
133    Boolean(bool),
134    Integer8Bit(i8),
135    Integer16Bit(i16),
136    Integer32Bit(i32),
137    Integer64Bit(i64),
138    Integer128Bit(i128),
139    UnsignedInteger8Bit(u8),
140    UnsignedInteger16Bit(u16),
141    UnsignedInteger32Bit(u32),
142    UnsignedInteger64Bit(u64),
143    UnsignedInteger128Bit(u128),
144    FloatingPoint32Bit(f32),
145    FloatingPoint64Bit(f64),
146}
147
148macro_rules! implement_from_type {
149    ($value_type:ty, $vertex_property_enum_value:ident) => {
150        impl From<$value_type> for VertexValue {
151            fn from(item: $value_type) -> Self {
152                VertexValue::$vertex_property_enum_value(item)
153            }
154        }
155    };
156}
157
158implement_from_type!(String, String);
159implement_from_type!(bool, Boolean);
160implement_from_type!(i8, Integer8Bit);
161implement_from_type!(i16, Integer16Bit);
162implement_from_type!(i32, Integer32Bit);
163implement_from_type!(i64, Integer64Bit);
164implement_from_type!(i128, Integer128Bit);
165implement_from_type!(u8, UnsignedInteger8Bit);
166implement_from_type!(u16, UnsignedInteger16Bit);
167implement_from_type!(u32, UnsignedInteger32Bit);
168implement_from_type!(u64, UnsignedInteger64Bit);
169implement_from_type!(u128, UnsignedInteger128Bit);
170implement_from_type!(f32, FloatingPoint32Bit);
171implement_from_type!(f64, FloatingPoint64Bit);
172
173pub trait VertexKeyAndIndexConversion {
174    fn vertex_index_to_vertex_key_ref(
175        &self,
176        vertex_index: VertexIndex,
177    ) -> Result<&VertexKeyRef, GraphComputingError>;
178
179    fn vertex_key_ref_to_vertex_index_ref(
180        &self,
181        key: &VertexKeyRef,
182    ) -> Result<&VertexIndex, GraphComputingError>;
183}
184
185impl VertexKeyAndIndexConversion for Graph {
186    fn vertex_index_to_vertex_key_ref(
187        &self,
188        vertex_index: VertexIndex,
189    ) -> Result<&VertexKeyRef, GraphComputingError> {
190        match self.vertex_store_ref().get_ref(vertex_index) {
191            Ok(vertex) => return Ok(vertex.key_ref()),
192            Err(_) => {
193                // TODO:match actual error type
194                return Err(LogicError::new(
195                    LogicErrorType::VertexMustExist,
196                    format!("There is no vertex at index [{}]", vertex_index.index()),
197                    None,
198                )
199                .into());
200            }
201        }
202    }
203
204    fn vertex_key_ref_to_vertex_index_ref(
205        &self,
206        key: &VertexKeyRef,
207    ) -> Result<&VertexIndex, GraphComputingError> {
208        match self.vertex_key_to_vertex_index_map_ref().get(key) {
209            None => Err(SystemError::new(
210                SystemErrorType::KeyNotFound,
211                format!("Could not map vertex key '{}' to a vertex index", key),
212                None,
213            )
214            .into()),
215            Some(vertex_index) => Ok(vertex_index),
216        }
217    }
218}
219
220#[cfg(test)]
221mod tests {
222    use super::*;
223
224    use crate::operations::add_vertex::AddVertex;
225
226    #[test]
227    fn test_convert_vertex_index_to_vertex_key_ref() {
228        let mut graph = Graph::new(10, 20).unwrap();
229
230        let vertex_key_1 = String::from("Vertex_1");
231        let vertex_value_1 = String::from("Property_1");
232        let vertex_1 = Vertex::new(vertex_key_1.clone(), vertex_value_1.into());
233        graph.add_or_replace_vertex(vertex_1).unwrap();
234
235        let vertex_key_2 = String::from("Vertex_2");
236        let vertex_value_2 = String::from("Property_2");
237        let vertex_2 = Vertex::new(vertex_key_2.clone(), vertex_value_2.into());
238        graph.add_or_replace_vertex(vertex_2).unwrap();
239
240        let index_vertex_1 = graph
241            .vertex_key_to_vertex_index_map_ref()
242            .get(vertex_key_1.as_str())
243            .unwrap();
244        assert_eq!(
245            graph
246                .vertex_index_to_vertex_key_ref(index_vertex_1.clone())
247                .unwrap(),
248            vertex_key_1
249        );
250
251        let index_vertex_2 = graph
252            .vertex_key_to_vertex_index_map_ref()
253            .get(vertex_key_2.as_str())
254            .unwrap();
255        assert_eq!(
256            graph
257                .vertex_index_to_vertex_key_ref(index_vertex_2.clone())
258                .unwrap(),
259            vertex_key_2
260        );
261    }
262}