1use std::{
2 collections::HashMap,
3 mem,
4 panic::{catch_unwind, UnwindSafe},
5};
6
7use bytes::{Buf, BufMut, Bytes, BytesMut};
8use chrono::{
9 DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Offset, TimeZone, Timelike,
10};
11use chrono_tz::Tz;
12
13pub use duration::Duration;
14pub use node::Node;
15pub use path::Path;
16pub use point_2d::Point2D;
17pub use point_3d::Point3D;
18pub use relationship::Relationship;
19pub use unbound_relationship::UnboundRelationship;
20
21use crate::error::*;
22use crate::serialization::*;
23
24pub(crate) mod conversions;
25pub(crate) mod duration;
26pub(crate) mod node;
27pub(crate) mod path;
28pub(crate) mod point_2d;
29pub(crate) mod point_3d;
30pub(crate) mod relationship;
31pub(crate) mod unbound_relationship;
32
33pub(crate) const MARKER_FALSE: u8 = 0xC2;
34pub(crate) const MARKER_TRUE: u8 = 0xC3;
35pub(crate) const MARKER_INT_8: u8 = 0xC8;
36pub(crate) const MARKER_INT_16: u8 = 0xC9;
37pub(crate) const MARKER_INT_32: u8 = 0xCA;
38pub(crate) const MARKER_INT_64: u8 = 0xCB;
39pub(crate) const MARKER_FLOAT: u8 = 0xC1;
40pub(crate) const MARKER_SMALL_BYTES: u8 = 0xCC;
41pub(crate) const MARKER_MEDIUM_BYTES: u8 = 0xCD;
42pub(crate) const MARKER_LARGE_BYTES: u8 = 0xCE;
43pub(crate) const MARKER_TINY_LIST: u8 = 0x90;
44pub(crate) const MARKER_SMALL_LIST: u8 = 0xD4;
45pub(crate) const MARKER_MEDIUM_LIST: u8 = 0xD5;
46pub(crate) const MARKER_LARGE_LIST: u8 = 0xD6;
47pub(crate) const MARKER_TINY_MAP: u8 = 0xA0;
48pub(crate) const MARKER_SMALL_MAP: u8 = 0xD8;
49pub(crate) const MARKER_MEDIUM_MAP: u8 = 0xD9;
50pub(crate) const MARKER_LARGE_MAP: u8 = 0xDA;
51pub(crate) const MARKER_NULL: u8 = 0xC0;
52pub(crate) const MARKER_TINY_STRING: u8 = 0x80;
53pub(crate) const MARKER_SMALL_STRING: u8 = 0xD0;
54pub(crate) const MARKER_MEDIUM_STRING: u8 = 0xD1;
55pub(crate) const MARKER_LARGE_STRING: u8 = 0xD2;
56pub(crate) const MARKER_TINY_STRUCT: u8 = 0xB0;
57pub(crate) const MARKER_SMALL_STRUCT: u8 = 0xDC;
58pub(crate) const MARKER_MEDIUM_STRUCT: u8 = 0xDD;
59
60pub(crate) const SIGNATURE_NODE: u8 = 0x4E;
61pub(crate) const SIGNATURE_RELATIONSHIP: u8 = 0x52;
62pub(crate) const SIGNATURE_PATH: u8 = 0x50;
63pub(crate) const SIGNATURE_UNBOUND_RELATIONSHIP: u8 = 0x72;
64pub(crate) const SIGNATURE_DATE: u8 = 0x44;
65pub(crate) const SIGNATURE_TIME: u8 = 0x54;
66pub(crate) const SIGNATURE_DATE_TIME_OFFSET: u8 = 0x46;
67pub(crate) const SIGNATURE_DATE_TIME_ZONED: u8 = 0x66;
68pub(crate) const SIGNATURE_LOCAL_TIME: u8 = 0x74;
69pub(crate) const SIGNATURE_LOCAL_DATE_TIME: u8 = 0x64;
70pub(crate) const SIGNATURE_DURATION: u8 = 0x45;
71pub(crate) const SIGNATURE_POINT_2D: u8 = 0x58;
72pub(crate) const SIGNATURE_POINT_3D: u8 = 0x59;
73
74#[derive(Debug, Clone, PartialEq)]
83pub enum Value {
84 Boolean(bool),
86 Integer(i64),
87 Float(f64),
88 Bytes(Vec<u8>),
89 List(Vec<Value>),
90 Map(HashMap<String, Value>),
91 Null,
92 String(String),
93 Node(Node),
94 Relationship(Relationship),
95 Path(Path),
96 UnboundRelationship(UnboundRelationship),
97
98 Date(NaiveDate), Time(NaiveTime, FixedOffset), DateTimeOffset(DateTime<FixedOffset>), DateTimeZoned(DateTime<Tz>), LocalTime(NaiveTime), LocalDateTime(NaiveDateTime), Duration(Duration),
106 Point2D(Point2D),
107 Point3D(Point3D),
108}
109
110impl Eq for Value {
111 fn assert_receiver_is_total_eq(&self) {
112 if let Value::Float(_) | Value::Point2D(_) | Value::Point3D(_) = self {
113 panic!("{:?} does not impl Eq", self)
114 }
115 }
116}
117
118impl BoltValue for Value {
119 fn marker(&self) -> SerializeResult<u8> {
120 match self {
121 Value::Boolean(true) => Ok(MARKER_TRUE),
122 Value::Boolean(false) => Ok(MARKER_FALSE),
123 Value::Integer(integer) => match integer {
124 -9_223_372_036_854_775_808..=-2_147_483_649
125 | 2_147_483_648..=9_223_372_036_854_775_807 => Ok(MARKER_INT_64),
126 -2_147_483_648..=-32_769 | 32_768..=2_147_483_647 => Ok(MARKER_INT_32),
127 -32_768..=-129 | 128..=32_767 => Ok(MARKER_INT_16),
128 -128..=-17 => Ok(MARKER_INT_8),
129 -16..=127 => Ok(*integer as u8),
130 },
131 Value::Float(_) => Ok(MARKER_FLOAT),
132 Value::Bytes(bytes) => match bytes.len() {
133 0..=255 => Ok(MARKER_SMALL_BYTES),
134 256..=65_535 => Ok(MARKER_MEDIUM_BYTES),
135 65_536..=2_147_483_647 => Ok(MARKER_LARGE_BYTES),
136 _ => Err(SerializationError::ValueTooLarge(bytes.len())),
137 },
138 Value::List(list) => match list.len() {
139 0..=15 => Ok(MARKER_TINY_LIST | list.len() as u8),
140 16..=255 => Ok(MARKER_SMALL_LIST),
141 256..=65_535 => Ok(MARKER_MEDIUM_LIST),
142 65_536..=4_294_967_295 => Ok(MARKER_LARGE_LIST),
143 len => Err(SerializationError::ValueTooLarge(len)),
144 },
145 Value::Map(map) => match map.len() {
146 0..=15 => Ok(MARKER_TINY_MAP | map.len() as u8),
147 16..=255 => Ok(MARKER_SMALL_MAP),
148 256..=65_535 => Ok(MARKER_MEDIUM_MAP),
149 65_536..=4_294_967_295 => Ok(MARKER_LARGE_MAP),
150 _ => Err(SerializationError::ValueTooLarge(map.len())),
151 },
152 Value::Null => Ok(MARKER_NULL),
153 Value::String(string) => match string.len() {
154 0..=15 => Ok(MARKER_TINY_STRING | string.len() as u8),
155 16..=255 => Ok(MARKER_SMALL_STRING),
156 256..=65_535 => Ok(MARKER_MEDIUM_STRING),
157 65_536..=4_294_967_295 => Ok(MARKER_LARGE_STRING),
158 _ => Err(SerializationError::ValueTooLarge(string.len())),
159 },
160 Value::Node(node) => node.marker(),
161 Value::Relationship(rel) => rel.marker(),
162 Value::Path(path) => path.marker(),
163 Value::UnboundRelationship(unbound_rel) => unbound_rel.marker(),
164 Value::Date(_) => Ok(MARKER_TINY_STRUCT | 1),
165 Value::Time(_, _) => Ok(MARKER_TINY_STRUCT | 2),
166 Value::DateTimeOffset(_) => Ok(MARKER_TINY_STRUCT | 3),
167 Value::DateTimeZoned(_) => Ok(MARKER_TINY_STRUCT | 3),
168 Value::LocalTime(_) => Ok(MARKER_TINY_STRUCT | 1),
169 Value::LocalDateTime(_) => Ok(MARKER_TINY_STRUCT | 2),
170 Value::Duration(duration) => duration.marker(),
171 Value::Point2D(point_2d) => point_2d.marker(),
172 Value::Point3D(point_3d) => point_3d.marker(),
173 }
174 }
175
176 fn serialize(self) -> SerializeResult<Bytes> {
177 let marker = self.marker()?;
178 match self {
179 Value::Boolean(true) => Ok(Bytes::from_static(&[MARKER_TRUE])),
180 Value::Boolean(false) => Ok(Bytes::from_static(&[MARKER_FALSE])),
181 Value::Integer(integer) => {
182 let mut bytes =
184 BytesMut::with_capacity(mem::size_of::<u8>() + mem::size_of::<i64>());
185
186 bytes.put_u8(marker);
187 match integer {
188 -9_223_372_036_854_775_808..=-2_147_483_649
189 | 2_147_483_648..=9_223_372_036_854_775_807 => {
190 bytes.put_i64(integer);
191 }
192 -2_147_483_648..=-32_769 | 32_768..=2_147_483_647 => {
193 bytes.put_i32(integer as i32);
194 }
195 -32_768..=-129 | 128..=32_767 => {
196 bytes.put_i16(integer as i16);
197 }
198 -128..=-17 => {
199 bytes.put_i8(integer as i8);
200 }
201 -16..=127 => {} }
203
204 Ok(bytes.freeze())
205 }
206 Value::Float(f) => {
207 let mut bytes =
208 BytesMut::with_capacity(mem::size_of::<u8>() + mem::size_of::<f64>());
209 bytes.put_u8(marker);
210 bytes.put_f64(f);
211 Ok(bytes.freeze())
212 }
213 Value::Bytes(bytes) => {
214 let mut buf = BytesMut::with_capacity(
216 mem::size_of::<u8>() + mem::size_of::<u32>() + bytes.len(),
217 );
218
219 buf.put_u8(marker);
220 match bytes.len() {
221 0..=255 => buf.put_u8(bytes.len() as u8),
222 256..=65_535 => buf.put_u16(bytes.len() as u16),
223 65_536..=2_147_483_647 => buf.put_u32(bytes.len() as u32),
224 _ => return Err(SerializationError::ValueTooLarge(bytes.len())),
225 }
226 buf.put_slice(&bytes);
227
228 Ok(buf.freeze())
229 }
230 Value::List(list) => {
231 let length = list.len();
232 let mut total_value_bytes: usize = 0;
233 let mut value_bytes_vec: Vec<Bytes> = Vec::with_capacity(length);
234
235 for value in list {
236 let value_bytes = value.serialize()?;
237 total_value_bytes += value_bytes.len();
238 value_bytes_vec.push(value_bytes);
239 }
240
241 let mut bytes = BytesMut::with_capacity(
244 mem::size_of::<u8>() + mem::size_of::<u32>() + total_value_bytes,
245 );
246
247 bytes.put_u8(marker);
248 match length {
249 0..=15 => {} 16..=255 => bytes.put_u8(length as u8),
251 256..=65_535 => bytes.put_u16(length as u16),
252 65_536..=4_294_967_295 => bytes.put_u32(length as u32),
253 _ => return Err(SerializationError::ValueTooLarge(length)),
254 }
255
256 for value_bytes in value_bytes_vec {
257 bytes.put(value_bytes);
258 }
259
260 Ok(bytes.freeze())
261 }
262 Value::Map(map) => {
263 let length = map.len();
264
265 let mut total_value_bytes: usize = 0;
266 let mut value_bytes_vec: Vec<Bytes> = Vec::with_capacity(length);
267 for (key, val) in map {
268 let key_bytes: Bytes = Value::String(key).serialize()?;
269 let val_bytes: Bytes = val.serialize()?;
270 total_value_bytes += key_bytes.len() + val_bytes.len();
271 value_bytes_vec.push(key_bytes);
272 value_bytes_vec.push(val_bytes);
273 }
274 let mut bytes = BytesMut::with_capacity(
277 mem::size_of::<u8>() + mem::size_of::<u32>() + total_value_bytes,
278 );
279
280 bytes.put_u8(marker);
281 match length {
282 0..=15 => {} 16..=255 => bytes.put_u8(length as u8),
284 256..=65_535 => bytes.put_u16(length as u16),
285 65_536..=4_294_967_295 => bytes.put_u32(length as u32),
286 _ => return Err(SerializationError::ValueTooLarge(length)),
287 }
288
289 for value_bytes in value_bytes_vec {
290 bytes.put(value_bytes);
291 }
292
293 Ok(bytes.freeze())
294 }
295 Value::Null => Ok(Bytes::from_static(&[MARKER_NULL])),
296 Value::String(string) => {
297 let length = string.len();
298 let mut bytes =
300 BytesMut::with_capacity(mem::size_of::<u8>() + mem::size_of::<u32>() + length);
301
302 bytes.put_u8(marker);
303 match length {
304 0..=15 => {} 16..=255 => bytes.put_u8(length as u8),
306 256..=65_535 => bytes.put_u16(length as u16),
307 65_536..=4_294_967_295 => bytes.put_u32(length as u32),
308 _ => return Err(SerializationError::ValueTooLarge(length)),
309 }
310 bytes.put(string.as_bytes());
311
312 Ok(bytes.freeze())
313 }
314 Value::Node(node) => node.serialize(),
315 Value::Relationship(rel) => rel.serialize(),
316 Value::Path(path) => path.serialize(),
317 Value::UnboundRelationship(unbound_rel) => unbound_rel.serialize(),
318 Value::Date(date) => Ok(vec![marker, SIGNATURE_DATE]
319 .into_iter()
320 .chain(
321 Value::from((date - NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).num_days())
323 .serialize()?,
324 )
325 .collect()),
326 Value::Time(time, offset) => Ok(vec![marker, SIGNATURE_TIME]
327 .into_iter()
328 .chain(
329 Value::from(
332 i64::from(time.num_seconds_from_midnight()) * 1_000_000_000
333 + i64::from(time.nanosecond()),
334 )
335 .serialize()?,
336 )
337 .chain(
338 Value::from(offset.fix().local_minus_utc()).serialize()?,
340 )
341 .collect()),
342 Value::DateTimeOffset(date_time_offset) => Ok(vec![marker, SIGNATURE_DATE_TIME_OFFSET]
343 .into_iter()
344 .chain(
345 Value::from(date_time_offset.timestamp()).serialize()?,
347 )
348 .chain(
349 Value::from(i64::from(date_time_offset.nanosecond())).serialize()?,
351 )
352 .chain(
353 Value::from(date_time_offset.offset().fix().local_minus_utc()).serialize()?,
355 )
356 .collect()),
357 Value::DateTimeZoned(date_time_zoned) => {
358 Ok(vec![marker, SIGNATURE_DATE_TIME_ZONED]
359 .into_iter()
360 .chain(Value::from(date_time_zoned.timestamp()).serialize()?)
362 .chain(Value::from(i64::from(date_time_zoned.nanosecond())).serialize()?)
364 .chain(Value::from(date_time_zoned.timezone().name().to_string()).serialize()?)
366 .collect())
367 }
368 Value::LocalTime(local_time) => Ok(vec![marker, SIGNATURE_LOCAL_TIME]
369 .into_iter()
370 .chain(
371 Value::from(
372 i64::from(local_time.num_seconds_from_midnight()) * 1_000_000_000
374 + i64::from(local_time.nanosecond()),
375 )
376 .serialize()?,
377 )
378 .collect()),
379 Value::LocalDateTime(local_date_time) => Ok(vec![marker, SIGNATURE_LOCAL_DATE_TIME]
380 .into_iter()
381 .chain(Value::from(local_date_time.timestamp()).serialize()?)
383 .chain(Value::from(i64::from(local_date_time.nanosecond())).serialize()?)
385 .collect()),
386 Value::Duration(duration) => duration.serialize(),
387 Value::Point2D(point_2d) => point_2d.serialize(),
388 Value::Point3D(point_3d) => point_3d.serialize(),
389 }
390 }
391
392 fn deserialize<B: Buf + UnwindSafe>(mut bytes: B) -> DeserializeResult<(Self, B)> {
393 catch_unwind(move || {
394 let marker = bytes.get_u8();
395 match marker {
396 MARKER_TRUE => Ok((Value::Boolean(true), bytes)),
398 MARKER_FALSE => Ok((Value::Boolean(false), bytes)),
399 marker if (-16..=127).contains(&(marker as i8)) => {
401 Ok((Value::Integer(i64::from(marker as i8)), bytes))
402 }
403 MARKER_INT_8 => Ok((Value::Integer(i64::from(bytes.get_i8())), bytes)),
405 MARKER_INT_16 => Ok((Value::Integer(i64::from(bytes.get_i16())), bytes)),
406 MARKER_INT_32 => Ok((Value::Integer(i64::from(bytes.get_i32())), bytes)),
407 MARKER_INT_64 => Ok((Value::Integer(bytes.get_i64()), bytes)),
408 MARKER_FLOAT => Ok((Value::Float(bytes.get_f64()), bytes)),
410 MARKER_SMALL_BYTES | MARKER_MEDIUM_BYTES | MARKER_LARGE_BYTES => {
412 let size = match marker {
413 MARKER_SMALL_BYTES => bytes.get_u8() as usize,
414 MARKER_MEDIUM_BYTES => bytes.get_u16() as usize,
415 MARKER_LARGE_BYTES => bytes.get_u32() as usize,
416 _ => unreachable!(),
417 };
418 Ok((Value::Bytes(bytes.copy_to_bytes(size).to_vec()), bytes))
419 }
420 marker
422 if (MARKER_TINY_LIST..=(MARKER_TINY_LIST | 0x0F)).contains(&marker)
423 || matches!(
424 marker,
425 MARKER_SMALL_LIST | MARKER_MEDIUM_LIST | MARKER_LARGE_LIST
426 ) =>
427 {
428 let size = match marker {
429 marker
430 if (MARKER_TINY_LIST..=(MARKER_TINY_LIST | 0x0F)).contains(&marker) =>
431 {
432 0x0F & marker as usize
433 }
434 MARKER_SMALL_LIST => bytes.get_u8() as usize,
435 MARKER_MEDIUM_LIST => bytes.get_u16() as usize,
436 MARKER_LARGE_LIST => bytes.get_u32() as usize,
437 _ => unreachable!(),
438 };
439 let mut list: Vec<Value> = Vec::with_capacity(size);
440 for _ in 0..size {
441 let (v, b) = Value::deserialize(bytes)?;
442 bytes = b;
443 list.push(v);
444 }
445 Ok((Value::List(list), bytes))
446 }
447 marker
449 if (MARKER_TINY_MAP..=(MARKER_TINY_MAP | 0x0F)).contains(&marker)
450 || matches!(
451 marker,
452 MARKER_SMALL_MAP | MARKER_MEDIUM_MAP | MARKER_LARGE_MAP
453 ) =>
454 {
455 let size = match marker {
456 marker
457 if (MARKER_TINY_MAP..=(MARKER_TINY_MAP | 0x0F)).contains(&marker) =>
458 {
459 0x0F & marker as usize
460 }
461 MARKER_SMALL_MAP => bytes.get_u8() as usize,
462 MARKER_MEDIUM_MAP => bytes.get_u16() as usize,
463 MARKER_LARGE_MAP => bytes.get_u32() as usize,
464 _ => unreachable!(),
465 };
466
467 let mut hash_map: HashMap<std::string::String, Value> =
468 HashMap::with_capacity(size);
469 for _ in 0..size {
470 let (value, remaining) = Value::deserialize(bytes)?;
471 bytes = remaining;
472 match value {
473 Value::String(key) => {
474 let (value, remaining) = Value::deserialize(bytes)?;
475 bytes = remaining;
476 hash_map.insert(key, value);
477 }
478 other => return Err(ConversionError::FromValue(other).into()),
479 }
480 }
481
482 Ok((Value::Map(hash_map), bytes))
483 }
484 MARKER_NULL => Ok((Value::Null, bytes)),
486 marker
488 if (MARKER_TINY_STRING..=(MARKER_TINY_STRING | 0x0F)).contains(&marker)
489 || matches!(
490 marker,
491 MARKER_SMALL_STRING | MARKER_MEDIUM_STRING | MARKER_LARGE_STRING
492 ) =>
493 {
494 let size = match marker {
495 marker
496 if (MARKER_TINY_STRING..=(MARKER_TINY_STRING | 0x0F))
497 .contains(&marker) =>
498 {
499 0x0F & marker as usize
500 }
501 MARKER_SMALL_STRING => bytes.get_u8() as usize,
502 MARKER_MEDIUM_STRING => bytes.get_u16() as usize,
503 MARKER_LARGE_STRING => bytes.get_u32() as usize,
504 _ => unreachable!(),
505 };
506
507 Ok((
508 Value::String(String::from_utf8(bytes.copy_to_bytes(size).to_vec())?),
509 bytes,
510 ))
511 }
512 marker
514 if (MARKER_TINY_STRUCT..=(MARKER_TINY_STRUCT | 0x0F)).contains(&marker)
515 || matches!(marker, MARKER_SMALL_STRUCT | MARKER_MEDIUM_STRUCT) =>
516 {
517 deserialize_structure(marker, bytes)
518 }
519 _ => Err(DeserializationError::InvalidMarkerByte(marker)),
520 }
521 })
522 .map_err(|_| DeserializationError::Panicked)?
523 }
524}
525
526macro_rules! deserialize_struct {
527 ($name:ident, $bytes:ident) => {{
528 let (value, remaining) = $name::deserialize($bytes)?;
529 $bytes = remaining;
530 Ok((Value::$name(value), $bytes))
531 }};
532}
533
534macro_rules! deserialize_variant {
535 ($name:ident, $bytes:ident) => {{
536 let (value, remaining) = Value::deserialize($bytes)?;
537 $bytes = remaining;
538 if let Value::$name(inner) = value {
539 inner
540 } else {
541 return Err(ConversionError::FromValue(value).into());
542 }
543 }};
544}
545
546fn deserialize_structure<B: Buf + UnwindSafe>(
547 marker: u8,
548 mut bytes: B,
549) -> DeserializeResult<(Value, B)> {
550 let (_, signature) = get_structure_info(marker, &mut bytes)?;
551
552 match signature {
553 SIGNATURE_NODE => deserialize_struct!(Node, bytes),
554 SIGNATURE_RELATIONSHIP => deserialize_struct!(Relationship, bytes),
555 SIGNATURE_PATH => deserialize_struct!(Path, bytes),
556 SIGNATURE_UNBOUND_RELATIONSHIP => deserialize_struct!(UnboundRelationship, bytes),
557 SIGNATURE_DATE => {
558 let days_since_epoch: i64 = deserialize_variant!(Integer, bytes);
559 Ok((
560 Value::Date(
561 NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()
562 + chrono::Duration::days(days_since_epoch),
563 ),
564 bytes,
565 ))
566 }
567 SIGNATURE_TIME => {
568 let nanos_since_midnight: i64 = deserialize_variant!(Integer, bytes);
569 let zone_offset: i32 = deserialize_variant!(Integer, bytes) as i32;
570 Ok((
571 Value::Time(
572 NaiveTime::from_num_seconds_from_midnight_opt(
573 (nanos_since_midnight / 1_000_000_000) as u32,
574 (nanos_since_midnight % 1_000_000_000) as u32,
575 )
576 .unwrap(),
577 FixedOffset::east_opt(zone_offset).unwrap(),
578 ),
579 bytes,
580 ))
581 }
582 SIGNATURE_DATE_TIME_OFFSET => {
583 let epoch_seconds: i64 = deserialize_variant!(Integer, bytes);
584 let nanos: i64 = deserialize_variant!(Integer, bytes);
585 let offset_seconds: i32 = deserialize_variant!(Integer, bytes) as i32;
586 Ok((
587 Value::DateTimeOffset(DateTime::from_utc(
588 NaiveDateTime::from_timestamp_opt(epoch_seconds, nanos as u32).unwrap(),
589 FixedOffset::east_opt(offset_seconds).unwrap(),
590 )),
591 bytes,
592 ))
593 }
594 SIGNATURE_DATE_TIME_ZONED => {
595 let epoch_seconds: i64 = deserialize_variant!(Integer, bytes);
596 let nanos: i64 = deserialize_variant!(Integer, bytes);
597 let timezone_id: String = deserialize_variant!(String, bytes);
598 let timezone: Tz = timezone_id.parse().unwrap();
599 Ok((
600 Value::DateTimeZoned(timezone.timestamp_opt(epoch_seconds, nanos as u32).unwrap()),
601 bytes,
602 ))
603 }
604 SIGNATURE_LOCAL_TIME => {
605 let nanos_since_midnight: i64 = deserialize_variant!(Integer, bytes);
606 Ok((
607 Value::LocalTime(
608 NaiveTime::from_num_seconds_from_midnight_opt(
609 (nanos_since_midnight / 1_000_000_000) as u32,
610 (nanos_since_midnight % 1_000_000_000) as u32,
611 )
612 .unwrap(),
613 ),
614 bytes,
615 ))
616 }
617 SIGNATURE_LOCAL_DATE_TIME => {
618 let epoch_seconds: i64 = deserialize_variant!(Integer, bytes);
619 let nanos: i64 = deserialize_variant!(Integer, bytes);
620 Ok((
621 Value::LocalDateTime(
622 NaiveDateTime::from_timestamp_opt(epoch_seconds, nanos as u32).unwrap(),
623 ),
624 bytes,
625 ))
626 }
627 SIGNATURE_DURATION => deserialize_struct!(Duration, bytes),
628 SIGNATURE_POINT_2D => deserialize_struct!(Point2D, bytes),
629 SIGNATURE_POINT_3D => deserialize_struct!(Point3D, bytes),
630 _ => Err(DeserializationError::InvalidSignatureByte(signature)),
631 }
632}
633
634#[cfg(test)]
635mod tests {
636 use std::collections::HashMap;
637
638 use chrono::{FixedOffset, NaiveDate, NaiveTime, TimeZone, Utc};
639
640 use super::*;
641
642 macro_rules! value_test {
643 ($name:ident, $value:expr, $marker:expr, $($bytes:expr),+) => {
644 #[test]
645 fn $name() {
646 let value = $value;
647 let bytes: Bytes = vec![$marker]
648 .into_iter()
649 $(.chain($bytes.iter().copied()))*
650 .collect();
651 assert_eq!(value.marker().unwrap(), $marker);
652 assert_eq!(value.clone().serialize().unwrap(), &bytes);
653 let (deserialized, remaining) = Value::deserialize(bytes).unwrap();
654 assert_eq!(deserialized, value);
655 assert_eq!(remaining.len(), 0);
656 }
657 };
658 ($name:ident, $value:expr, $marker:expr) => {
659 #[test]
660 fn $name() {
661 let value = $value;
662 let bytes = $value.clone().serialize().unwrap();
663 assert_eq!(value.marker().unwrap(), $marker);
664 let (deserialized, remaining) = Value::deserialize(bytes).unwrap();
665 assert_eq!(deserialized, value);
666 assert_eq!(remaining.len(), 0);
667 }
668 };
669 }
670
671 value_test!(null, Value::Null, MARKER_NULL, &[]);
672
673 value_test!(bool_true, Value::Boolean(true), MARKER_TRUE, &[]);
674
675 value_test!(bool_false, Value::Boolean(false), MARKER_FALSE, &[]);
676
677 value_test!(tiny_int, Value::Integer(110), 110, &[]);
678
679 value_test!(
680 small_int,
681 Value::Integer(-127),
682 MARKER_INT_8,
683 (-127_i8).to_be_bytes()
684 );
685
686 value_test!(
687 medium_int,
688 Value::Integer(8000),
689 MARKER_INT_16,
690 8000_i16.to_be_bytes()
691 );
692
693 value_test!(
694 medium_negative_int,
695 Value::Integer(-18621),
696 MARKER_INT_16,
697 (-18621_i16).to_be_bytes()
698 );
699
700 value_test!(
701 large_int,
702 Value::Integer(-1_000_000_000),
703 MARKER_INT_32,
704 (-1_000_000_000_i32).to_be_bytes()
705 );
706
707 value_test!(
708 very_large_int,
709 Value::Integer(9_000_000_000_000_000_000),
710 MARKER_INT_64,
711 9_000_000_000_000_000_000_i64.to_be_bytes()
712 );
713
714 value_test!(
715 float_min,
716 Value::Float(f64::MIN_POSITIVE),
717 MARKER_FLOAT,
718 f64::MIN_POSITIVE.to_be_bytes()
719 );
720
721 value_test!(
722 float_max,
723 Value::Float(f64::MAX),
724 MARKER_FLOAT,
725 f64::MAX.to_be_bytes()
726 );
727
728 value_test!(
729 float_e,
730 Value::Float(std::f64::consts::E),
731 MARKER_FLOAT,
732 std::f64::consts::E.to_be_bytes()
733 );
734
735 value_test!(
736 float_pi,
737 Value::Float(std::f64::consts::PI),
738 MARKER_FLOAT,
739 std::f64::consts::PI.to_be_bytes()
740 );
741
742 value_test!(
743 empty_byte_array,
744 Value::Bytes(vec![]),
745 MARKER_SMALL_BYTES,
746 &[0]
747 );
748
749 value_test!(
750 small_byte_array,
751 Value::Bytes(vec![1_u8; 100]),
752 MARKER_SMALL_BYTES,
753 &[100],
754 &[1_u8; 100]
755 );
756
757 value_test!(
758 medium_byte_array,
759 Value::Bytes(vec![99_u8; 1000]),
760 MARKER_MEDIUM_BYTES,
761 1000_u16.to_be_bytes(),
762 &[99_u8; 1000]
763 );
764
765 value_test!(
766 large_byte_array,
767 Value::Bytes(vec![1_u8; 100_000]),
768 MARKER_LARGE_BYTES,
769 100_000_u32.to_be_bytes(),
770 &[1_u8; 100_000]
771 );
772
773 value_test!(empty_list, Value::List(vec![]), MARKER_TINY_LIST | 0, &[]);
774
775 value_test!(
776 tiny_list,
777 Value::List(vec![Value::Integer(100_000); 3]),
778 MARKER_TINY_LIST | 3,
779 &[MARKER_INT_32],
780 100_000_u32.to_be_bytes(),
781 &[MARKER_INT_32],
782 100_000_u32.to_be_bytes(),
783 &[MARKER_INT_32],
784 100_000_u32.to_be_bytes()
785 );
786
787 value_test!(
788 small_list,
789 Value::List(vec![Value::String(String::from("item")); 100]),
790 MARKER_SMALL_LIST,
791 &[100],
792 &[MARKER_TINY_STRING | 4, b'i', b't', b'e', b'm'].repeat(100)
793 );
794
795 value_test!(
796 medium_list,
797 Value::List(vec![Value::Boolean(false); 1000]),
798 MARKER_MEDIUM_LIST,
799 1000_u16.to_be_bytes(),
800 &[MARKER_FALSE; 1000]
801 );
802
803 value_test!(
804 large_list,
805 Value::List(vec![Value::Integer(1); 70_000]),
806 MARKER_LARGE_LIST,
807 70_000_u32.to_be_bytes(),
808 &[1; 70_000]
809 );
810
811 value_test!(
812 tiny_string,
813 Value::String(String::from("string")),
814 MARKER_TINY_STRING | 6,
815 b"string"
816 );
817
818 value_test!(
819 small_string,
820 Value::String("string".repeat(10)),
821 MARKER_SMALL_STRING,
822 60_u8.to_be_bytes(),
823 b"string".repeat(10)
824 );
825
826 value_test!(
827 medium_string,
828 Value::String("string".repeat(1000)),
829 MARKER_MEDIUM_STRING,
830 6000_u16.to_be_bytes(),
831 b"string".repeat(1000)
832 );
833
834 value_test!(
835 large_string,
836 Value::String("string".repeat(100_000)),
837 MARKER_LARGE_STRING,
838 600_000_u32.to_be_bytes(),
839 b"string".repeat(100_000)
840 );
841
842 value_test!(
843 special_string,
844 Value::String(String::from("En å flöt över ängen")),
845 MARKER_SMALL_STRING,
846 24_u8.to_be_bytes(),
847 "En å flöt över ängen".bytes().collect::<Vec<_>>()
848 );
849
850 value_test!(
851 empty_map,
852 Value::from(HashMap::<&str, i8>::new()),
853 MARKER_TINY_MAP | 0,
854 &[]
855 );
856
857 value_test!(
858 tiny_map,
859 Value::from(HashMap::<&str, i8>::from_iter(vec![("a", 1_i8)])),
860 MARKER_TINY_MAP | 1,
861 &[MARKER_TINY_STRING | 1, b'a', 1]
862 );
863
864 #[test]
865 fn small_map_from_bytes() {
866 let small_map = Value::from(HashMap::<&str, i8>::from_iter(vec![
867 ("a", 1_i8),
868 ("b", 1_i8),
869 ("c", 3_i8),
870 ("d", 4_i8),
871 ("e", 5_i8),
872 ("f", 6_i8),
873 ("g", 7_i8),
874 ("h", 8_i8),
875 ("i", 9_i8),
876 ("j", 0_i8),
877 ("k", 1_i8),
878 ("l", 2_i8),
879 ("m", 3_i8),
880 ("n", 4_i8),
881 ("o", 5_i8),
882 ("p", 6_i8),
883 ]));
884 let bytes = small_map.clone().serialize().unwrap();
885 let (deserialized, remaining) = Value::deserialize(bytes).unwrap();
886 assert_eq!(deserialized, small_map);
887 assert_eq!(remaining.len(), 0);
888 }
889
890 value_test!(
891 node,
892 Value::Node(Node::new(
893 24_i64,
894 vec!["TestNode".to_string()],
895 HashMap::from_iter(vec![
896 ("key1".to_string(), -1_i8),
897 ("key2".to_string(), 1_i8),
898 ]),
899 )),
900 MARKER_TINY_STRUCT | 3
901 );
902
903 value_test!(
904 relationship,
905 Value::Relationship(Relationship::new(
906 24_i64,
907 32_i64,
908 128_i64,
909 "TestRel".to_string(),
910 HashMap::from_iter(vec![
911 ("key1".to_string(), -2_i8),
912 ("key2".to_string(), 2_i8),
913 ]),
914 )),
915 MARKER_TINY_STRUCT | 5
916 );
917
918 value_test!(
919 path,
920 Value::Path(Path::new(
921 vec![Node::new(
922 24_i64,
923 vec!["TestNode".to_string()],
924 HashMap::from_iter(vec![
925 ("key1".to_string(), -1_i8),
926 ("key2".to_string(), 1_i8),
927 ]),
928 )],
929 vec![UnboundRelationship::new(
930 128_i64,
931 "TestRel".to_string(),
932 HashMap::from_iter(vec![
933 ("key1".to_string(), -2_i8),
934 ("key2".to_string(), 2_i8),
935 ]),
936 )],
937 vec![100, 101]
938 )),
939 MARKER_TINY_STRUCT | 3
940 );
941
942 value_test!(
943 unbound_relationship,
944 Value::UnboundRelationship(UnboundRelationship::new(
945 128_i64,
946 "TestRel".to_string(),
947 HashMap::from_iter(vec![
948 ("key1".to_string(), -2_i8),
949 ("key2".to_string(), 2_i8),
950 ]),
951 )),
952 MARKER_TINY_STRUCT | 3
953 );
954
955 value_test!(
956 date,
957 Value::Date(NaiveDate::from_ymd_opt(2020, 12, 25).unwrap()),
958 MARKER_TINY_STRUCT | 1,
959 &[SIGNATURE_DATE],
960 &[MARKER_INT_16],
961 18621_i16.to_be_bytes()
962 );
963
964 value_test!(
965 past_date,
966 Value::Date(NaiveDate::from_ymd_opt(1901, 12, 31).unwrap()),
967 MARKER_TINY_STRUCT | 1,
968 &[SIGNATURE_DATE],
969 &[MARKER_INT_16],
970 (-24838_i16).to_be_bytes()
971 );
972
973 value_test!(
974 future_date,
975 Value::Date(NaiveDate::from_ymd_opt(3000, 5, 23).unwrap()),
976 MARKER_TINY_STRUCT | 1,
977 &[SIGNATURE_DATE],
978 &[MARKER_INT_32],
979 376342_i32.to_be_bytes()
980 );
981
982 value_test!(
983 time,
984 Value::Time(NaiveTime::from_hms_nano_opt(0, 0, 0, 0).unwrap(), Utc.fix()),
985 MARKER_TINY_STRUCT | 2,
986 &[SIGNATURE_TIME],
987 &[0, 0]
988 );
989
990 value_test!(
991 about_four_pm_pacific,
992 Value::Time(
993 NaiveTime::from_hms_nano_opt(16, 4, 35, 235).unwrap(),
994 FixedOffset::east_opt(-8 * 3600).unwrap(),
995 ),
996 MARKER_TINY_STRUCT | 2,
997 &[SIGNATURE_TIME],
998 &[MARKER_INT_64],
999 57875000000235_i64.to_be_bytes(),
1000 &[MARKER_INT_16],
1001 (-8 * 3600_i16).to_be_bytes()
1002 );
1003
1004 value_test!(
1005 date_time_offset,
1006 Value::DateTimeOffset(
1007 FixedOffset::east_opt(-5 * 3600).unwrap().from_utc_datetime(
1008 &NaiveDate::from_ymd_opt(2050, 12, 31)
1009 .unwrap()
1010 .and_hms_nano_opt(23, 59, 59, 10)
1011 .unwrap()
1012 ),
1013 ),
1014 MARKER_TINY_STRUCT | 3,
1015 &[SIGNATURE_DATE_TIME_OFFSET],
1016 &[MARKER_INT_64],
1017 2556143999_i64.to_be_bytes(),
1018 &[10],
1019 &[MARKER_INT_16],
1020 (-5 * 3600_i16).to_be_bytes()
1021 );
1022
1023 value_test!(
1024 date_time_zoned,
1025 Value::DateTimeZoned(
1026 chrono_tz::Asia::Ulaanbaatar
1027 .with_ymd_and_hms(2030, 8, 3, 14, 30, 1)
1028 .unwrap()
1029 .with_nanosecond(12345)
1030 .unwrap(),
1031 ),
1032 MARKER_TINY_STRUCT | 3,
1033 &[SIGNATURE_DATE_TIME_ZONED],
1034 &[MARKER_INT_32],
1035 1911969001_i32.to_be_bytes(),
1036 &[MARKER_INT_16],
1037 12345_i16.to_be_bytes(),
1038 &[MARKER_SMALL_STRING, 16],
1039 b"Asia/Ulaanbaatar"
1040 );
1041
1042 value_test!(
1043 local_time,
1044 Value::LocalTime(NaiveTime::from_hms_nano_opt(23, 59, 59, 999).unwrap()),
1045 MARKER_TINY_STRUCT | 1,
1046 &[SIGNATURE_LOCAL_TIME],
1047 &[MARKER_INT_64],
1048 86399000000999_i64.to_be_bytes()
1049 );
1050
1051 value_test!(
1052 local_date_time,
1053 Value::LocalDateTime(
1054 NaiveDate::from_ymd_opt(1999, 2, 27)
1055 .unwrap()
1056 .and_hms_nano_opt(1, 0, 0, 9999)
1057 .unwrap()
1058 ),
1059 MARKER_TINY_STRUCT | 2,
1060 &[SIGNATURE_LOCAL_DATE_TIME],
1061 &[MARKER_INT_32],
1062 920077200_i32.to_be_bytes(),
1063 &[MARKER_INT_16],
1064 9999_i16.to_be_bytes()
1065 );
1066
1067 value_test!(
1068 duration,
1069 Value::Duration(Duration::new(9876, 12345, 65332, 23435)),
1070 MARKER_TINY_STRUCT | 4,
1071 &[SIGNATURE_DURATION],
1072 &[MARKER_INT_16],
1073 9876_i16.to_be_bytes(),
1074 &[MARKER_INT_16],
1075 12345_i16.to_be_bytes(),
1076 &[MARKER_INT_32],
1077 65332_i32.to_be_bytes(),
1078 &[MARKER_INT_16],
1079 23435_i16.to_be_bytes()
1080 );
1081
1082 value_test!(
1083 point_2d,
1084 Value::Point2D(Point2D::new(9876, 12.312_345, 134_564.123_567_543)),
1085 MARKER_TINY_STRUCT | 3,
1086 &[SIGNATURE_POINT_2D],
1087 &[MARKER_INT_16],
1088 9876_i16.to_be_bytes(),
1089 &[MARKER_FLOAT],
1090 12.312345_f64.to_be_bytes(),
1091 &[MARKER_FLOAT],
1092 134_564.123_567_543_f64.to_be_bytes()
1093 );
1094
1095 value_test!(
1096 point_3d,
1097 Value::Point3D(Point3D::new(
1098 249,
1099 543.598_387,
1100 2_945_732_849.293_85,
1101 45_438.874_385
1102 )),
1103 MARKER_TINY_STRUCT | 4,
1104 &[SIGNATURE_POINT_3D],
1105 &[MARKER_INT_16],
1106 249_i16.to_be_bytes(),
1107 &[MARKER_FLOAT],
1108 543.598_387_f64.to_be_bytes(),
1109 &[MARKER_FLOAT],
1110 2_945_732_849.293_85_f64.to_be_bytes(),
1111 &[MARKER_FLOAT],
1112 45_438.874_385_f64.to_be_bytes()
1113 );
1114
1115 #[test]
1116 #[ignore]
1117 fn value_size() {
1118 use std::mem::size_of;
1119 println!("Duration: {} bytes", size_of::<Duration>());
1120 println!("Node: {} bytes", size_of::<Node>());
1121 println!("Path: {} bytes", size_of::<Path>());
1122 println!("Point2D: {} bytes", size_of::<Point2D>());
1123 println!("Point3D: {} bytes", size_of::<Point3D>());
1124 println!("Relationship: {} bytes", size_of::<Relationship>());
1125 println!(
1126 "UnboundRelationship: {} bytes",
1127 size_of::<UnboundRelationship>()
1128 );
1129 println!("Value: {} bytes", size_of::<Value>())
1130 }
1131}