bolt_proto/
value.rs

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/// An enum that can hold values of all Bolt-compatible types.
75///
76/// Conversions are provided for most types, and are usually pretty intuitive ([`bool`] to
77/// [`Value::Boolean`], [`i32`] to [`Value::Integer`], [`HashMap`](std::collections::HashMap) to
78/// [`Value::Map`], etc.), but some types have no analog in Rust, like a timezone-aware time. For
79/// such types, conversions are still provided, but may feel a bit clunky (for example, you can
80/// convert a `(`[`NaiveTime`](chrono::NaiveTime)`, impl `[`Offset`](chrono::Offset)`)` tuple into
81/// a [`Value::Time`]).
82#[derive(Debug, Clone, PartialEq)]
83pub enum Value {
84    // V1-compatible value types
85    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    // V2+-compatible value types
99    Date(NaiveDate),              // A date without a time zone, i.e. LocalDate
100    Time(NaiveTime, FixedOffset), // A time with UTC offset, i.e. OffsetTime
101    DateTimeOffset(DateTime<FixedOffset>), // A date-time with UTC offset, i.e. OffsetDateTime
102    DateTimeZoned(DateTime<Tz>),  // A date-time with time zone ID, i.e. ZonedDateTime
103    LocalTime(NaiveTime),         // A time without time zone
104    LocalDateTime(NaiveDateTime), // A date-time without time zone
105    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                // Worst case is marker + 64-bit int
183                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 => {} // The marker is the value
202                }
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                // Worst case is a large ByteArray, with marker byte, 32-bit size value, and length
215                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                // Worst case is a large List, with marker byte, 32-bit size value, and all the
242                // Value bytes
243                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 => {} // The marker contains the length
250                    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                // Worst case is a large Map, with marker byte, 32-bit size value, and all the
275                // Value bytes
276                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 => {} // The marker contains the length
283                    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                // Worst case is a large string, with marker byte, 32-bit size value, and length
299                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 => {} // The marker contains the length
305                    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                    // Days since UNIX epoch
322                    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                    // Nanoseconds since midnight
330                    // Will not overflow: u32::MAX * 1_000_000_000 + u32::MAX < i64::MAX
331                    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                    // Timezone offset
339                    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                    // Seconds since UNIX epoch
346                    Value::from(date_time_offset.timestamp()).serialize()?,
347                )
348                .chain(
349                    // Nanoseconds
350                    Value::from(i64::from(date_time_offset.nanosecond())).serialize()?,
351                )
352                .chain(
353                    // Timezone offset
354                    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                    // Seconds since UNIX epoch
361                    .chain(Value::from(date_time_zoned.timestamp()).serialize()?)
362                    // Nanoseconds
363                    .chain(Value::from(i64::from(date_time_zoned.nanosecond())).serialize()?)
364                    // Timezone ID
365                    .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                        // Will not overflow: u32::MAX * 1_000_000_000 + u32::MAX < i64::MAX
373                        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                // Seconds since UNIX epoch
382                .chain(Value::from(local_date_time.timestamp()).serialize()?)
383                // Nanoseconds
384                .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                // Boolean
397                MARKER_TRUE => Ok((Value::Boolean(true), bytes)),
398                MARKER_FALSE => Ok((Value::Boolean(false), bytes)),
399                // Tiny int
400                marker if (-16..=127).contains(&(marker as i8)) => {
401                    Ok((Value::Integer(i64::from(marker as i8)), bytes))
402                }
403                // Other int types
404                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                // Float
409                MARKER_FLOAT => Ok((Value::Float(bytes.get_f64()), bytes)),
410                // Byte array
411                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                // List
421                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                // Map
448                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                // Null
485                MARKER_NULL => Ok((Value::Null, bytes)),
486                // String
487                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                // Structure
513                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}