gremlin_client/io/
mod.rs

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}