solomon_gremlin/
conversion.rs

1use crate::{
2	process::traversal::{Bytecode, TerminatorToken},
3	structure::{Predicate, TextP},
4	Edge, GKey, GValue, GremlinError, GremlinResult, IntermediateRepr, List, Map, Metric, Path,
5	Property, Token, TraversalExplanation, TraversalMetrics, Vertex, VertexProperty, GID,
6};
7
8use crate::structure::Set;
9use crate::structure::Traverser;
10
11use std::collections::HashMap;
12
13pub trait ToGValue: Send + Sync {
14	fn to_gvalue(&self) -> GValue;
15}
16
17#[derive(Debug, PartialEq)]
18pub struct Params(pub HashMap<String, GValue>);
19
20impl Into<Params> for () {
21	fn into(self) -> Params {
22		Params(HashMap::new())
23	}
24}
25
26impl ToGValue for Vec<GValue> {
27	fn to_gvalue(&self) -> GValue {
28		GValue::List(List::new(self.clone()))
29	}
30}
31
32impl ToGValue for GID {
33	fn to_gvalue(&self) -> GValue {
34		match self {
35			GID::Int32(n) => GValue::from(*n),
36			GID::Int64(n) => GValue::from(*n),
37			GID::String(n) => GValue::from(n),
38			GID::Bytes(n) => GValue::from(n.to_vec()),
39		}
40	}
41}
42
43macro_rules! impl_to_gvalue {
44	($t:ty, $v:path) => {
45		impl ToGValue for $t {
46			fn to_gvalue(&self) -> GValue {
47				$v(*self)
48			}
49		}
50	};
51}
52
53impl_to_gvalue!(f32, GValue::Float);
54impl_to_gvalue!(f64, GValue::Double);
55impl_to_gvalue!(i32, GValue::Int32);
56impl_to_gvalue!(i64, GValue::Int64);
57impl_to_gvalue!(chrono::DateTime<chrono::Utc>, GValue::Date);
58impl_to_gvalue!(uuid::Uuid, GValue::Uuid);
59impl_to_gvalue!(bool, GValue::Bool);
60
61impl ToGValue for &str {
62	fn to_gvalue(&self) -> GValue {
63		GValue::String(String::from(*self))
64	}
65}
66
67impl ToGValue for Predicate {
68	fn to_gvalue(&self) -> GValue {
69		GValue::P(self.clone())
70	}
71}
72
73impl ToGValue for TextP {
74	fn to_gvalue(&self) -> GValue {
75		GValue::TextP(self.clone())
76	}
77}
78
79impl ToGValue for String {
80	fn to_gvalue(&self) -> GValue {
81		GValue::String(self.clone())
82	}
83}
84
85impl ToGValue for Bytecode {
86	fn to_gvalue(&self) -> GValue {
87		GValue::Bytecode(self.clone())
88	}
89}
90
91// Take from GValue
92
93#[doc(hidden)]
94pub trait FromGValue: Sized {
95	fn from_gvalue(v: GValue) -> GremlinResult<Self>;
96}
97
98macro_rules! impl_from_gvalue {
99	($t:ty, $v:path) => {
100		impl FromGValue for $t {
101			fn from_gvalue(v: GValue) -> GremlinResult<$t> {
102				match v {
103					$v(e) => Ok(e),
104					_ => Err(GremlinError::Cast(format!(
105						"Cannot convert {:?} to {}",
106						v,
107						stringify!($t)
108					))),
109				}
110			}
111		}
112	};
113}
114
115impl_from_gvalue!(VertexProperty, GValue::VertexProperty);
116impl_from_gvalue!(Property, GValue::Property);
117impl_from_gvalue!(Map, GValue::Map);
118impl_from_gvalue!(Set, GValue::Set);
119impl_from_gvalue!(List, GValue::List);
120impl_from_gvalue!(Token, GValue::Token);
121impl_from_gvalue!(Vertex, GValue::Vertex);
122impl_from_gvalue!(Edge, GValue::Edge);
123impl_from_gvalue!(Path, GValue::Path);
124impl_from_gvalue!(String, GValue::String);
125impl_from_gvalue!(f32, GValue::Float);
126impl_from_gvalue!(f64, GValue::Double);
127impl_from_gvalue!(i32, GValue::Int32);
128impl_from_gvalue!(i64, GValue::Int64);
129impl_from_gvalue!(bool, GValue::Bool);
130impl_from_gvalue!(uuid::Uuid, GValue::Uuid);
131impl_from_gvalue!(Metric, GValue::Metric);
132impl_from_gvalue!(TraversalMetrics, GValue::TraversalMetrics);
133impl_from_gvalue!(TraversalExplanation, GValue::TraversalExplanation);
134impl_from_gvalue!(IntermediateRepr, GValue::IntermediateRepr);
135impl_from_gvalue!(chrono::DateTime<chrono::Utc>, GValue::Date);
136impl_from_gvalue!(Traverser, GValue::Traverser);
137impl_from_gvalue!(Predicate, GValue::P);
138
139impl FromGValue for GKey {
140	fn from_gvalue(v: GValue) -> GremlinResult<GKey> {
141		match v {
142			GValue::String(s) => Ok(GKey::String(s)),
143			GValue::Token(s) => Ok(GKey::String(s.value().clone())),
144			GValue::Vertex(s) => Ok(GKey::Vertex(s)),
145			GValue::Edge(s) => Ok(GKey::Edge(s)),
146			_ => Err(GremlinError::Cast(format!("Cannot convert {:?} to {}", v, "GKey"))),
147		}
148	}
149}
150
151impl FromGValue for GValue {
152	fn from_gvalue(v: GValue) -> GremlinResult<GValue> {
153		Ok(v)
154	}
155}
156// Borrow from GValue
157
158impl<T: FromGValue> FromGValue for Vec<T> {
159	fn from_gvalue(v: GValue) -> GremlinResult<Vec<T>> {
160		match v {
161			GValue::List(l) => {
162				let results: GremlinResult<Vec<T>> =
163					l.take().into_iter().map(T::from_gvalue).collect();
164				Ok(results?)
165			}
166			_ => Err(GremlinError::Cast(format!("Cannot convert {:?} to List of T", v))),
167		}
168	}
169}
170
171#[doc(hidden)]
172pub trait BorrowFromGValue: Sized {
173	fn from_gvalue<'a>(v: &'a GValue) -> GremlinResult<&'a Self>;
174}
175
176macro_rules! impl_borrow_from_gvalue {
177	($t:ty, $v:path) => {
178		impl BorrowFromGValue for $t {
179			fn from_gvalue<'a>(v: &'a GValue) -> GremlinResult<&'a $t> {
180				match v {
181					$v(e) => Ok(e),
182					_ => Err(GremlinError::Cast(format!(
183						"Cannot convert {:?} to {}",
184						v,
185						stringify!($t)
186					))),
187				}
188			}
189		}
190	};
191}
192
193impl_borrow_from_gvalue!(TerminatorToken, GValue::Terminator);
194impl_borrow_from_gvalue!(VertexProperty, GValue::VertexProperty);
195impl_borrow_from_gvalue!(Property, GValue::Property);
196impl_borrow_from_gvalue!(Map, GValue::Map);
197impl_borrow_from_gvalue!(Set, GValue::Set);
198impl_borrow_from_gvalue!(List, GValue::List);
199impl_borrow_from_gvalue!(Vertex, GValue::Vertex);
200impl_borrow_from_gvalue!(Edge, GValue::Edge);
201impl_borrow_from_gvalue!(Path, GValue::Path);
202impl_borrow_from_gvalue!(String, GValue::String);
203impl_borrow_from_gvalue!(Token, GValue::Token);
204impl_borrow_from_gvalue!(f32, GValue::Float);
205impl_borrow_from_gvalue!(f64, GValue::Double);
206impl_borrow_from_gvalue!(i32, GValue::Int32);
207impl_borrow_from_gvalue!(i64, GValue::Int64);
208impl_borrow_from_gvalue!(uuid::Uuid, GValue::Uuid);
209impl_borrow_from_gvalue!(chrono::DateTime<chrono::Utc>, GValue::Date);
210impl_borrow_from_gvalue!(bool, GValue::Bool);
211
212#[cfg(feature = "test-suite")]
213#[test]
214fn to_gvalue_for_vec_gvalue() {
215	let ids_from_somewhere = vec![1, 2, 3];
216	let converted_ids: Vec<GValue> = ids_from_somewhere.into_iter().map(|x| x.into()).collect();
217	let actual: GValue = converted_ids.clone().into();
218	let expected = GValue::List(List::new(converted_ids));
219	assert_eq!(actual, expected);
220}