indradb_proto/
converters.rs

1//! Trait implementations for conveniently converting between protobuf and
2//! native IndraDB models.
3
4use std::convert::TryInto;
5use std::error::Error as StdError;
6use std::fmt;
7
8use indradb::ValidationError;
9use serde_json::Error as SerdeJsonError;
10use uuid::Error as UuidError;
11use uuid::Uuid;
12
13/// The error returned if a try into operation fails.
14#[derive(Debug)]
15pub enum ConversionError {
16    Json { inner: SerdeJsonError },
17    Uuid { inner: UuidError },
18    Validation { inner: ValidationError },
19    NoneField { name: String },
20    UnexpectedResponseType,
21}
22
23impl StdError for ConversionError {
24    fn source(&self) -> Option<&(dyn StdError + 'static)> {
25        match *self {
26            ConversionError::Json { ref inner } => Some(inner),
27            ConversionError::Uuid { ref inner } => Some(inner),
28            ConversionError::Validation { ref inner } => Some(inner),
29            _ => None,
30        }
31    }
32}
33
34impl fmt::Display for ConversionError {
35    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36        match *self {
37            ConversionError::Json { ref inner } => write!(f, "json conversion failed: {inner}"),
38            ConversionError::Uuid { ref inner } => write!(f, "uuid conversion failed: {inner}"),
39            ConversionError::Validation { ref inner } => write!(f, "validation conversion failed: {inner}"),
40            ConversionError::NoneField { ref name } => write!(f, "proto field '{name}' should not be none"),
41            ConversionError::UnexpectedResponseType => write!(f, "unexpected response type"),
42        }
43    }
44}
45
46impl From<SerdeJsonError> for ConversionError {
47    fn from(err: SerdeJsonError) -> Self {
48        ConversionError::Json { inner: err }
49    }
50}
51
52impl From<UuidError> for ConversionError {
53    fn from(err: UuidError) -> Self {
54        ConversionError::Uuid { inner: err }
55    }
56}
57
58impl From<ValidationError> for ConversionError {
59    fn from(err: ValidationError) -> Self {
60        ConversionError::Validation { inner: err }
61    }
62}
63
64fn required_field<T>(field_name: &str, value: Option<T>) -> Result<T, ConversionError> {
65    value.ok_or_else(|| ConversionError::NoneField {
66        name: field_name.to_string(),
67    })
68}
69
70impl From<Uuid> for crate::Uuid {
71    fn from(uuid: Uuid) -> Self {
72        crate::Uuid {
73            value: uuid.as_bytes().to_vec(),
74        }
75    }
76}
77
78impl TryInto<Uuid> for crate::Uuid {
79    type Error = ConversionError;
80
81    fn try_into(self) -> Result<Uuid, Self::Error> {
82        Ok(Uuid::from_slice(&self.value)?)
83    }
84}
85
86impl From<indradb::Identifier> for crate::Identifier {
87    fn from(t: indradb::Identifier) -> Self {
88        crate::Identifier { value: t.to_string() }
89    }
90}
91
92impl TryInto<indradb::Identifier> for crate::Identifier {
93    type Error = ConversionError;
94
95    fn try_into(self) -> Result<indradb::Identifier, Self::Error> {
96        Ok(indradb::Identifier::new(self.value)?)
97    }
98}
99
100impl From<indradb::Json> for crate::Json {
101    fn from(value: indradb::Json) -> Self {
102        crate::Json {
103            value: (*value).to_string(),
104        }
105    }
106}
107
108impl TryInto<indradb::Json> for crate::Json {
109    type Error = ConversionError;
110
111    fn try_into(self) -> Result<indradb::Json, Self::Error> {
112        Ok(serde_json::from_str(&self.value)?)
113    }
114}
115
116impl From<indradb::Edge> for crate::Edge {
117    fn from(edge: indradb::Edge) -> Self {
118        crate::Edge {
119            outbound_id: Some(edge.outbound_id.into()),
120            t: Some(edge.t.into()),
121            inbound_id: Some(edge.inbound_id.into()),
122        }
123    }
124}
125
126impl TryInto<indradb::Edge> for crate::Edge {
127    type Error = ConversionError;
128
129    fn try_into(self) -> Result<indradb::Edge, Self::Error> {
130        Ok(indradb::Edge::new(
131            required_field("outbound_id", self.outbound_id)?.try_into()?,
132            required_field("t", self.t)?.try_into()?,
133            required_field("inbound_id", self.inbound_id)?.try_into()?,
134        ))
135    }
136}
137
138impl From<indradb::Vertex> for crate::Vertex {
139    fn from(vertex: indradb::Vertex) -> Self {
140        crate::Vertex {
141            id: Some(vertex.id.into()),
142            t: Some(vertex.t.into()),
143        }
144    }
145}
146
147impl TryInto<indradb::Vertex> for crate::Vertex {
148    type Error = ConversionError;
149
150    fn try_into(self) -> Result<indradb::Vertex, Self::Error> {
151        Ok(indradb::Vertex::with_id(
152            required_field("id", self.id)?.try_into()?,
153            required_field("t", self.t)?.try_into()?,
154        ))
155    }
156}
157
158impl From<indradb::Query> for crate::Query {
159    fn from(q: indradb::Query) -> Self {
160        crate::Query {
161            query: Some(match q {
162                indradb::Query::AllVertex => crate::QueryVariant::AllVertex(()),
163                indradb::Query::RangeVertex(q) => crate::QueryVariant::RangeVertex(crate::RangeVertexQuery {
164                    limit: q.limit,
165                    t: q.t.map(|t| t.into()),
166                    start_id: q.start_id.map(|start_id| start_id.into()),
167                }),
168                indradb::Query::SpecificVertex(q) => crate::QueryVariant::SpecificVertex(crate::SpecificVertexQuery {
169                    ids: q.ids.into_iter().map(|id| id.into()).collect(),
170                }),
171                indradb::Query::VertexWithPropertyPresence(q) => {
172                    crate::QueryVariant::VertexWithPropertyPresence(crate::VertexWithPropertyPresenceQuery {
173                        name: Some(q.name.into()),
174                    })
175                }
176                indradb::Query::VertexWithPropertyValue(q) => {
177                    crate::QueryVariant::VertexWithPropertyValue(crate::VertexWithPropertyValueQuery {
178                        name: Some(q.name.into()),
179                        value: Some(q.value.into()),
180                    })
181                }
182
183                indradb::Query::AllEdge => crate::QueryVariant::AllEdge(()),
184                indradb::Query::SpecificEdge(q) => crate::QueryVariant::SpecificEdge(crate::SpecificEdgeQuery {
185                    edges: q.edges.into_iter().map(|id| id.into()).collect(),
186                }),
187                indradb::Query::EdgeWithPropertyPresence(q) => {
188                    crate::QueryVariant::EdgeWithPropertyPresence(crate::EdgeWithPropertyPresenceQuery {
189                        name: Some(q.name.into()),
190                    })
191                }
192                indradb::Query::EdgeWithPropertyValue(q) => {
193                    crate::QueryVariant::EdgeWithPropertyValue(crate::EdgeWithPropertyValueQuery {
194                        name: Some(q.name.into()),
195                        value: Some(q.value.into()),
196                    })
197                }
198
199                indradb::Query::Pipe(q) => {
200                    let mut proto_q = crate::PipeQuery {
201                        inner: Some(Box::new((*q.inner).into())),
202                        direction: 0,
203                        limit: q.limit,
204                        t: q.t.map(|t| t.into()),
205                    };
206                    proto_q.set_direction(q.direction.into());
207                    crate::QueryVariant::Pipe(Box::new(proto_q))
208                }
209                indradb::Query::PipeProperty(q) => {
210                    let proto_q = crate::PipePropertyQuery {
211                        inner: Some(Box::new((*q.inner).into())),
212                        name: q.name.map(|name| name.into()),
213                    };
214                    crate::QueryVariant::PipeProperty(Box::new(proto_q))
215                }
216                indradb::Query::PipeWithPropertyPresence(q) => {
217                    let proto_q = crate::PipeWithPropertyPresenceQuery {
218                        inner: Some(Box::new((*q.inner).into())),
219                        name: Some(q.name.into()),
220                        exists: q.exists,
221                    };
222                    crate::QueryVariant::PipeWithPropertyPresence(Box::new(proto_q))
223                }
224                indradb::Query::PipeWithPropertyValue(q) => {
225                    let proto_q = crate::PipeWithPropertyValueQuery {
226                        inner: Some(Box::new((*q.inner).into())),
227                        name: Some(q.name.into()),
228                        value: Some(q.value.into()),
229                        equal: q.equal,
230                    };
231                    crate::QueryVariant::PipeWithPropertyValue(Box::new(proto_q))
232                }
233
234                indradb::Query::Include(q) => {
235                    let proto_q = crate::IncludeQuery {
236                        inner: Some(Box::new((*q.inner).into())),
237                    };
238                    crate::QueryVariant::Include(Box::new(proto_q))
239                }
240                indradb::Query::Count(q) => {
241                    let proto_q = crate::CountQuery {
242                        inner: Some(Box::new((*q.inner).into())),
243                    };
244                    crate::QueryVariant::Count(Box::new(proto_q))
245                }
246            }),
247        }
248    }
249}
250
251impl TryInto<indradb::Query> for crate::Query {
252    type Error = ConversionError;
253
254    fn try_into(self) -> Result<indradb::Query, Self::Error> {
255        Ok(match required_field("query", self.query)? {
256            crate::QueryVariant::AllVertex(_q) => indradb::Query::AllVertex,
257            crate::QueryVariant::RangeVertex(q) => indradb::Query::RangeVertex(indradb::RangeVertexQuery {
258                limit: q.limit,
259                t: q.t.map(|t| t.try_into()).transpose()?,
260                start_id: q.start_id.map(|start_id| start_id.try_into()).transpose()?,
261            }),
262            crate::QueryVariant::SpecificVertex(q) => {
263                let ids: Result<Vec<Uuid>, ConversionError> = q.ids.into_iter().map(|id| id.try_into()).collect();
264                indradb::Query::SpecificVertex(indradb::SpecificVertexQuery { ids: ids? })
265            }
266            crate::QueryVariant::VertexWithPropertyPresence(q) => {
267                let name = required_field("name", q.name)?;
268                indradb::Query::VertexWithPropertyPresence(indradb::VertexWithPropertyPresenceQuery {
269                    name: name.try_into()?,
270                })
271            }
272            crate::QueryVariant::VertexWithPropertyValue(q) => {
273                let name = required_field("name", q.name)?;
274                let value = required_field("value", q.value)?;
275                indradb::Query::VertexWithPropertyValue(indradb::VertexWithPropertyValueQuery {
276                    name: name.try_into()?,
277                    value: value.try_into()?,
278                })
279            }
280
281            crate::QueryVariant::AllEdge(_q) => indradb::Query::AllEdge,
282            crate::QueryVariant::SpecificEdge(q) => {
283                let edges: Result<Vec<indradb::Edge>, ConversionError> =
284                    q.edges.into_iter().map(|id| id.try_into()).collect();
285                indradb::Query::SpecificEdge(indradb::SpecificEdgeQuery { edges: edges? })
286            }
287            crate::QueryVariant::EdgeWithPropertyPresence(q) => {
288                let name = required_field("name", q.name)?;
289                indradb::Query::EdgeWithPropertyPresence(indradb::EdgeWithPropertyPresenceQuery {
290                    name: name.try_into()?,
291                })
292            }
293            crate::QueryVariant::EdgeWithPropertyValue(q) => {
294                let name = required_field("name", q.name)?;
295                let value = required_field("value", q.value)?;
296                indradb::Query::EdgeWithPropertyValue(indradb::EdgeWithPropertyValueQuery {
297                    name: name.try_into()?,
298                    value: value.try_into()?,
299                })
300            }
301
302            crate::QueryVariant::Pipe(q) => {
303                let direction = q.direction().into();
304                let limit = q.limit;
305                let t = q.t.map(|t| t.try_into()).transpose()?;
306                let inner = required_field("inner", q.inner)?;
307                indradb::Query::Pipe(indradb::PipeQuery {
308                    direction,
309                    limit,
310                    t,
311                    inner: Box::new((*inner).try_into()?),
312                })
313            }
314            crate::QueryVariant::PipeProperty(q) => {
315                let inner = required_field("inner", q.inner)?;
316                let name = q.name.map(|n| n.try_into()).transpose()?;
317                indradb::Query::PipeProperty(indradb::PipePropertyQuery {
318                    inner: Box::new((*inner).try_into()?),
319                    name,
320                })
321            }
322            crate::QueryVariant::PipeWithPropertyPresence(q) => {
323                let inner = required_field("inner", q.inner)?;
324                let name = required_field("name", q.name)?;
325                indradb::Query::PipeWithPropertyPresence(indradb::PipeWithPropertyPresenceQuery {
326                    inner: Box::new((*inner).try_into()?),
327                    name: name.try_into()?,
328                    exists: q.exists,
329                })
330            }
331            crate::QueryVariant::PipeWithPropertyValue(q) => {
332                let inner = required_field("inner", q.inner)?;
333                let name = required_field("name", q.name)?;
334                let value = required_field("value", q.value)?;
335                indradb::Query::PipeWithPropertyValue(indradb::PipeWithPropertyValueQuery {
336                    inner: Box::new((*inner).try_into()?),
337                    name: name.try_into()?,
338                    value: value.try_into()?,
339                    equal: q.equal,
340                })
341            }
342
343            crate::QueryVariant::Include(q) => {
344                let inner = required_field("inner", q.inner)?;
345                indradb::Query::Include(indradb::IncludeQuery {
346                    inner: Box::new((*inner).try_into()?),
347                })
348            }
349            crate::QueryVariant::Count(q) => {
350                let inner = required_field("inner", q.inner)?;
351                indradb::Query::Count(indradb::CountQuery {
352                    inner: Box::new((*inner).try_into()?),
353                })
354            }
355        })
356    }
357}
358
359impl From<indradb::QueryOutputValue> for crate::QueryOutputValue {
360    fn from(output: indradb::QueryOutputValue) -> Self {
361        let variant = match output {
362            indradb::QueryOutputValue::Vertices(vertices) => {
363                crate::QueryOutputValueVariant::Vertices(crate::QueryOutputVertices {
364                    vertices: vertices.into_iter().map(|e| e.into()).collect(),
365                })
366            }
367            indradb::QueryOutputValue::Edges(edges) => crate::QueryOutputValueVariant::Edges(crate::QueryOutputEdges {
368                edges: edges.into_iter().map(|e| e.into()).collect(),
369            }),
370            indradb::QueryOutputValue::Count(count) => crate::QueryOutputValueVariant::Count(count),
371            indradb::QueryOutputValue::VertexProperties(vertex_properties) => {
372                crate::QueryOutputValueVariant::VertexProperties(crate::QueryOutputVertexProperties {
373                    vertex_properties: vertex_properties.into_iter().map(|vp| vp.into()).collect(),
374                })
375            }
376            indradb::QueryOutputValue::EdgeProperties(edge_properties) => {
377                crate::QueryOutputValueVariant::EdgeProperties(crate::QueryOutputEdgeProperties {
378                    edge_properties: edge_properties.into_iter().map(|ep| ep.into()).collect(),
379                })
380            }
381        };
382
383        crate::QueryOutputValue { value: Some(variant) }
384    }
385}
386
387impl TryInto<indradb::QueryOutputValue> for crate::QueryOutputValue {
388    type Error = ConversionError;
389
390    fn try_into(self) -> Result<indradb::QueryOutputValue, Self::Error> {
391        Ok(match required_field("value", self.value)? {
392            crate::QueryOutputValueVariant::Vertices(vertices) => {
393                let vertices: Result<Vec<indradb::Vertex>, ConversionError> =
394                    vertices.vertices.into_iter().map(|v| v.try_into()).collect();
395                indradb::QueryOutputValue::Vertices(vertices?)
396            }
397            crate::QueryOutputValueVariant::Edges(edges) => {
398                let edges: Result<Vec<indradb::Edge>, ConversionError> =
399                    edges.edges.into_iter().map(|e| e.try_into()).collect();
400                indradb::QueryOutputValue::Edges(edges?)
401            }
402            crate::QueryOutputValueVariant::Count(count) => indradb::QueryOutputValue::Count(count),
403            crate::QueryOutputValueVariant::VertexProperties(vertex_properties) => {
404                let vertex_properties: Result<Vec<indradb::VertexProperties>, ConversionError> = vertex_properties
405                    .vertex_properties
406                    .into_iter()
407                    .map(|vp| vp.try_into())
408                    .collect();
409                indradb::QueryOutputValue::VertexProperties(vertex_properties?)
410            }
411            crate::QueryOutputValueVariant::EdgeProperties(edge_properties) => {
412                let edge_properties: Result<Vec<indradb::EdgeProperties>, ConversionError> = edge_properties
413                    .edge_properties
414                    .into_iter()
415                    .map(|ep| ep.try_into())
416                    .collect();
417                indradb::QueryOutputValue::EdgeProperties(edge_properties?)
418            }
419        })
420    }
421}
422
423impl From<indradb::EdgeDirection> for crate::EdgeDirection {
424    fn from(direction: indradb::EdgeDirection) -> Self {
425        match direction {
426            indradb::EdgeDirection::Outbound => crate::EdgeDirection::Outbound,
427            indradb::EdgeDirection::Inbound => crate::EdgeDirection::Inbound,
428        }
429    }
430}
431
432impl From<crate::EdgeDirection> for indradb::EdgeDirection {
433    fn from(direction: crate::EdgeDirection) -> Self {
434        match direction {
435            crate::EdgeDirection::Outbound => indradb::EdgeDirection::Outbound,
436            crate::EdgeDirection::Inbound => indradb::EdgeDirection::Inbound,
437        }
438    }
439}
440
441impl From<indradb::NamedProperty> for crate::NamedProperty {
442    fn from(prop: indradb::NamedProperty) -> Self {
443        crate::NamedProperty {
444            name: Some(prop.name.into()),
445            value: Some(prop.value.into()),
446        }
447    }
448}
449
450impl TryInto<indradb::NamedProperty> for crate::NamedProperty {
451    type Error = ConversionError;
452
453    fn try_into(self) -> Result<indradb::NamedProperty, Self::Error> {
454        Ok(indradb::NamedProperty::new(
455            required_field("name", self.name)?.try_into()?,
456            required_field("value", self.value)?.try_into()?,
457        ))
458    }
459}
460
461impl From<indradb::VertexProperty> for crate::VertexProperty {
462    fn from(prop: indradb::VertexProperty) -> Self {
463        crate::VertexProperty {
464            id: Some(prop.id.into()),
465            value: Some(prop.value.into()),
466        }
467    }
468}
469
470impl TryInto<indradb::VertexProperty> for crate::VertexProperty {
471    type Error = ConversionError;
472
473    fn try_into(self) -> Result<indradb::VertexProperty, Self::Error> {
474        Ok(indradb::VertexProperty::new(
475            required_field("id", self.id)?.try_into()?,
476            required_field("value", self.value)?.try_into()?,
477        ))
478    }
479}
480
481impl From<indradb::VertexProperties> for crate::VertexProperties {
482    fn from(props: indradb::VertexProperties) -> Self {
483        crate::VertexProperties {
484            vertex: Some(props.vertex.into()),
485            props: props.props.into_iter().map(|prop| prop.into()).collect(),
486        }
487    }
488}
489
490impl TryInto<indradb::VertexProperties> for crate::VertexProperties {
491    type Error = ConversionError;
492
493    fn try_into(self) -> Result<indradb::VertexProperties, Self::Error> {
494        let props: Result<Vec<indradb::NamedProperty>, ConversionError> =
495            self.props.into_iter().map(|prop| prop.try_into()).collect();
496        Ok(indradb::VertexProperties::new(
497            required_field("vertex", self.vertex)?.try_into()?,
498            props?,
499        ))
500    }
501}
502
503impl From<indradb::EdgeProperty> for crate::EdgeProperty {
504    fn from(prop: indradb::EdgeProperty) -> Self {
505        crate::EdgeProperty {
506            edge: Some(prop.edge.into()),
507            value: Some(prop.value.into()),
508        }
509    }
510}
511
512impl TryInto<indradb::EdgeProperty> for crate::EdgeProperty {
513    type Error = ConversionError;
514
515    fn try_into(self) -> Result<indradb::EdgeProperty, Self::Error> {
516        Ok(indradb::EdgeProperty::new(
517            required_field("edge", self.edge)?.try_into()?,
518            required_field("value", self.value)?.try_into()?,
519        ))
520    }
521}
522
523impl From<indradb::EdgeProperties> for crate::EdgeProperties {
524    fn from(props: indradb::EdgeProperties) -> Self {
525        crate::EdgeProperties {
526            edge: Some(props.edge.into()),
527            props: props.props.into_iter().map(|prop| prop.into()).collect(),
528        }
529    }
530}
531
532impl TryInto<indradb::EdgeProperties> for crate::EdgeProperties {
533    type Error = ConversionError;
534
535    fn try_into(self) -> Result<indradb::EdgeProperties, Self::Error> {
536        let props: Result<Vec<indradb::NamedProperty>, ConversionError> =
537            self.props.into_iter().map(|prop| prop.try_into()).collect();
538        Ok(indradb::EdgeProperties::new(
539            required_field("edge", self.edge)?.try_into()?,
540            props?,
541        ))
542    }
543}
544
545impl From<indradb::BulkInsertItem> for crate::BulkInsertItem {
546    fn from(item: indradb::BulkInsertItem) -> Self {
547        crate::BulkInsertItem {
548            item: Some(match item {
549                indradb::BulkInsertItem::Vertex(vertex) => crate::BulkInsertItemVariant::Vertex(vertex.into()),
550                indradb::BulkInsertItem::Edge(edge) => crate::BulkInsertItemVariant::Edge(edge.into()),
551                indradb::BulkInsertItem::VertexProperty(id, name, value) => {
552                    crate::BulkInsertItemVariant::VertexProperty(crate::VertexPropertyBulkInsertItem {
553                        id: Some(id.into()),
554                        name: Some(name.into()),
555                        value: Some(value.into()),
556                    })
557                }
558                indradb::BulkInsertItem::EdgeProperty(edge, name, value) => {
559                    crate::BulkInsertItemVariant::EdgeProperty(crate::EdgePropertyBulkInsertItem {
560                        edge: Some(edge.into()),
561                        name: Some(name.into()),
562                        value: Some(value.into()),
563                    })
564                }
565            }),
566        }
567    }
568}
569
570impl TryInto<indradb::BulkInsertItem> for crate::BulkInsertItem {
571    type Error = ConversionError;
572
573    fn try_into(self) -> Result<indradb::BulkInsertItem, Self::Error> {
574        Ok(match required_field("item", self.item)? {
575            crate::BulkInsertItemVariant::Vertex(vertex) => indradb::BulkInsertItem::Vertex(vertex.try_into()?),
576            crate::BulkInsertItemVariant::Edge(edge) => indradb::BulkInsertItem::Edge(edge.try_into()?),
577            crate::BulkInsertItemVariant::VertexProperty(item) => indradb::BulkInsertItem::VertexProperty(
578                required_field("id", item.id)?.try_into()?,
579                required_field("name", item.name)?.try_into()?,
580                required_field("value", item.value)?.try_into()?,
581            ),
582            crate::BulkInsertItemVariant::EdgeProperty(item) => indradb::BulkInsertItem::EdgeProperty(
583                required_field("edge", item.edge)?.try_into()?,
584                required_field("name", item.name)?.try_into()?,
585                required_field("value", item.value)?.try_into()?,
586            ),
587        })
588    }
589}
590
591impl TryInto<indradb::Identifier> for crate::IndexPropertyRequest {
592    type Error = ConversionError;
593
594    fn try_into(self) -> Result<indradb::Identifier, Self::Error> {
595        let name = required_field("name", self.name)?.try_into()?;
596        Ok(name)
597    }
598}
599
600impl TryInto<(indradb::Query, indradb::Identifier, indradb::Json)> for crate::SetPropertiesRequest {
601    type Error = ConversionError;
602
603    fn try_into(self) -> Result<(indradb::Query, indradb::Identifier, indradb::Json), Self::Error> {
604        let q = required_field("q", self.q)?.try_into()?;
605        let name = required_field("name", self.name)?.try_into()?;
606        let value = required_field("value", self.value)?.try_into()?;
607        Ok((q, name, value))
608    }
609}
610
611impl From<(indradb::Query, indradb::Identifier, indradb::Json)> for crate::SetPropertiesRequest {
612    fn from(value: (indradb::Query, indradb::Identifier, indradb::Json)) -> Self {
613        crate::SetPropertiesRequest {
614            q: Some(value.0.into()),
615            name: Some(value.1.into()),
616            value: Some(value.2.into()),
617        }
618    }
619}