1#[macro_use]
2mod macros;
3mod serializer_v2;
4mod serializer_v3;
5
6use crate::conversion::ToGValue;
7use crate::process::traversal::{Order, Scope};
8use crate::structure::{Cardinality, GValue, T};
9use serde_json::{json, Map, Value};
10use std::string::ToString;
11
12use crate::{GremlinError, GremlinResult};
13
14#[derive(Debug, Clone)]
15pub enum GraphSON {
16 V2,
17 V3,
18}
19
20impl GraphSON {
21 pub fn read(&self, value: &Value) -> GremlinResult<Option<GValue>> {
22 if let Value::Null = value {
23 return Ok(None);
24 }
25 match self {
26 GraphSON::V2 => serializer_v2::deserializer_v2(value).map(Some),
27 GraphSON::V3 => serializer_v3::deserializer_v3(value).map(Some),
28 }
29 }
30
31 pub fn write(&self, value: &GValue) -> GremlinResult<Value> {
32 match (self, value) {
33 (_, GValue::Double(d)) => Ok(json!({
34 "@type" : "g:Double",
35 "@value" : d
36 })),
37 (_, GValue::Float(f)) => Ok(json!({
38 "@type" : "g:Float",
39 "@value" : f
40 })),
41 (_, GValue::Int32(i)) => Ok(json!({
42 "@type" : "g:Int32",
43 "@value" : i
44 })),
45 (_, GValue::Int64(i)) => Ok(json!({
46 "@type" : "g:Int64",
47 "@value" : i
48 })),
49 (_, GValue::String(s)) => Ok(Value::String(s.clone())),
50 (_, GValue::Uuid(s)) => Ok(json!({
51 "@type" : "g:UUID",
52 "@value" : s.to_string()
53 })),
54 (_, GValue::Date(d)) => Ok(json!({
55 "@type" : "g:Date",
56 "@value" : d.timestamp_millis()
57 })),
58 (GraphSON::V2, GValue::List(d)) => {
59 let elements: GremlinResult<Vec<Value>> = d.iter().map(|e| self.write(e)).collect();
60 Ok(json!(elements?))
61 }
62 (GraphSON::V3, GValue::List(d)) => {
63 let elements: GremlinResult<Vec<Value>> = d.iter().map(|e| self.write(e)).collect();
64 Ok(json!({
65 "@type" : "g:List",
66 "@value" : elements?
67 }))
68 }
69 (_, GValue::P(p)) => Ok(json!({
70 "@type" : "g:P",
71 "@value" : {
72 "predicate" : p.operator(),
73 "value" : self.write(p.value())?
74 }
75 })),
76 (_, GValue::Bytecode(code)) => {
77 let steps: GremlinResult<Vec<Value>> = code
78 .steps()
79 .iter()
80 .map(|m| {
81 let mut instruction = vec![];
82 instruction.push(Value::String(m.operator().clone()));
83
84 let arguments: GremlinResult<Vec<Value>> =
85 m.args().iter().map(|a| self.write(a)).collect();
86
87 instruction.extend(arguments?);
88 Ok(Value::Array(instruction))
89 })
90 .collect();
91
92 let sources: GremlinResult<Vec<Value>> = code
93 .sources()
94 .iter()
95 .map(|m| {
96 let mut instruction = vec![];
97 instruction.push(Value::String(m.operator().clone()));
98
99 let arguments: GremlinResult<Vec<Value>> =
100 m.args().iter().map(|a| self.write(a)).collect();
101
102 instruction.extend(arguments?);
103 Ok(Value::Array(instruction))
104 })
105 .collect();
106 Ok(json!({
107 "@type" : "g:Bytecode",
108 "@value" : {
109 "step" : steps?,
110 "source" : sources?
111 }
112 }))
113 }
114 (_, GValue::Vertex(v)) => {
115 let id = self.write(&v.id().to_gvalue())?;
116 Ok(json!({
117 "@type" : "g:Vertex",
118 "@value" : {
119 "id" : id,
120 }
121 }))
122 }
123 (GraphSON::V2, GValue::Map(map)) => {
124 let mut params = Map::new();
125
126 for (k, v) in map.iter() {
127 params.insert(
128 self.write(&k.clone().into())?
129 .as_str()
130 .ok_or_else(|| {
131 GremlinError::Generic("Non-string key value.".to_string())
132 })?
133 .to_string(),
134 self.write(&v)?,
135 );
136 }
137
138 Ok(json!(params))
139 }
140 (GraphSON::V3, GValue::Map(map)) => {
141 let mut params = vec![];
142
143 for (k, v) in map.iter() {
144 params.push(self.write(&k.clone().into())?);
145 params.push(self.write(&v)?);
146 }
147
148 Ok(json!({
149 "@type" : "g:Map",
150 "@value" : params
151 }))
152 }
153 (_, GValue::T(t)) => {
154 let v = match t {
155 T::Id => "id",
156 T::Key => "key",
157 T::Label => "label",
158 T::Value => "value",
159 };
160
161 Ok(json!({
162 "@type" : "g:T",
163 "@value" : v
164 }))
165 }
166 (_, GValue::Scope(s)) => {
167 let v = match s {
168 Scope::Global => "global",
169 Scope::Local => "local",
170 };
171
172 Ok(json!({
173 "@type" : "g:Scope",
174 "@value" : v
175 }))
176 }
177
178 (_, GValue::Order(s)) => {
179 let v = match s {
180 Order::Asc => "asc",
181 Order::Desc => "desc",
182 Order::Shuffle => "shuffle",
183 };
184
185 Ok(json!({
186 "@type" : "g:Order",
187 "@value" : v
188 }))
189 }
190 (_, GValue::Bool(b)) => {
191 let json_string = match b {
192 true => "true",
193 false => "false",
194 };
195 Ok(serde_json::from_str(json_string).unwrap())
196 }
197 (_, GValue::TextP(text_p)) => Ok(json!({
198 "@type" : "g:TextP",
199 "@value" : {
200 "predicate" : text_p.operator(),
201 "value" : self.write(text_p.value())?
202 }
203 })),
204 (_, GValue::Pop(pop)) => Ok(json!({
205 "@type": "g:Pop",
206 "@value": *pop.to_string(),
207 })),
208 (_, GValue::Cardinality(cardinality)) => {
209 let v = match cardinality {
210 Cardinality::List => "list",
211 Cardinality::Single => "single",
212 Cardinality::Set => "set",
213 };
214 Ok(json!({
215 "@type" : "g:Cardinality",
216 "@value" : v
217 }))
218 }
219
220 (_, _) => panic!("Type {:?} not supported.", value),
221 }
222 }
223
224 pub fn content_type(&self) -> &str {
225 match self {
226 GraphSON::V2 => "application/vnd.gremlin-v2.0+json",
227 GraphSON::V3 => "application/vnd.gremlin-v3.0+json",
228 }
229 }
230}