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#[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}
156impl<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}