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