use crate::{
types::{
serde::{
date_time::BoltDateTimeVisitor,
element::ElementDataDeserializer,
node::BoltNodeVisitor,
path::BoltPathVisitor,
point::{self, BoltPointDeserializer, BoltPointVisitor},
rel::BoltRelationVisitor,
urel::BoltUnboundedRelationVisitor,
BoltKind,
},
BoltBoolean, BoltBytes, BoltDate, BoltDateTime, BoltDateTimeZoneId, BoltFloat, BoltInteger,
BoltList, BoltLocalDateTime, BoltLocalTime, BoltMap, BoltNull, BoltString, BoltTime,
BoltType,
},
DeError,
};
use std::{fmt, result::Result};
use bytes::Bytes;
use serde::{
de::{
value::{
BorrowedBytesDeserializer, BorrowedStrDeserializer, MapDeserializer, SeqDeserializer,
},
DeserializeSeed, Deserializer, EnumAccess, Error, Expected, IntoDeserializer,
Unexpected as Unexp, VariantAccess, Visitor,
},
Deserialize,
};
impl<'de> Deserialize<'de> for BoltType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_enum(std::any::type_name::<BoltType>(), &[], BoltTypeVisitor)
}
}
impl BoltType {
pub(crate) fn to<'this, T>(&'this self) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
T::deserialize(self.into_deserializer())
}
}
impl BoltMap {
pub(crate) fn to<'this, T>(&'this self) -> Result<T, DeError>
where
T: Deserialize<'this>,
{
T::deserialize(MapDeserializer::new(self.value.iter()))
}
}
struct BoltTypeVisitor;
impl<'de> Visitor<'de> for BoltTypeVisitor {
type Value = BoltType;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a valid bolt type")
}
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where
E: Error,
{
Ok(BoltType::Boolean(BoltBoolean::new(v)))
}
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: Error,
{
Ok(BoltType::Integer(BoltInteger::new(v)))
}
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: Error,
{
match i64::try_from(v) {
Ok(v) => self.visit_i64(v),
Err(_) => Err(E::custom(format!("i128 out of range: {}", v))),
}
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: Error,
{
match i64::try_from(v) {
Ok(v) => self.visit_i64(v),
Err(_) => Err(E::custom(format!("u64 out of range: {}", v))),
}
}
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: Error,
{
match i64::try_from(v) {
Ok(v) => self.visit_i64(v),
Err(_) => Err(E::custom(format!("u128 out of range: {}", v))),
}
}
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
where
E: Error,
{
Ok(BoltType::Float(BoltFloat::new(v)))
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
Ok(BoltType::String(BoltString::new(v)))
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
Ok(BoltType::Bytes(BoltBytes::new(Bytes::copy_from_slice(v))))
}
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: Error,
{
Ok(BoltType::Null(BoltNull))
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
::serde::de::Deserialize::deserialize(deserializer)
}
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: Error,
{
Ok(BoltType::Null(BoltNull))
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
self.visit_some(deserializer)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: ::serde::de::SeqAccess<'de>,
{
let mut items = match seq.size_hint() {
Some(s) => BoltList::with_capacity(s),
None => BoltList::new(),
};
while let Some(next) = seq.next_element()? {
items.push(next);
}
Ok(BoltType::List(items))
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: ::serde::de::MapAccess<'de>,
{
let mut items = match map.size_hint() {
Some(s) => BoltMap::with_capacity(s),
None => BoltMap::new(),
};
while let Some((key, value)) = map.next_entry()? {
items.put(key, value);
}
Ok(BoltType::Map(items))
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: Error,
{
Ok(BoltType::String(BoltString { value: v }))
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: Error,
{
Ok(BoltType::Bytes(BoltBytes {
value: Bytes::from(v),
}))
}
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: serde::de::EnumAccess<'de>,
{
let (kind, variant): (BoltKind, _) = data.variant()?;
match kind {
BoltKind::Null => variant.tuple_variant(1, self),
BoltKind::String => variant.tuple_variant(1, self),
BoltKind::Boolean => variant.tuple_variant(1, self),
BoltKind::Map => variant.tuple_variant(1, self),
BoltKind::Integer => variant.tuple_variant(1, self),
BoltKind::Float => variant.tuple_variant(1, self),
BoltKind::List => variant.tuple_variant(1, self),
BoltKind::Node => variant
.tuple_variant(1, BoltNodeVisitor)
.map(BoltType::Node),
BoltKind::Relation => variant
.tuple_variant(1, BoltRelationVisitor)
.map(BoltType::Relation),
BoltKind::UnboundedRelation => variant
.tuple_variant(1, BoltUnboundedRelationVisitor)
.map(BoltType::UnboundedRelation),
BoltKind::Point2D => variant
.struct_variant(
&point::Field::NAMES[..3],
BoltPointVisitor::_2d::<A::Error>(),
)
.map(BoltType::Point2D),
BoltKind::Point3D => variant
.struct_variant(point::Field::NAMES, BoltPointVisitor::_3d::<A::Error>())
.map(BoltType::Point3D),
BoltKind::Bytes => variant.tuple_variant(1, self),
BoltKind::Path => variant
.tuple_variant(1, BoltPathVisitor)
.map(BoltType::Path),
BoltKind::Duration => variant.tuple_variant(1, self),
BoltKind::Date => variant
.tuple_variant(1, BoltDateTimeVisitor::<BoltDate>::new())
.map(BoltType::Date),
BoltKind::Time => variant
.tuple_variant(1, BoltDateTimeVisitor::<BoltTime>::new())
.map(BoltType::Time),
BoltKind::LocalTime => variant
.tuple_variant(1, BoltDateTimeVisitor::<BoltLocalTime>::new())
.map(BoltType::LocalTime),
BoltKind::DateTime => variant
.tuple_variant(1, BoltDateTimeVisitor::<BoltDateTime>::new())
.map(BoltType::DateTime),
BoltKind::LocalDateTime => variant
.tuple_variant(1, BoltDateTimeVisitor::<BoltLocalDateTime>::new())
.map(BoltType::LocalDateTime),
BoltKind::DateTimeZoneId => variant
.tuple_variant(1, BoltDateTimeVisitor::<BoltDateTimeZoneId>::new())
.map(BoltType::DateTimeZoneId),
}
}
}
pub struct BoltTypeDeserializer<'de> {
value: &'de BoltType,
}
impl<'de> Deserializer<'de> for BoltTypeDeserializer<'de> {
type Error = DeError;
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.value {
BoltType::List(v) => visitor.visit_seq(SeqDeserializer::new(v.value.iter())),
BoltType::Bytes(v) => visitor.visit_seq(SeqDeserializer::new(v.value.iter().copied())),
BoltType::Point2D(p) => p.into_deserializer().deserialize_seq(visitor),
BoltType::Point3D(p) => p.into_deserializer().deserialize_seq(visitor),
_ => self.unexpected(visitor),
}
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.value {
BoltType::Map(v) => visitor.visit_map(MapDeserializer::new(v.value.iter())),
BoltType::Node(v) => v.into_deserializer().deserialize_map(visitor),
BoltType::Relation(v) => v.into_deserializer().deserialize_map(visitor),
BoltType::UnboundedRelation(v) => v.into_deserializer().deserialize_map(visitor),
BoltType::Path(p) => p.into_deserializer().deserialize_map(visitor),
BoltType::Point2D(p) => p.into_deserializer().deserialize_map(visitor),
BoltType::Point3D(p) => p.into_deserializer().deserialize_map(visitor),
_ => self.unexpected(visitor),
}
}
fn deserialize_struct<V>(
self,
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.value {
BoltType::Map(v) => visitor.visit_map(MapDeserializer::new(v.value.iter())),
BoltType::Node(v) => v
.into_deserializer()
.deserialize_struct(name, fields, visitor),
BoltType::Relation(v) => v
.into_deserializer()
.deserialize_struct(name, fields, visitor),
BoltType::UnboundedRelation(v) => v
.into_deserializer()
.deserialize_struct(name, fields, visitor),
BoltType::Path(p) => p
.into_deserializer()
.deserialize_struct(name, fields, visitor),
BoltType::Point2D(p) => p
.into_deserializer()
.deserialize_struct(name, fields, visitor),
BoltType::Point3D(p) => p
.into_deserializer()
.deserialize_struct(name, fields, visitor),
BoltType::Duration(d) => visitor.visit_seq(d.seq_access()),
_ => self.unexpected(visitor),
}
}
fn deserialize_newtype_struct<V>(
self,
name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.value {
BoltType::Node(v) => v
.into_deserializer()
.deserialize_newtype_struct(name, visitor),
BoltType::Relation(v) => v
.into_deserializer()
.deserialize_newtype_struct(name, visitor),
BoltType::UnboundedRelation(v) => v
.into_deserializer()
.deserialize_newtype_struct(name, visitor),
BoltType::Path(p) => p
.into_deserializer()
.deserialize_newtype_struct(name, visitor),
BoltType::Point2D(p) => p
.into_deserializer()
.deserialize_newtype_struct(name, visitor),
BoltType::Point3D(p) => p
.into_deserializer()
.deserialize_newtype_struct(name, visitor),
BoltType::Duration(d) => visitor.visit_seq(d.seq_access()),
BoltType::DateTimeZoneId(dtz) if name == "Timezone" => {
visitor.visit_newtype_struct(BorrowedStrDeserializer::new(dtz.tz_id()))
}
_ => visitor.visit_newtype_struct(self),
}
}
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.value {
BoltType::List(v) if v.len() == len => {
visitor.visit_seq(SeqDeserializer::new(v.value.iter()))
}
BoltType::Point2D(p) => p.into_deserializer().deserialize_tuple(len, visitor),
BoltType::Point3D(p) => p.into_deserializer().deserialize_tuple(len, visitor),
BoltType::Duration(d) if len == 2 => visitor.visit_seq(d.seq_access()),
BoltType::DateTimeZoneId(dtz) => visitor.visit_seq(
dtz.seq_access(
std::any::type_name::<V>()
.contains("TupleVisitor<chrono::naive::datetime::NaiveDateTime,"),
),
),
BoltType::LocalTime(t) if len == 2 => visitor.visit_seq(t.seq_access()),
BoltType::Time(t) if len == 2 => visitor.visit_seq(t.seq_access()),
_ => self.unexpected(visitor),
}
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_tuple(len, visitor)
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.value {
BoltType::String(v) => visitor.visit_borrowed_str(&v.value),
BoltType::Date(_)
| BoltType::Time(_)
| BoltType::LocalTime(_)
| BoltType::DateTime(_)
| BoltType::LocalDateTime(_)
| BoltType::DateTimeZoneId(_) => self.deserialize_string(visitor),
_ => self.unexpected(visitor),
}
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.value {
BoltType::String(v) => visitor.visit_string(v.value.clone()),
BoltType::Date(v) => {
let date = v.try_to_chrono().map_err(|_| {
Error::custom("Could not convert Neo4j Date into chrono::NaiveDate")
})?;
visitor.visit_string(date.to_string())
}
BoltType::Time(v) => {
let (time, _) = v.to_chrono();
visitor.visit_string(time.to_string())
}
BoltType::LocalTime(v) => {
let time = v.to_chrono();
visitor.visit_string(time.to_string())
}
BoltType::DateTime(datetime) => {
let datetime = datetime.try_to_chrono().map_err(|_| {
Error::custom("Could not convert Neo4j DateTime into chrono::DateTime")
})?;
let value = match std::any::type_name::<V>() {
"chrono::naive::datetime::serde::NaiveDateTimeVisitor" => {
format!("{:?}", datetime.naive_local())
}
_ => datetime.to_rfc3339(),
};
visitor.visit_string(value)
}
BoltType::LocalDateTime(ldt) => {
let ldt = ldt.try_to_chrono().map_err(|_| {
Error::custom(
"Could not convert Neo4j LocalDateTime into chrono::NaiveDateTime",
)
})?;
let ldt = format!("{:?}", ldt);
visitor.visit_string(ldt)
}
BoltType::DateTimeZoneId(dtz) => {
let dtz = dtz.try_to_chrono().map_err(|_| {
Error::custom("Could not convert Neo4j DateTimeZoneId into chrono::DateTime")
})?;
let value = match dbg!(std::any::type_name::<V>()) {
"chrono::naive::datetime::serde::NaiveDateTimeVisitor" => {
format!("{:?}", dtz.naive_local())
}
_ => dtz.to_rfc3339(),
};
visitor.visit_string(value)
}
_ => self.unexpected(visitor),
}
}
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let BoltType::Bytes(v) = self.value {
visitor.visit_borrowed_bytes(&v.value)
} else {
self.unexpected(visitor)
}
}
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let BoltType::Bytes(v) = self.value {
visitor.visit_byte_buf(v.value.to_vec())
} else {
self.unexpected(visitor)
}
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let BoltType::Boolean(v) = self.value {
visitor.visit_bool(v.value)
} else {
self.unexpected(visitor)
}
}
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let (v, visitor) = self.read_integer(visitor)?;
visitor.visit_i8(v)
}
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let (v, visitor) = self.read_integer(visitor)?;
visitor.visit_i16(v)
}
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let (v, visitor) = self.read_integer(visitor)?;
visitor.visit_i32(v)
}
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let (v, visitor) = self.read_integer(visitor)?;
visitor.visit_i64(v)
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let (v, visitor) = self.read_integer(visitor)?;
visitor.visit_u8(v)
}
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let (v, visitor) = self.read_integer(visitor)?;
visitor.visit_u16(v)
}
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let (v, visitor) = self.read_integer(visitor)?;
visitor.visit_u32(v)
}
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let (v, visitor) = self.read_integer(visitor)?;
visitor.visit_u64(v)
}
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let (v, visitor) = self.read_float(visitor)?;
visitor.visit_f32(v)
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let (v, visitor) = self.read_float(visitor)?;
visitor.visit_f64(v)
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let BoltType::Null(_) = self.value {
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let BoltType::Null(_) = self.value {
visitor.visit_unit()
} else {
self.unexpected(visitor)
}
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let BoltType::Null(_) = self.value {
visitor.visit_unit()
} else {
self.unexpected(visitor)
}
}
fn deserialize_enum<V>(
self,
name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if name == std::any::type_name::<BoltType>() {
visitor.visit_enum(BoltEnum { value: self.value })
} else {
visitor.visit_enum(CStyleEnum {
variant: self.value,
})
}
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_unit()
}
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.value {
BoltType::String(_) => self.deserialize_str(visitor),
BoltType::Boolean(_) => self.deserialize_bool(visitor),
BoltType::Map(_)
| BoltType::Node(_)
| BoltType::Relation(_)
| BoltType::UnboundedRelation(_)
| BoltType::Path(_)
| BoltType::Point2D(_)
| BoltType::Point3D(_) => self.deserialize_map(visitor),
BoltType::Null(_) => self.deserialize_unit(visitor),
BoltType::Integer(_) => self.deserialize_i64(visitor),
BoltType::Float(_) => self.deserialize_f64(visitor),
BoltType::List(_) | BoltType::Bytes(_) => self.deserialize_seq(visitor),
BoltType::Date(_)
| BoltType::Time(_)
| BoltType::LocalTime(_)
| BoltType::DateTime(_)
| BoltType::LocalDateTime(_)
| BoltType::DateTimeZoneId(_) => self.deserialize_string(visitor),
BoltType::Duration(_) => self.deserialize_newtype_struct("", visitor),
}
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.unexpected(visitor)
}
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.unexpected(visitor)
}
fn is_human_readable(&self) -> bool {
true
}
}
impl<'de> BoltTypeDeserializer<'de> {
fn new(value: &'de BoltType) -> Self {
Self { value }
}
fn read_integer<T, E, V>(self, visitor: V) -> Result<(T, V), DeError>
where
V: Visitor<'de>,
i64: TryInto<T, Error = E>,
E: Into<std::num::TryFromIntError>,
{
let integer = match self.value {
BoltType::Integer(v) => v.value,
BoltType::DateTime(dt) => match dt.try_to_chrono() {
Ok(dt) => match std::any::type_name::<V>().rsplit("::").next() {
Some("MicroSecondsTimestampVisitor") => dt.timestamp_micros(),
Some("MilliSecondsTimestampVisitor") => dt.timestamp_millis(),
Some("SecondsTimestampVisitor") => dt.timestamp(),
_ => dt.timestamp_nanos(),
},
Err(_) => return Err(DeError::DateTimeOutOfBounds(std::any::type_name::<T>())),
},
BoltType::LocalDateTime(ldt) => match ldt.try_to_chrono() {
Ok(ldt) => match std::any::type_name::<V>().rsplit("::").next() {
Some("MicroSecondsTimestampVisitor") => ldt.timestamp_micros(),
Some("MilliSecondsTimestampVisitor") => ldt.timestamp_millis(),
Some("SecondsTimestampVisitor") => ldt.timestamp(),
otherwise => {
dbg!(otherwise);
ldt.timestamp_nanos()
}
},
Err(_) => return Err(DeError::DateTimeOutOfBounds(std::any::type_name::<T>())),
},
_ => return self.unexpected(visitor),
};
match integer.try_into() {
Ok(v) => Ok((v, visitor)),
Err(e) => Err(DeError::IntegerOutOfBounds(
e.into(),
integer,
std::any::type_name::<T>(),
)),
}
}
fn read_float<T, V>(self, visitor: V) -> Result<(T, V), DeError>
where
V: Visitor<'de>,
T: FromFloat,
{
if let BoltType::Float(v) = self.value {
Ok((T::from_float(v.value), visitor))
} else {
self.unexpected(visitor)
}
}
fn unexpected<V, T>(self, visitor: V) -> Result<T, DeError>
where
V: Visitor<'de>,
{
self.value.unexpected(&visitor)
}
}
impl BoltType {
fn unexpected<T, E>(&self, expected: &E) -> Result<T, DeError>
where
E: Expected,
{
let typ = match self {
BoltType::String(v) => Unexp::Str(&v.value),
BoltType::Boolean(v) => Unexp::Bool(v.value),
BoltType::Map(_) => Unexp::Map,
BoltType::Null(_) => Unexp::Unit,
BoltType::Integer(v) => Unexp::Signed(v.value),
BoltType::Float(v) => Unexp::Float(v.value),
BoltType::List(_) => Unexp::Seq,
BoltType::Node(_) => Unexp::Map,
BoltType::Relation(_) => Unexp::Map,
BoltType::UnboundedRelation(_) => Unexp::Map,
BoltType::Point2D(_) => Unexp::Other("Point2D"),
BoltType::Point3D(_) => Unexp::Other("Point3D"),
BoltType::Bytes(v) => Unexp::Bytes(&v.value),
BoltType::Path(_) => Unexp::Other("Path"),
BoltType::Duration(_) => Unexp::Other("Duration"),
BoltType::Date(_) => Unexp::Other("Date"),
BoltType::Time(_) => Unexp::Other("Time"),
BoltType::LocalTime(_) => Unexp::Other("LocalTime"),
BoltType::DateTime(_) => Unexp::Other("DateTime"),
BoltType::LocalDateTime(_) => Unexp::Other("LocalDateTime"),
BoltType::DateTimeZoneId(_) => Unexp::Other("DateTimeZoneId"),
};
Err(DeError::invalid_type(typ, expected))
}
}
struct BoltEnum<'de> {
value: &'de BoltType,
}
impl<'de> EnumAccess<'de> for BoltEnum<'de> {
type Error = DeError;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: DeserializeSeed<'de>,
{
let kind = match self.value {
BoltType::String(_) => BoltKind::String,
BoltType::Boolean(_) => BoltKind::Boolean,
BoltType::Map(_) => BoltKind::Map,
BoltType::Null(_) => BoltKind::Null,
BoltType::Integer(_) => BoltKind::Integer,
BoltType::Float(_) => BoltKind::Float,
BoltType::List(_) => BoltKind::List,
BoltType::Node(_) => BoltKind::Node,
BoltType::Relation(_) => BoltKind::Relation,
BoltType::UnboundedRelation(_) => BoltKind::UnboundedRelation,
BoltType::Point2D(_) => BoltKind::Point2D,
BoltType::Point3D(_) => BoltKind::Point3D,
BoltType::Bytes(_) => BoltKind::Bytes,
BoltType::Path(_) => BoltKind::Path,
BoltType::Duration(_) => BoltKind::Duration,
BoltType::Date(_) => BoltKind::Date,
BoltType::Time(_) => BoltKind::Time,
BoltType::LocalTime(_) => BoltKind::LocalTime,
BoltType::DateTime(_) => BoltKind::DateTime,
BoltType::LocalDateTime(_) => BoltKind::LocalDateTime,
BoltType::DateTimeZoneId(_) => BoltKind::DateTimeZoneId,
};
let val = seed.deserialize(kind.into_deserializer())?;
Ok((val, self))
}
}
impl<'de> VariantAccess<'de> for BoltEnum<'de> {
type Error = DeError;
fn unit_variant(self) -> Result<(), Self::Error> {
Err(DeError::invalid_type(Unexp::TupleVariant, &"unit variant"))
}
fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
Err(DeError::invalid_type(
Unexp::TupleVariant,
&"newtype variant",
))
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.value {
BoltType::String(s) => visitor.visit_borrowed_str(&s.value),
BoltType::Boolean(b) => visitor.visit_bool(b.value),
BoltType::Map(m) => visitor.visit_map(MapDeserializer::new(m.value.iter())),
BoltType::Null(_) => visitor.visit_unit(),
BoltType::Integer(i) => visitor.visit_i64(i.value),
BoltType::Float(f) => visitor.visit_f64(f.value),
BoltType::List(l) => visitor.visit_seq(SeqDeserializer::new(l.value.iter())),
BoltType::Node(n) => ElementDataDeserializer::new(n).tuple_variant(len, visitor),
BoltType::Relation(r) => ElementDataDeserializer::new(r).tuple_variant(len, visitor),
BoltType::UnboundedRelation(r) => {
ElementDataDeserializer::new(r).tuple_variant(len, visitor)
}
BoltType::Point2D(p) => BoltPointDeserializer::new(p).deserialize_tuple(len, visitor),
BoltType::Point3D(p) => BoltPointDeserializer::new(p).deserialize_tuple(len, visitor),
BoltType::Bytes(b) => visitor.visit_borrowed_bytes(&b.value),
BoltType::Path(p) => ElementDataDeserializer::new(p).tuple_variant(len, visitor),
BoltType::Duration(d) => visitor.visit_seq(d.seq_access()),
BoltType::Date(d) => visitor.visit_map(d.map_access()),
BoltType::Time(t) => visitor.visit_map(t.map_access()),
BoltType::LocalTime(t) => visitor.visit_map(t.map_access()),
BoltType::DateTime(dt) => visitor.visit_map(dt.map_access()),
BoltType::LocalDateTime(dt) => visitor.visit_map(dt.map_access()),
BoltType::DateTimeZoneId(dt) => visitor.visit_map(dt.map_access()),
}
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
Err(DeError::invalid_type(
Unexp::TupleVariant,
&"struct variant",
))
}
}
struct CStyleEnum<'de> {
variant: &'de BoltType,
}
impl<'de> EnumAccess<'de> for CStyleEnum<'de> {
type Error = DeError;
type Variant = UnitVariant;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: DeserializeSeed<'de>,
{
let val = match self.variant {
BoltType::String(variant) => seed.deserialize(variant.into_deserializer())?,
BoltType::Bytes(variant) => seed.deserialize(variant.into_deserializer())?,
BoltType::Integer(variant) => seed.deserialize(variant.value.into_deserializer())?,
otherwise => {
otherwise.unexpected(&"string, bytes, or integer (valid enum identifier)")?
}
};
Ok((val, UnitVariant))
}
}
struct UnitVariant;
impl<'de> VariantAccess<'de> for UnitVariant {
type Error = DeError;
fn unit_variant(self) -> Result<(), Self::Error> {
Ok(())
}
fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
Err(DeError::invalid_type(
Unexp::NewtypeVariant,
&"unit variant",
))
}
fn tuple_variant<V>(self, _len: usize, _visitorr: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
Err(DeError::invalid_type(Unexp::TupleVariant, &"unit variant"))
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
Err(DeError::invalid_type(Unexp::StructVariant, &"unit variant"))
}
}
impl<'de> IntoDeserializer<'de, DeError> for &'de BoltType {
type Deserializer = BoltTypeDeserializer<'de>;
fn into_deserializer(self) -> Self::Deserializer {
BoltTypeDeserializer::new(self)
}
}
impl<'de> IntoDeserializer<'de, DeError> for &'de BoltString {
type Deserializer = BorrowedStrDeserializer<'de, DeError>;
fn into_deserializer(self) -> Self::Deserializer {
BorrowedStrDeserializer::new(&self.value)
}
}
impl<'de> IntoDeserializer<'de, DeError> for &'de BoltBytes {
type Deserializer = BorrowedBytesDeserializer<'de, DeError>;
fn into_deserializer(self) -> Self::Deserializer {
BorrowedBytesDeserializer::new(&self.value)
}
}
trait FromFloat {
fn from_float(f: f64) -> Self;
}
impl FromFloat for f32 {
fn from_float(f: f64) -> Self {
f as f32
}
}
impl FromFloat for f64 {
fn from_float(f: f64) -> Self {
f
}
}
#[cfg(test)]
mod tests {
use std::{borrow::Cow, collections::HashMap, fmt::Debug, net::SocketAddr, time::Duration};
use super::*;
use crate::{
types::{
BoltDate, BoltDateTime, BoltDateTimeZoneId, BoltDuration, BoltInteger,
BoltLocalDateTime, BoltLocalTime, BoltMap, BoltNode, BoltNull, BoltPoint2D,
BoltPoint3D, BoltRelation, BoltTime, BoltUnboundedRelation,
},
EndNodeId, Id, Keys, Labels, Node, Offset, Row, StartNodeId, Timezone, Type,
};
use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Timelike, Utc};
use serde::Deserialize;
#[test]
fn map_with_extra_fields() {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
struct Person {
name: String,
age: u8,
}
let map = [
(BoltString::from("name"), BoltType::from("Alice")),
(BoltString::from("age"), BoltType::from(42)),
(BoltString::from("bar"), BoltType::from(1337)),
]
.into_iter()
.collect::<BoltMap>();
let map = BoltType::Map(map);
let actual = map.to::<Person>().unwrap();
let expected = Person {
name: "Alice".into(),
age: 42,
};
assert_eq!(actual, expected);
}
#[test]
fn map_with_extra_fields_fails_for_deny_unknown_fields() {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[serde(deny_unknown_fields)]
struct Person {
name: String,
age: u8,
}
let map = [
(BoltString::from("name"), BoltType::from("Alice")),
(BoltString::from("age"), BoltType::from(42)),
(BoltString::from("bar"), BoltType::from(1337)),
]
.into_iter()
.collect::<BoltMap>();
let map = BoltType::Map(map);
assert!(map.to::<Person>().is_err());
}
#[test]
fn simple_struct() {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
struct Person {
name: String,
age: u8,
}
let map = [
(BoltString::from("name"), BoltType::from("Alice")),
(BoltString::from("age"), BoltType::from(42)),
]
.into_iter()
.collect::<BoltMap>();
let actual = map.to::<Person>().unwrap();
let expected = Person {
name: "Alice".into(),
age: 42,
};
assert_eq!(actual, expected);
}
#[test]
fn struct_with_null_value() {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
struct Person {
name: String,
age: Option<u8>,
}
let map = [
(BoltString::from("name"), BoltType::from("Alice")),
(BoltString::from("age"), BoltType::Null(BoltNull)),
]
.into_iter()
.collect::<BoltMap>();
let actual = map.to::<Person>().unwrap();
let expected = Person {
name: "Alice".into(),
age: None,
};
assert_eq!(actual, expected);
}
#[test]
fn tuple_struct_from_list() {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
struct Person(String, u8);
let list = BoltType::from(vec![BoltType::from("Alice"), BoltType::from(42)]);
let actual = list.to::<Person>().unwrap();
let expected = Person("Alice".into(), 42);
assert_eq!(actual, expected);
}
#[test]
fn tuple_struct_from_map_fails() {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
struct Person(String, u8);
let map = [
(BoltString::from("name"), BoltType::from("Alice")),
(BoltString::from("age"), BoltType::from(42)),
]
.into_iter()
.collect::<BoltMap>();
let map = BoltType::Map(map);
assert!(map.to::<Person>().is_err());
}
#[test]
fn node() {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
struct Person {
id: Id,
labels: Labels,
keys: Keys,
name: String,
age: u8,
}
let id = BoltInteger::new(1337);
let labels = vec!["Person".into()].into();
let properties = vec![
("name".into(), "Alice".into()),
("age".into(), 42_u16.into()),
]
.into_iter()
.collect();
let node = BoltNode {
id,
labels,
properties,
};
let node = BoltType::Node(node);
let actual = node.to::<Person>().unwrap();
let expected = Person {
id: Id(1337),
labels: Labels(vec!["Person".into()]),
keys: Keys(["name".into(), "age".into()].into()),
name: "Alice".into(),
age: 42,
};
assert_eq!(actual, expected);
}
#[test]
fn relation() {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
struct Person {
id: Id,
start: StartNodeId,
end: EndNodeId,
typ: Type,
keys: Keys,
name: String,
age: u8,
}
let id = BoltInteger::new(1337);
let start_node_id = BoltInteger::new(21);
let end_node_id = BoltInteger::new(84);
let typ = "Person".into();
let properties = vec![
("name".into(), "Alice".into()),
("age".into(), 42_u16.into()),
]
.into_iter()
.collect();
let relation = BoltRelation {
id,
start_node_id,
end_node_id,
properties,
typ,
};
let relation = BoltType::Relation(relation);
let actual = relation.to::<Person>().unwrap();
let expected = Person {
id: Id(1337),
start: StartNodeId(21),
end: EndNodeId(84),
typ: Type("Person".into()),
keys: Keys(["name".into(), "age".into()].into()),
name: "Alice".into(),
age: 42,
};
assert_eq!(actual, expected);
}
#[test]
fn unbounded_relation() {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
struct Person {
id: Id,
typ: Type,
keys: Keys,
name: String,
age: u8,
}
let id = BoltInteger::new(1337);
let typ = "Person".into();
let properties = vec![
("name".into(), "Alice".into()),
("age".into(), 42_u16.into()),
]
.into_iter()
.collect();
let relation = BoltUnboundedRelation {
id,
properties,
typ,
};
let relation = BoltType::UnboundedRelation(relation);
let actual = relation.to::<Person>().unwrap();
let expected = Person {
id: Id(1337),
typ: Type("Person".into()),
keys: Keys(["name".into(), "age".into()].into()),
name: "Alice".into(),
age: 42,
};
assert_eq!(actual, expected);
}
#[test]
fn tuple() {
let list = BoltType::from(vec![BoltType::from("Alice"), BoltType::from(42)]);
let actual = list.to::<(String, u8)>().unwrap();
let expected = ("Alice".into(), 42);
assert_eq!(actual, expected);
}
#[test]
fn borrowing_struct() {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
struct Person<'a> {
name: &'a str,
age: u8,
}
let map = [
(BoltString::from("name"), BoltType::from("Alice")),
(BoltString::from("age"), BoltType::from(42)),
]
.into_iter()
.collect::<BoltMap>();
let actual = map.to::<Person>().unwrap();
let expected = Person {
name: "Alice",
age: 42,
};
assert_eq!(actual, expected);
}
#[test]
fn various_types() {
#[derive(Clone, Debug, PartialEq, Deserialize)]
struct Bag<'a> {
borrowed: &'a str,
owned: String,
float: f64,
int: i32,
long: i64,
boolean: bool,
unit: (),
}
let map = [
(
BoltString::from("borrowed"),
BoltType::from("I am borrowed"),
),
(
BoltString::from("owned"),
BoltType::from("I am cloned and owned"),
),
(BoltString::from("float"), BoltType::from(13.37)),
(BoltString::from("int"), BoltType::from(42_i32)),
(BoltString::from("long"), BoltType::from(1337_i64)),
(BoltString::from("boolean"), BoltType::from(true)),
(BoltString::from("unit"), BoltType::Null(BoltNull)),
]
.into_iter()
.collect::<BoltMap>();
let actual = map.to::<Bag>().unwrap();
let expected = Bag {
borrowed: "I am borrowed",
owned: "I am cloned and owned".to_owned(),
float: 13.37,
int: 42,
long: 1337,
boolean: true,
unit: (),
};
assert_eq!(actual, expected);
}
#[test]
fn std_bytes() {
#[derive(Clone, Debug, PartialEq, Deserialize)]
struct Bytes<'a> {
bytes: Vec<u8>,
slice: &'a [u8],
}
let map = [
(BoltString::from("bytes"), BoltType::from(vec![4_u8, 2])),
(
BoltString::from("slice"),
BoltType::from(vec![1_u8, 3, 3, 7]),
),
]
.into_iter()
.collect::<BoltMap>();
let actual = map.to::<Bytes>().unwrap();
let expected = Bytes {
bytes: vec![4, 2],
slice: &[1, 3, 3, 7],
};
assert_eq!(actual, expected);
}
#[test]
fn serde_bytes_bytes() {
#[derive(Clone, Debug, PartialEq, Deserialize)]
struct Bytes<'a> {
#[serde(with = "serde_bytes")]
bytes: Vec<u8>,
#[serde(with = "serde_bytes")]
slice: &'a [u8],
}
let map = [
(BoltString::from("bytes"), BoltType::from(vec![4_u8, 2])),
(
BoltString::from("slice"),
BoltType::from(vec![1_u8, 3, 3, 7]),
),
]
.into_iter()
.collect::<BoltMap>();
let actual = map.to::<Bytes>().unwrap();
let expected = Bytes {
bytes: vec![4, 2],
slice: &[1, 3, 3, 7],
};
assert_eq!(actual, expected);
}
#[test]
fn serde_with_bytes() {
use serde_with::{serde_as, Bytes};
#[serde_as]
#[derive(Clone, Debug, PartialEq, Deserialize)]
struct AsBytes<'a> {
#[serde_as(as = "Bytes")]
array: [u8; 4],
#[serde_as(as = "Bytes")]
boxed: Box<[u8]>,
#[serde_as(as = "Bytes")]
#[serde(borrow)]
cow: Cow<'a, [u8]>,
#[serde_as(as = "Bytes")]
#[serde(borrow)]
cow_array: Cow<'a, [u8; 2]>,
#[serde_as(as = "Bytes")]
bytes: Vec<u8>,
#[serde_as(as = "Bytes")]
slice: &'a [u8],
}
let map = [
(
BoltString::from("array"),
BoltType::from(vec![1_u8, 3, 3, 7]),
),
(BoltString::from("boxed"), BoltType::from(vec![4_u8, 2])),
(BoltString::from("cow"), BoltType::from(vec![1_u8, 3, 3, 7])),
(BoltString::from("cow_array"), BoltType::from(vec![4_u8, 2])),
(
BoltString::from("bytes"),
BoltType::from(vec![1_u8, 3, 3, 7]),
),
(BoltString::from("slice"), BoltType::from(vec![4_u8, 2])),
]
.into_iter()
.collect::<BoltMap>();
let actual = map.to::<AsBytes>().unwrap();
let expected = AsBytes {
array: [1, 3, 3, 7],
boxed: vec![4, 2].into_boxed_slice(),
cow: vec![1_u8, 3, 3, 7].into(),
cow_array: Cow::Owned([4_u8, 2]),
bytes: vec![1, 3, 3, 7],
slice: &[4, 2],
};
assert_eq!(actual, expected);
}
#[test]
fn nested_struct() {
#[derive(Clone, Debug, PartialEq, Deserialize)]
struct Person {
name: String,
age: u32,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
struct Couple {
p0: Person,
p1: Person,
}
let map = [
(
BoltString::from("p0"),
BoltType::Map(
[
(BoltString::from("name"), BoltType::from("Alice")),
(BoltString::from("age"), BoltType::from(42)),
]
.into_iter()
.collect(),
),
),
(
BoltString::from("p1"),
BoltType::Map(
[
(BoltString::from("name"), BoltType::from("Bob")),
(BoltString::from("age"), BoltType::from(1337)),
]
.into_iter()
.collect(),
),
),
]
.into_iter()
.collect::<BoltMap>();
let actual = map.to::<Couple>().unwrap();
let expected = Couple {
p0: Person {
name: "Alice".into(),
age: 42,
},
p1: Person {
name: "Bob".into(),
age: 1337,
},
};
assert_eq!(actual, expected);
}
#[test]
fn list() {
let list = BoltType::from(vec![42_i64, 1337]);
let actual = list.to::<Vec<i64>>().unwrap();
assert_eq!(actual, vec![42_i64, 1337]);
}
#[test]
fn nested_list() {
#[derive(Debug, Deserialize, PartialEq)]
struct Foo {
bars: Vec<i64>,
}
let data = [(BoltString::from("bars"), BoltType::from(vec![42, 1337]))]
.into_iter()
.collect::<BoltMap>();
let actual = data.to::<Foo>().unwrap();
let expected = Foo {
bars: vec![42, 1337],
};
assert_eq!(actual, expected);
}
fn test_datetime() -> DateTime<FixedOffset> {
DateTime::parse_from_rfc3339("1999-07-14T13:37:42+02:00").unwrap()
}
#[test]
fn datetime() {
let expected = test_datetime();
let datetime = BoltDateTime::from(expected);
let datetime = BoltType::DateTime(datetime);
let actual = datetime.to::<DateTime<FixedOffset>>().unwrap();
assert_eq!(actual, expected);
}
#[test]
fn datetime_nanoseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::serde::ts_nanoseconds")]
datetime: DateTime<Utc>,
}
let expected = test_datetime();
let datetime = BoltDateTime::from(expected);
let datetime = BoltType::DateTime(datetime);
let actual = datetime.to::<S>().unwrap().datetime;
assert_eq!(actual, expected);
}
#[test]
fn datetime_opt_nanoseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::serde::ts_nanoseconds_option")]
datetime: Option<DateTime<Utc>>,
}
let expected = test_datetime();
let datetime = BoltDateTime::from(expected);
let datetime = BoltType::DateTime(datetime);
let actual = datetime.to::<S>().unwrap().datetime.unwrap();
assert_eq!(actual, expected);
}
#[test]
fn datetime_microseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::serde::ts_microseconds")]
datetime: DateTime<Utc>,
}
let expected = test_datetime();
let datetime = BoltDateTime::from(expected);
let datetime = BoltType::DateTime(datetime);
let actual = datetime.to::<S>().unwrap().datetime;
assert_eq!(actual, expected);
}
#[test]
fn datetime_opt_microseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::serde::ts_microseconds_option")]
datetime: Option<DateTime<Utc>>,
}
let expected = test_datetime();
let datetime = BoltDateTime::from(expected);
let datetime = BoltType::DateTime(datetime);
let actual = datetime.to::<S>().unwrap().datetime.unwrap();
assert_eq!(actual, expected);
}
#[test]
fn datetime_milliseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::serde::ts_milliseconds")]
datetime: DateTime<Utc>,
}
let expected = test_datetime();
let datetime = BoltDateTime::from(expected);
let datetime = BoltType::DateTime(datetime);
let actual = datetime.to::<S>().unwrap().datetime;
assert_eq!(actual, expected);
}
#[test]
fn datetime_opt_milliseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::serde::ts_milliseconds_option")]
datetime: Option<DateTime<Utc>>,
}
let expected = test_datetime();
let datetime = BoltDateTime::from(expected);
let datetime = BoltType::DateTime(datetime);
let actual = datetime.to::<S>().unwrap().datetime.unwrap();
assert_eq!(actual, expected);
}
#[test]
fn datetime_seconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::serde::ts_seconds")]
datetime: DateTime<Utc>,
}
let expected = test_datetime();
let datetime = BoltDateTime::from(expected);
let datetime = BoltType::DateTime(datetime);
let actual = datetime.to::<S>().unwrap().datetime;
assert_eq!(actual, expected);
}
#[test]
fn datetime_opt_seconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::serde::ts_seconds_option")]
datetime: Option<DateTime<Utc>>,
}
let expected = test_datetime();
let datetime = BoltDateTime::from(expected);
let datetime = BoltType::DateTime(datetime);
let actual = datetime.to::<S>().unwrap().datetime.unwrap();
assert_eq!(actual, expected);
}
fn test_local_datetime() -> NaiveDateTime {
NaiveDate::from_ymd_opt(1999, 7, 14)
.unwrap()
.and_hms_nano_opt(13, 37, 42, 421337420)
.unwrap()
}
#[test]
fn local_datetime() {
let expected = test_local_datetime();
let local_datetime = BoltLocalDateTime::from(test_local_datetime());
let local_datetime = BoltType::LocalDateTime(local_datetime);
let actual = local_datetime.to::<NaiveDateTime>().unwrap();
assert_eq!(actual, expected);
}
#[test]
fn local_datetime_nanoseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::naive::serde::ts_nanoseconds")]
local_datetime: NaiveDateTime,
}
let expected = test_local_datetime();
let local_datetime = BoltLocalDateTime::from(test_local_datetime());
let local_datetime = BoltType::LocalDateTime(local_datetime);
let actual = local_datetime.to::<S>().unwrap().local_datetime;
assert_eq!(actual, expected);
}
#[test]
fn local_datetime_opt_nanoseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::naive::serde::ts_nanoseconds_option")]
local_datetime: Option<NaiveDateTime>,
}
let expected = test_local_datetime();
let local_datetime = BoltLocalDateTime::from(test_local_datetime());
let local_datetime = BoltType::LocalDateTime(local_datetime);
let actual = local_datetime.to::<S>().unwrap().local_datetime.unwrap();
assert_eq!(actual, expected);
}
#[test]
fn local_datetime_microseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::naive::serde::ts_microseconds")]
local_datetime: NaiveDateTime,
}
let expected = test_local_datetime().with_nanosecond(421337000).unwrap();
let local_datetime = BoltLocalDateTime::from(test_local_datetime());
let local_datetime = BoltType::LocalDateTime(local_datetime);
let actual = local_datetime.to::<S>().unwrap().local_datetime;
assert_eq!(actual, expected);
}
#[test]
fn local_datetime_opt_microseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::naive::serde::ts_microseconds_option")]
local_datetime: Option<NaiveDateTime>,
}
let expected = test_local_datetime().with_nanosecond(421337000).unwrap();
let local_datetime = BoltLocalDateTime::from(test_local_datetime());
let local_datetime = BoltType::LocalDateTime(local_datetime);
let actual = local_datetime.to::<S>().unwrap().local_datetime.unwrap();
assert_eq!(actual, expected);
}
#[test]
fn local_datetime_milliseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::naive::serde::ts_milliseconds")]
local_datetime: NaiveDateTime,
}
let expected = test_local_datetime().with_nanosecond(421000000).unwrap();
let local_datetime = BoltLocalDateTime::from(test_local_datetime());
let local_datetime = BoltType::LocalDateTime(local_datetime);
let actual = local_datetime.to::<S>().unwrap().local_datetime;
assert_eq!(actual, expected);
}
#[test]
fn local_datetime_opt_milliseconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::naive::serde::ts_milliseconds_option")]
local_datetime: Option<NaiveDateTime>,
}
let expected = test_local_datetime().with_nanosecond(421000000).unwrap();
let local_datetime = BoltLocalDateTime::from(test_local_datetime());
let local_datetime = BoltType::LocalDateTime(local_datetime);
let actual = local_datetime.to::<S>().unwrap().local_datetime.unwrap();
assert_eq!(actual, expected);
}
#[test]
fn local_datetime_seconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::naive::serde::ts_seconds")]
local_datetime: NaiveDateTime,
}
let expected = test_local_datetime().with_nanosecond(0).unwrap();
let local_datetime = BoltLocalDateTime::from(test_local_datetime());
let local_datetime = BoltType::LocalDateTime(local_datetime);
let actual = local_datetime.to::<S>().unwrap().local_datetime;
assert_eq!(actual, expected);
}
#[test]
fn local_datetime_opt_seconds() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(transparent)]
struct S {
#[serde(with = "chrono::naive::serde::ts_seconds_option")]
local_datetime: Option<NaiveDateTime>,
}
let expected = test_local_datetime().with_nanosecond(0).unwrap();
let local_datetime = BoltLocalDateTime::from(test_local_datetime());
let local_datetime = BoltType::LocalDateTime(local_datetime);
let actual = local_datetime.to::<S>().unwrap().local_datetime.unwrap();
assert_eq!(actual, expected);
}
fn test_datetime_tz() -> DateTime<FixedOffset> {
test_local_datetime()
.and_local_timezone(FixedOffset::east_opt(2 * 3600).unwrap())
.unwrap()
}
#[test]
fn datetime_tz() {
let expected = test_datetime_tz();
let datetime_tz = BoltDateTimeZoneId::from((test_local_datetime(), "Europe/Paris"));
let datetime_tz = BoltType::DateTimeZoneId(datetime_tz);
let actual = datetime_tz.to::<DateTime<FixedOffset>>().unwrap();
assert_eq!(actual, expected);
}
#[test]
fn datetime_tz_info() {
let datetime_tz = BoltDateTimeZoneId::from((test_local_datetime(), "Europe/Paris"));
let datetime_tz = BoltType::DateTimeZoneId(datetime_tz);
let actual = datetime_tz.to::<Timezone>().unwrap().0;
assert_eq!(actual, "Europe/Paris");
}
#[test]
fn datetime_tz_with_info() {
let expected = test_datetime_tz();
let datetime_tz = BoltDateTimeZoneId::from((test_local_datetime(), "Europe/Paris"));
let datetime_tz = BoltType::DateTimeZoneId(datetime_tz);
let (datetime, timezone) = datetime_tz.to::<(DateTime<FixedOffset>, String)>().unwrap();
assert_eq!(datetime, expected);
assert_eq!(timezone, "Europe/Paris");
}
#[test]
fn datetime_as_naive_datetime() {
let expected = test_datetime().naive_local();
let datetime = BoltDateTime::from(test_datetime());
let datetime = BoltType::DateTime(datetime);
let datetime = datetime.to::<NaiveDateTime>().unwrap();
assert_eq!(datetime, expected);
}
#[test]
fn datetime_tz_as_naive_datetime() {
let expected = test_datetime_tz().naive_local();
let datetime = BoltDateTimeZoneId::from((test_local_datetime(), "Europe/Paris"));
let datetime = BoltType::DateTimeZoneId(datetime);
let datetime = datetime.to::<NaiveDateTime>().unwrap();
assert_eq!(datetime, expected);
}
#[test]
fn datetime_tz_as_naive_datetime_with_tz_info() {
let expected = test_datetime_tz().naive_local();
let datetime = BoltDateTimeZoneId::from((test_local_datetime(), "Europe/Paris"));
let datetime = BoltType::DateTimeZoneId(datetime);
let (datetime, tz) = datetime.to::<(NaiveDateTime, String)>().unwrap();
assert_eq!(datetime, expected);
assert_eq!(tz, "Europe/Paris");
}
#[test]
fn point_2d() {
#[derive(Debug, PartialEq, Deserialize)]
struct P {
x: f64,
y: f64,
}
let point = BoltType::Point2D(BoltPoint2D {
sr_id: 420.into(),
x: BoltFloat::new(42.0),
y: BoltFloat::new(13.37),
});
let actual = point.to::<P>().unwrap();
let expected = P { x: 42.0, y: 13.37 };
assert_eq!(actual, expected);
}
#[test]
fn point_3d() {
#[derive(Debug, PartialEq, Deserialize)]
struct P {
x: f64,
y: f64,
z: f64,
}
let point = BoltType::Point3D(BoltPoint3D {
sr_id: 420.into(),
x: BoltFloat::new(42.0),
y: BoltFloat::new(13.37),
z: BoltFloat::new(84.0),
});
let actual = point.to::<P>().unwrap();
let expected = P {
x: 42.0,
y: 13.37,
z: 84.0,
};
assert_eq!(actual, expected);
}
#[test]
fn duration() {
let duration = Duration::new(42, 1337);
let bolt = BoltType::Duration(BoltDuration::from(duration));
let actual = bolt.to::<std::time::Duration>().unwrap();
assert_eq!(actual, duration);
let actual = bolt.to::<time::Duration>().unwrap();
assert_eq!(actual, duration);
}
fn test_date() -> NaiveDate {
NaiveDate::from_ymd_opt(1999, 7, 14).unwrap()
}
#[test]
fn date() {
let date = test_date();
let bolt = BoltDate::from(date);
let bolt = BoltType::Date(bolt);
let actual = bolt.to::<NaiveDate>().unwrap();
assert_eq!(actual, date);
}
fn test_time() -> NaiveTime {
NaiveTime::from_hms_nano_opt(13, 37, 42, 421337420).unwrap()
}
#[test]
fn local_time() {
let time = test_time();
let bolt = BoltLocalTime::from(time);
let bolt = BoltType::LocalTime(bolt);
let actual = bolt.to::<NaiveTime>().unwrap();
assert_eq!(actual, time);
}
#[test]
fn local_time_optional_offset() {
let time = test_time();
let bolt = BoltLocalTime::from(time);
let bolt = BoltType::LocalTime(bolt);
let acutal = bolt.to::<(NaiveTime, Option<Offset>)>().unwrap();
assert_eq!(acutal.0, time);
assert_eq!(acutal.1, None);
}
#[test]
fn time() {
let time = test_time();
let bolt = BoltTime::from((time, FixedOffset::east_opt(2 * 3600).unwrap()));
let bolt = BoltType::Time(bolt);
let actual = bolt.to::<NaiveTime>().unwrap();
assert_eq!(actual, time);
}
#[test]
fn time_offset() {
let time = test_time();
let bolt = BoltTime::from((time, FixedOffset::east_opt(2 * 3600).unwrap()));
let bolt = BoltType::Time(bolt);
let actual = bolt.to::<(NaiveTime, Offset)>().unwrap();
assert_eq!(actual.0, time);
assert_eq!(actual.1 .0, FixedOffset::east_opt(2 * 3600).unwrap());
}
#[test]
fn time_optional_offset() {
let time = test_time();
let bolt = BoltTime::from((time, FixedOffset::east_opt(2 * 3600).unwrap()));
let bolt = BoltType::Time(bolt);
let actual = bolt.to::<(NaiveTime, Option<Offset>)>().unwrap();
assert_eq!(actual.0, time);
assert_eq!(
actual.1,
Some(Offset(FixedOffset::east_opt(2 * 3600).unwrap()))
);
}
#[test]
fn type_convert() {
let i = BoltType::from(42);
assert_eq!(i.to::<i8>().unwrap(), 42);
}
#[test]
fn type_convert_error() {
let i = BoltType::from(1337);
assert_eq!(
i.to::<i8>().unwrap_err().to_string(),
"Could not convert the integer `1337` to the target type i8"
);
}
#[test]
fn deserialize_roundtrips() {
let map = [
("age".into(), 42.into()),
("awesome".into(), true.into()),
("values".into(), vec![13.37, 42.84].into()),
("payload".into(), b"Hello, World!".as_slice().into()),
("secret".into(), BoltType::Null(BoltNull)),
("event".into(), test_datetime().into()),
("local_event".into(), test_local_datetime().into()),
("tz_event".into(), test_datetime_tz().into()),
("date_event".into(), test_date().into()),
("local_time_event".into(), test_time().into()),
(
"time_event".into(),
(test_time(), FixedOffset::east_opt(2 * 3600).unwrap()).into(),
),
]
.into_iter()
.collect::<BoltMap>();
let map = BoltType::Map(map);
let actual = map.to::<BoltType>().unwrap();
assert_eq!(actual, map);
}
#[test]
fn issue_108_example() {
#[derive(Debug, Deserialize, PartialEq)]
struct Model {
node: Node,
d_left: Option<Node>,
d_right: Option<Node>,
}
#[derive(Deserialize)]
struct Res {
res: Vec<Model>,
}
let model1 = BoltNode::new(BoltInteger::new(1), BoltList::new(), BoltMap::new());
let model2 = BoltNode::new(BoltInteger::new(2), BoltList::new(), BoltMap::new());
let models = HashMap::from_iter([("node", model1), ("d_left", model2)]);
let models = BoltList::from(vec![models.into()]);
let row = Row::new(
vec!["res".into()].into(),
vec![BoltType::List(models)].into(),
);
let m1 = row.get::<Vec<Model>>("res").unwrap();
let m2 = row.to::<Res>().unwrap().res;
assert_eq!(m1, m2);
assert_eq!(m1.len(), 1);
let m = &m1[0];
assert_eq!(m.node.id(), 1);
assert_eq!(m.d_left.as_ref().unwrap().id(), 2);
assert_eq!(m.d_right.as_ref(), None);
}
#[test]
fn deserialize_socket_addr() {
#[derive(Debug, Deserialize)]
struct Test {
addr: SocketAddr,
}
let value = BoltType::from("127.0.0.1:4242");
let value = [(BoltString::from("addr"), value)]
.into_iter()
.collect::<BoltMap>();
let value = BoltType::Map(value);
let actual = value.to::<Test>().unwrap();
assert_eq!(actual.addr, SocketAddr::from(([127, 0, 0, 1], 4242)));
}
#[test]
fn deserialize_some_c_style_enum() {
#[derive(Debug, Copy, Clone, Deserialize, PartialEq, Eq)]
enum Frobnicate {
Foo,
Moo,
Bing,
}
let value = BoltType::from("Foo");
let actual = value.to::<Frobnicate>().unwrap();
assert_eq!(actual, Frobnicate::Foo);
}
#[test]
fn deserialize_tuple_struct() {
#[derive(Deserialize, Debug)]
pub struct MyString(String);
#[derive(Deserialize, Debug)]
pub struct MyThing {
my_string: MyString,
}
let value = BoltType::from("Frobnicate");
let value = [(BoltString::from("my_string"), value)]
.into_iter()
.collect::<BoltMap>();
let value = BoltType::Map(value);
let actual = value.to::<MyThing>().unwrap();
assert_eq!(actual.my_string.0, "Frobnicate");
}
#[test]
fn deserialize_into_serde_json() {
let actual = [
("age".into(), 42.into()),
("awesome".into(), true.into()),
("values".into(), vec![13.37, 42.84].into()),
(
"nested".into(),
BoltType::Map([("key".into(), "value".into())].into_iter().collect()),
),
("payload".into(), b"Hello, World!".as_slice().into()),
("secret".into(), BoltType::Null(BoltNull)),
]
.into_iter()
.collect::<BoltMap>();
let actual = BoltType::Map(actual);
let actual = actual.to::<serde_json::Value>().unwrap();
let expected = serde_json::json!({
"age": 42,
"awesome": true,
"values": [13.37, 42.84],
"nested": {
"key": "value",
},
"payload": [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33],
"secret": null,
});
assert_eq!(actual, expected);
}
}