use crate::{
types::{
serde::DeError, BoltList, BoltMap, BoltNode, BoltPath, BoltPoint2D, BoltPoint3D,
BoltRelation, BoltUnboundedRelation,
},
BoltType,
};
use serde::Deserialize;
use std::convert::TryInto;
#[derive(Debug)]
pub struct Row {
attributes: BoltMap,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Node {
inner: BoltNode,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Path {
inner: BoltPath,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Relation {
inner: BoltRelation,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UnboundedRelation {
inner: BoltUnboundedRelation,
}
pub struct Point2D {
inner: BoltPoint2D,
}
pub struct Point3D {
inner: BoltPoint3D,
}
impl Path {
pub fn new(inner: BoltPath) -> Self {
Path { inner }
}
#[deprecated(since = "0.7.0", note = "Please use `indices` instead.")]
pub fn ids(&self) -> Vec<i64> {
self.indices()
}
pub fn indices(&self) -> Vec<i64> {
self.indices_as().unwrap()
}
pub fn nodes(&self) -> Vec<Node> {
self.nodes_as().unwrap()
}
pub fn rels(&self) -> Vec<UnboundedRelation> {
self.relationships_as().unwrap()
}
pub fn to<'this, T>(&'this self) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
self.inner.to::<T>()
}
pub fn nodes_as<'this, T>(&'this self) -> Result<Vec<T>, DeError>
where
T: Deserialize<'this>,
{
Ok(self.to::<crate::Nodes<T>>()?.0)
}
pub fn relationships_as<'this, T>(&'this self) -> Result<Vec<T>, DeError>
where
T: Deserialize<'this>,
{
Ok(self.to::<crate::Relationships<T>>()?.0)
}
pub fn indices_as<'this, T>(&'this self) -> Result<Vec<T>, DeError>
where
T: Deserialize<'this>,
{
Ok(self.to::<crate::Indices<T>>()?.0)
}
}
impl Point2D {
pub fn new(inner: BoltPoint2D) -> Self {
Point2D { inner }
}
pub fn sr_id(&self) -> i64 {
self.inner.sr_id.value
}
pub fn x(&self) -> f64 {
self.inner.x.value
}
pub fn y(&self) -> f64 {
self.inner.y.value
}
}
impl Point3D {
pub fn new(inner: BoltPoint3D) -> Self {
Point3D { inner }
}
pub fn sr_id(&self) -> i64 {
self.inner.sr_id.value
}
pub fn x(&self) -> f64 {
self.inner.x.value
}
pub fn y(&self) -> f64 {
self.inner.y.value
}
pub fn z(&self) -> f64 {
self.inner.z.value
}
}
impl Row {
pub fn new(fields: BoltList, data: BoltList) -> Self {
let mut attributes = BoltMap::with_capacity(fields.len());
for (field, value) in fields.into_iter().zip(data.into_iter()) {
if let Ok(key) = field.try_into() {
attributes.put(key, value);
}
}
Row { attributes }
}
pub fn get<'this, T>(&'this self, key: &str) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
self.attributes.get::<T>(key)
}
pub fn to<'this, T>(&'this self) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
self.to_strict::<T>().or_else(|e| match self.single() {
Some(single) => single.to::<T>(),
None => Err(e),
})
}
pub fn to_strict<'this, T>(&'this self) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
self.attributes.to::<T>()
}
fn single(&self) -> Option<&BoltType> {
let mut values = self.attributes.value.values();
let first = values.next()?;
if values.next().is_some() {
return None;
}
Some(first)
}
}
impl Node {
pub fn new(inner: BoltNode) -> Self {
Node { inner }
}
pub fn id(&self) -> i64 {
self.inner.id.value
}
pub fn labels(&self) -> Vec<&str> {
self.to::<crate::Labels<_>>().unwrap().0
}
pub fn keys(&self) -> Vec<&str> {
self.to::<crate::Keys<_>>().unwrap().0
}
pub fn get<'this, T>(&'this self, key: &str) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
self.inner.properties.get::<T>(key)
}
pub fn to<'this, T>(&'this self) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
self.inner.to::<T>()
}
}
impl Relation {
pub fn new(inner: BoltRelation) -> Self {
Relation { inner }
}
pub fn id(&self) -> i64 {
self.inner.id.value
}
pub fn start_node_id(&self) -> i64 {
self.inner.start_node_id.value
}
pub fn end_node_id(&self) -> i64 {
self.inner.end_node_id.value
}
pub fn typ(&self) -> &str {
self.to::<crate::Type<_>>().unwrap().0
}
pub fn keys(&self) -> Vec<&str> {
self.to::<crate::Keys<_>>().unwrap().0
}
pub fn get<'this, T>(&'this self, key: &str) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
self.inner.properties.get::<T>(key)
}
pub fn to<'this, T>(&'this self) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
self.inner.to::<T>()
}
}
impl UnboundedRelation {
pub fn new(inner: BoltUnboundedRelation) -> Self {
UnboundedRelation { inner }
}
pub fn id(&self) -> i64 {
self.inner.id.value
}
pub fn typ(&self) -> &str {
self.to::<crate::Type<_>>().unwrap().0
}
pub fn keys(&self) -> Vec<&str> {
self.to::<crate::Keys<_>>().unwrap().0
}
pub fn get<'this, T>(&'this self, key: &str) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
self.inner.properties.get::<T>(key)
}
pub fn to<'this, T>(&'this self) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
self.inner.to::<T>()
}
}
#[cfg(test)]
mod tests {
use serde::Deserialize;
use crate::types::{BoltString, BoltType};
use super::*;
#[test]
fn row_serializes_from_fields() {
#[derive(Clone, Debug, PartialEq, Deserialize)]
struct Person0 {
name: String,
age: i32,
score: f64,
awesome: bool,
#[serde(with = "serde_bytes")]
data: Vec<u8>,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
struct Person1<'a> {
name: &'a str,
age: i32,
score: f64,
awesome: bool,
#[serde(with = "serde_bytes")]
data: &'a [u8],
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
struct Couple<'a> {
p0: Person0,
#[serde(borrow)]
p1: Person1<'a>,
}
let row = {
let fields = BoltList::from(vec![BoltType::from("p0"), BoltType::from("p1")]);
let data = BoltList::from(vec![
BoltType::Map(
[
(BoltString::from("name"), BoltType::from("Alice")),
(BoltString::from("age"), BoltType::from(42)),
(BoltString::from("score"), BoltType::from(4.2)),
(BoltString::from("awesome"), BoltType::from(true)),
(BoltString::from("data"), BoltType::from(vec![4_u8, 2])),
]
.into_iter()
.collect(),
),
BoltType::Map(
[
(BoltString::from("name"), BoltType::from("Bob")),
(BoltString::from("age"), BoltType::from(1337)),
(BoltString::from("score"), BoltType::from(13.37)),
(BoltString::from("awesome"), BoltType::from(false)),
(
BoltString::from("data"),
BoltType::from(vec![1_u8, 3, 3, 7]),
),
]
.into_iter()
.collect(),
),
]);
Row::new(fields, data)
};
let actual = row.to::<Couple>().unwrap();
let expected = Couple {
p0: Person0 {
name: "Alice".to_owned(),
age: 42,
score: 4.2,
awesome: true,
data: vec![4, 2],
},
p1: Person1 {
name: "Bob",
age: 1337,
score: 13.37,
awesome: false, data: &[1, 3, 3, 7],
},
};
assert_eq!(actual, expected);
}
}