solomon_gremlin/structure/
value.rs

1use crate::conversion::{BorrowFromGValue, FromGValue};
2use crate::process::traversal::{Bytecode, Order, Scope, TerminatorToken};
3use crate::structure::traverser::Traverser;
4use crate::structure::{
5	label::LabelType, Cardinality, Edge, GKey, IntermediateRepr, List, Map, Metric, Path, Property,
6	Set, Token, TraversalExplanation, TraversalMetrics, Vertex, VertexProperty,
7};
8use crate::structure::{Pop, Predicate, TextP, T};
9use crate::{GremlinError, GremlinResult};
10use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
11pub type Date = chrono::DateTime<chrono::offset::Utc>;
12use std::convert::TryInto;
13use std::hash::Hash;
14/// Represent possible values coming from the [Gremlin Server](http://tinkerpop.apache.org/docs/3.4.0/dev/io/)
15#[allow(clippy::large_enum_variant)]
16#[derive(Debug, PartialEq, Clone)]
17pub enum GValue {
18	Null,
19	Vertex(Vertex),
20	Edge(Edge),
21	Bytes(Vec<u8>),
22	VertexProperty(VertexProperty),
23	Property(Property),
24	Uuid(uuid::Uuid),
25	Int32(i32),
26	Int64(i64),
27	Float(f32),
28	Double(f64),
29	Date(Date),
30	List(List),
31	Set(Set),
32	Map(Map),
33	Token(Token),
34	String(String),
35	Path(Path),
36	TraversalMetrics(TraversalMetrics),
37	Metric(Metric),
38	TraversalExplanation(TraversalExplanation),
39	IntermediateRepr(IntermediateRepr),
40	P(Predicate),
41	T(T),
42	Bytecode(Bytecode),
43	Traverser(Traverser),
44	Scope(Scope),
45	Order(Order),
46	Bool(bool),
47	TextP(TextP),
48	Pop(Pop),
49	Terminator(TerminatorToken),
50	Cardinality(Cardinality),
51}
52
53impl PartialOrd for GValue {
54	fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
55		match self {
56			GValue::Int32(v) => v.partial_cmp(other.get::<i32>().unwrap()),
57			GValue::Int64(v) => v.partial_cmp(other.get::<i64>().unwrap()),
58			GValue::Float(v) => v.partial_cmp(other.get::<f32>().unwrap()),
59			GValue::Double(v) => v.partial_cmp(other.get::<f64>().unwrap()),
60			GValue::Date(v) => v.partial_cmp(other.get::<Date>().unwrap()),
61			GValue::String(v) => v.partial_cmp(other.get::<String>().unwrap()),
62			_ => unimplemented!(),
63		}
64	}
65}
66
67impl GValue {
68	pub fn from_bytes(variant: usize, bytes: Vec<u8>) -> GValue {
69		match variant {
70			1 => GValue::String(String::from_utf8(bytes).unwrap()),
71			2 => {
72				let mut slice = [Default::default(); 4];
73				slice.copy_from_slice(&bytes);
74				GValue::Int32(i32::from_be_bytes(slice))
75			}
76			3 => {
77				let mut slice = [Default::default(); 8];
78				slice.copy_from_slice(&bytes);
79				GValue::Int64(i64::from_be_bytes(slice))
80			}
81			4 => GValue::Bool(*bytes.last().unwrap() == 0),
82			5 => {
83				let mut slice = [Default::default(); 4];
84				slice.copy_from_slice(&bytes);
85				GValue::Float(f32::from_be_bytes(slice))
86			}
87			8 => GValue::Bytes(bytes),
88			_ => unimplemented!(),
89		}
90	}
91
92	pub fn to_variant(&self) -> u8 {
93		match self {
94			GValue::String(_) => 1,
95			GValue::Int32(_) => 2,
96			GValue::Int64(_) => 3,
97			GValue::Bool(_) => 4,
98			GValue::Float(_) => 5,
99			GValue::Vertex(_) => 6,
100			GValue::VertexProperty(_) => 7,
101			GValue::Bytes(_) => 8,
102			GValue::Edge(_) => 9,
103			GValue::Double(_) => 10,
104			GValue::Cardinality(_) => 11,
105			GValue::Set(_) => 12,
106			GValue::P(_) => 13,
107			_ => unimplemented!(),
108		}
109	}
110
111	pub fn is_null(&self) -> bool {
112		matches!(self, GValue::Null)
113	}
114
115	pub fn bytes(&self) -> Vec<u8> {
116		match self {
117			GValue::String(v) => v.as_bytes().to_vec(),
118			GValue::Int32(v) => v.to_be_bytes().to_vec(),
119			GValue::Int64(v) => v.to_be_bytes().to_vec(),
120			GValue::Bytes(v) => v.to_vec(),
121			_ => unimplemented!(),
122		}
123	}
124
125	pub fn take<T>(self) -> GremlinResult<T>
126	where
127		T: FromGValue,
128	{
129		T::from_gvalue(self)
130	}
131
132	pub fn get<'a, T>(&'a self) -> GremlinResult<&'a T>
133	where
134		T: BorrowFromGValue,
135	{
136		T::from_gvalue(self)
137	}
138
139	pub fn is_cardinality(&self) -> bool {
140		match self {
141			GValue::Cardinality(_) => true,
142			_ => false,
143		}
144	}
145}
146
147impl From<Date> for GValue {
148	fn from(val: Date) -> Self {
149		GValue::Date(val)
150	}
151}
152
153impl From<String> for GValue {
154	fn from(val: String) -> Self {
155		GValue::String(val)
156	}
157}
158
159impl From<&String> for GValue {
160	fn from(val: &String) -> Self {
161		GValue::String(val.clone())
162	}
163}
164
165impl From<i32> for GValue {
166	fn from(val: i32) -> Self {
167		GValue::Int32(val)
168	}
169}
170
171impl From<Vec<u8>> for GValue {
172	fn from(val: Vec<u8>) -> Self {
173		GValue::Bytes(val.to_vec())
174	}
175}
176
177impl From<i64> for GValue {
178	fn from(val: i64) -> Self {
179		GValue::Int64(val)
180	}
181}
182
183impl From<f32> for GValue {
184	fn from(val: f32) -> Self {
185		GValue::Float(val)
186	}
187}
188impl From<f64> for GValue {
189	fn from(val: f64) -> Self {
190		GValue::Double(val)
191	}
192}
193
194impl<'a> From<&'a str> for GValue {
195	fn from(val: &'a str) -> Self {
196		GValue::String(String::from(val))
197	}
198}
199
200impl From<Vertex> for GValue {
201	fn from(val: Vertex) -> Self {
202		GValue::Vertex(val)
203	}
204}
205
206impl From<&Vertex> for GValue {
207	fn from(val: &Vertex) -> Self {
208		GValue::Vertex(val.clone())
209	}
210}
211
212impl From<Path> for GValue {
213	fn from(val: Path) -> Self {
214		GValue::Path(val)
215	}
216}
217impl From<Edge> for GValue {
218	fn from(val: Edge) -> Self {
219		GValue::Edge(val)
220	}
221}
222
223impl From<VertexProperty> for GValue {
224	fn from(val: VertexProperty) -> Self {
225		GValue::VertexProperty(val)
226	}
227}
228
229impl From<Traverser> for GValue {
230	fn from(val: Traverser) -> Self {
231		GValue::Traverser(val)
232	}
233}
234impl From<TraversalMetrics> for GValue {
235	fn from(val: TraversalMetrics) -> Self {
236		GValue::TraversalMetrics(val)
237	}
238}
239
240impl From<TraversalExplanation> for GValue {
241	fn from(val: TraversalExplanation) -> Self {
242		GValue::TraversalExplanation(val)
243	}
244}
245
246impl From<Metric> for GValue {
247	fn from(val: Metric) -> Self {
248		GValue::Metric(val)
249	}
250}
251
252impl From<Property> for GValue {
253	fn from(val: Property) -> Self {
254		GValue::Property(val)
255	}
256}
257
258impl From<Scope> for GValue {
259	fn from(val: Scope) -> Self {
260		GValue::Scope(val)
261	}
262}
263
264impl From<Order> for GValue {
265	fn from(val: Order) -> Self {
266		GValue::Order(val)
267	}
268}
269impl From<Token> for GValue {
270	fn from(val: Token) -> Self {
271		GValue::Token(val)
272	}
273}
274
275impl From<HashMap<String, GValue>> for GValue {
276	fn from(val: HashMap<String, GValue>) -> Self {
277		GValue::Map(Map::from(val))
278	}
279}
280
281impl From<HashMap<GKey, GValue>> for GValue {
282	fn from(val: HashMap<GKey, GValue>) -> Self {
283		GValue::Map(Map::from(val))
284	}
285}
286
287impl From<BTreeMap<String, GValue>> for GValue {
288	fn from(val: BTreeMap<String, GValue>) -> Self {
289		GValue::Map(Map::from(val))
290	}
291}
292
293impl From<Vec<GValue>> for GValue {
294	fn from(val: Vec<GValue>) -> Self {
295		GValue::List(List::new(val))
296	}
297}
298
299impl From<GValue> for Vec<GValue> {
300	fn from(val: GValue) -> Self {
301		vec![val]
302	}
303}
304
305impl From<GValue> for VecDeque<GValue> {
306	fn from(val: GValue) -> Self {
307		match val {
308			GValue::List(l) => VecDeque::from(l.take()),
309			GValue::Set(l) => VecDeque::from(l.take()),
310			_ => VecDeque::from(vec![val]),
311		}
312	}
313}
314
315impl From<GKey> for GValue {
316	fn from(val: GKey) -> Self {
317		match val {
318			GKey::String(s) => GValue::String(s),
319			GKey::Token(s) => GValue::String(s.value().clone()),
320			GKey::Vertex(v) => GValue::Vertex(v),
321			GKey::Edge(v) => GValue::Edge(v),
322		}
323	}
324}
325
326impl From<Predicate> for GValue {
327	fn from(val: Predicate) -> GValue {
328		GValue::P(val)
329	}
330}
331
332impl From<TextP> for GValue {
333	fn from(val: TextP) -> GValue {
334		GValue::TextP(val)
335	}
336}
337
338impl From<T> for GValue {
339	fn from(val: T) -> GValue {
340		GValue::T(val)
341	}
342}
343
344impl From<Bytecode> for GValue {
345	fn from(val: Bytecode) -> GValue {
346		GValue::Bytecode(val)
347	}
348}
349
350impl From<bool> for GValue {
351	fn from(val: bool) -> GValue {
352		GValue::Bool(val)
353	}
354}
355
356impl From<LabelType> for GValue {
357	fn from(val: LabelType) -> GValue {
358		match val {
359			LabelType::Str(val) => val.into(),
360			LabelType::Bool(val) => val.into(),
361			LabelType::T(val) => val.into(),
362		}
363	}
364}
365
366impl From<Cardinality> for GValue {
367	fn from(val: Cardinality) -> GValue {
368		GValue::Cardinality(val)
369	}
370}
371
372impl From<uuid::Uuid> for GValue {
373	fn from(val: uuid::Uuid) -> GValue {
374		GValue::Uuid(val)
375	}
376}
377
378impl std::convert::TryFrom<GValue> for String {
379	type Error = crate::GremlinError;
380
381	fn try_from(value: GValue) -> GremlinResult<Self> {
382		match value {
383			GValue::String(s) => Ok(s),
384			GValue::List(s) => from_list(s),
385			_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to String", value))),
386		}
387	}
388}
389
390impl std::convert::TryFrom<GValue> for i32 {
391	type Error = crate::GremlinError;
392
393	fn try_from(value: GValue) -> GremlinResult<Self> {
394		match value {
395			GValue::Int32(s) => Ok(s),
396			GValue::List(s) => from_list(s),
397			_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to i32", value))),
398		}
399	}
400}
401
402impl std::convert::TryFrom<GValue> for i64 {
403	type Error = crate::GremlinError;
404
405	fn try_from(value: GValue) -> GremlinResult<Self> {
406		match value {
407			GValue::Int64(s) => Ok(s),
408			GValue::List(s) => from_list(s),
409			_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to i32", value))),
410		}
411	}
412}
413
414impl std::convert::TryFrom<GValue> for uuid::Uuid {
415	type Error = crate::GremlinError;
416
417	fn try_from(value: GValue) -> GremlinResult<Self> {
418		match value {
419			GValue::Uuid(uid) => Ok(uid),
420			GValue::List(s) => from_list(s),
421			_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to Uuid", value))),
422		}
423	}
424}
425
426impl std::convert::TryFrom<GValue> for Date {
427	type Error = crate::GremlinError;
428
429	fn try_from(value: GValue) -> GremlinResult<Self> {
430		match value {
431			GValue::Date(date) => Ok(date),
432			GValue::List(s) => from_list(s),
433			_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to DateTime<Utc>", value))),
434		}
435	}
436}
437
438impl std::convert::TryFrom<GValue> for bool {
439	type Error = crate::GremlinError;
440
441	fn try_from(value: GValue) -> GremlinResult<Self> {
442		match value {
443			GValue::Bool(val) => Ok(val),
444			GValue::List(s) => from_list(s),
445			_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to bool", value))),
446		}
447	}
448}
449
450impl std::convert::TryFrom<GValue> for f32 {
451	type Error = crate::GremlinError;
452
453	fn try_from(value: GValue) -> GremlinResult<Self> {
454		match value {
455			GValue::Float(x) => Ok(x),
456			GValue::List(s) => from_list(s),
457			_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to f32", value))),
458		}
459	}
460}
461
462impl std::convert::TryFrom<GValue> for f64 {
463	type Error = crate::GremlinError;
464
465	fn try_from(value: GValue) -> GremlinResult<Self> {
466		match value {
467			GValue::Double(x) => Ok(x),
468			GValue::List(s) => from_list(s),
469			_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to f64", value))),
470		}
471	}
472}
473
474impl std::convert::TryFrom<GValue> for BTreeMap<String, GValue> {
475	type Error = crate::GremlinError;
476
477	fn try_from(value: GValue) -> GremlinResult<Self> {
478		if let GValue::Map(m) = value {
479			m.try_into()
480		} else {
481			Err(GremlinError::Cast(format!("Cannot cast {:?} to HashMap<GKey, GValue>", value)))
482		}
483	}
484}
485
486impl std::convert::TryFrom<GValue> for HashMap<GKey, GValue> {
487	type Error = crate::GremlinError;
488
489	fn try_from(value: GValue) -> GremlinResult<Self> {
490		if let GValue::Map(m) = value {
491			Ok(m.into())
492		} else {
493			Err(GremlinError::Cast(format!("Cannot cast {:?} to HashMap<GKey, GValue>", value)))
494		}
495	}
496}
497
498impl std::convert::TryFrom<GValue> for HashMap<String, GValue> {
499	type Error = crate::GremlinError;
500
501	fn try_from(value: GValue) -> GremlinResult<Self> {
502		if let GValue::Map(m) = value {
503			m.try_into()
504		} else {
505			Err(GremlinError::Cast(format!("Cannot cast {:?} to HashMap<GKey, GValue>", value)))
506		}
507	}
508}
509
510fn from_list<T>(glist: List) -> GremlinResult<T>
511where
512	T: std::convert::TryFrom<GValue, Error = GremlinError>,
513{
514	let mut vec = glist.take();
515
516	match vec.len() {
517		1 => vec.pop().unwrap().try_into(),
518		_ => Err(GremlinError::Cast(String::from("Cannot cast a List to String"))),
519	}
520}
521
522// Optional
523
524macro_rules! impl_try_from_option {
525	($t:ty) => {
526		impl std::convert::TryFrom<GValue> for Option<$t> {
527			type Error = crate::GremlinError;
528
529			fn try_from(value: GValue) -> GremlinResult<Self> {
530				if let GValue::Null = value {
531					return Ok(None);
532				}
533				let res: $t = value.try_into()?;
534				Ok(Some(res))
535			}
536		}
537	};
538}
539
540impl_try_from_option!(String);
541impl_try_from_option!(i32);
542impl_try_from_option!(i64);
543impl_try_from_option!(f32);
544impl_try_from_option!(f64);
545impl_try_from_option!(Date);
546impl_try_from_option!(uuid::Uuid);
547impl_try_from_option!(bool);
548
549fn for_list<T>(glist: &List) -> GremlinResult<Vec<T>>
550where
551	T: std::convert::TryFrom<GValue, Error = GremlinError>,
552{
553	glist.iter().map(|x| x.clone().try_into()).collect::<GremlinResult<Vec<T>>>()
554}
555
556fn for_list_to_set<T>(glist: &List) -> GremlinResult<HashSet<T>>
557where
558	T: std::convert::TryFrom<GValue, Error = GremlinError> + Hash + Eq,
559{
560	glist.iter().map(|x| x.clone().try_into()).collect::<GremlinResult<HashSet<T>>>()
561}
562
563fn for_set<T>(gset: &Set) -> GremlinResult<HashSet<T>>
564where
565	T: std::convert::TryFrom<GValue, Error = GremlinError> + Hash + Eq,
566{
567	gset.iter().map(|x| x.clone().try_into()).collect::<GremlinResult<HashSet<T>>>()
568}
569
570macro_rules! impl_try_from_set {
571	($t:ty) => {
572		//Ideally this would be handled in conversion.rs but because the GValue::Set holds a Vec
573		//we handle converting it here
574		impl FromGValue for HashSet<$t> {
575			fn from_gvalue(value: GValue) -> GremlinResult<Self> {
576				match value {
577					GValue::List(s) => for_list_to_set(&s),
578					GValue::Set(s) => for_set(&s),
579					GValue::Null => Ok(HashSet::new()),
580					_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to HashSet", value))),
581				}
582			}
583		}
584
585		impl std::convert::TryFrom<GValue> for HashSet<$t> {
586			type Error = crate::GremlinError;
587
588			fn try_from(value: GValue) -> GremlinResult<Self> {
589				match value {
590					GValue::List(s) => for_list_to_set(&s),
591					GValue::Set(s) => for_set(&s),
592					GValue::Null => Ok(HashSet::new()),
593					_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to HashSet", value))),
594				}
595			}
596		}
597
598		impl std::convert::TryFrom<&GValue> for HashSet<$t> {
599			type Error = crate::GremlinError;
600
601			fn try_from(value: &GValue) -> GremlinResult<Self> {
602				match value {
603					GValue::List(s) => for_list_to_set(s),
604					GValue::Set(s) => for_set(s),
605					GValue::Null => Ok(HashSet::new()),
606					_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to HashSet", value))),
607				}
608			}
609		}
610	};
611}
612
613impl_try_from_set!(String);
614impl_try_from_set!(i32);
615impl_try_from_set!(i64);
616impl_try_from_set!(Date);
617impl_try_from_set!(uuid::Uuid);
618impl_try_from_set!(bool);
619//floats do not conform to the Eq or Hash traits
620// impl_try_from_set!(f32);
621// impl_try_from_set!(f64);
622
623macro_rules! impl_try_from_list {
624	($t:ty) => {
625		impl std::convert::TryFrom<GValue> for Vec<$t> {
626			type Error = crate::GremlinError;
627
628			fn try_from(value: GValue) -> GremlinResult<Self> {
629				match value {
630					GValue::List(s) => for_list(&s),
631					GValue::Null => Ok(Vec::new()),
632					_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to Vec", value))),
633				}
634			}
635		}
636
637		impl std::convert::TryFrom<&GValue> for Vec<$t> {
638			type Error = crate::GremlinError;
639
640			fn try_from(value: &GValue) -> GremlinResult<Self> {
641				match value {
642					GValue::List(s) => for_list(s),
643					GValue::Null => Ok(Vec::new()),
644					_ => Err(GremlinError::Cast(format!("Cannot cast {:?} to Vec", value))),
645				}
646			}
647		}
648	};
649}
650
651impl_try_from_list!(String);
652impl_try_from_list!(i32);
653impl_try_from_list!(i64);
654impl_try_from_list!(f32);
655impl_try_from_list!(f64);
656impl_try_from_list!(Date);
657impl_try_from_list!(uuid::Uuid);
658impl_try_from_list!(bool);