gremlin_client/
conversion.rs

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// Take from GValue
91
92#[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}
157// Borrow from GValue
158
159impl<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}