Skip to main content

nodedb_types/value/
msgpack.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Hand-rolled zerompk implementations for `Value`.
4//!
5//! Cannot use derive because `rust_decimal::Decimal` is an external type.
6//! Format: [variant_tag: u8, ...payload fields] as a msgpack array.
7
8use std::collections::HashMap;
9use std::sync::Arc;
10
11use super::core::Value;
12use crate::array_cell::ArrayCell;
13use crate::datetime::{NdbDateTime, NdbDuration};
14use crate::geometry::Geometry;
15
16impl zerompk::ToMessagePack for Value {
17    fn write<W: zerompk::Write>(&self, writer: &mut W) -> zerompk::Result<()> {
18        match self {
19            Value::Null => {
20                writer.write_array_len(1)?;
21                writer.write_u8(0)
22            }
23            Value::Bool(b) => {
24                writer.write_array_len(2)?;
25                writer.write_u8(1)?;
26                writer.write_boolean(*b)
27            }
28            Value::Integer(i) => {
29                writer.write_array_len(2)?;
30                writer.write_u8(2)?;
31                writer.write_i64(*i)
32            }
33            Value::Float(f) => {
34                writer.write_array_len(2)?;
35                writer.write_u8(3)?;
36                writer.write_f64(*f)
37            }
38            Value::String(s) => {
39                writer.write_array_len(2)?;
40                writer.write_u8(4)?;
41                writer.write_string(s)
42            }
43            Value::Bytes(b) => {
44                writer.write_array_len(2)?;
45                writer.write_u8(5)?;
46                writer.write_binary(b)
47            }
48            Value::Array(arr) => {
49                writer.write_array_len(2)?;
50                writer.write_u8(6)?;
51                arr.write(writer)
52            }
53            Value::Object(map) => {
54                writer.write_array_len(2)?;
55                writer.write_u8(7)?;
56                map.write(writer)
57            }
58            Value::Uuid(s) => {
59                writer.write_array_len(2)?;
60                writer.write_u8(8)?;
61                writer.write_string(s)
62            }
63            Value::Ulid(s) => {
64                writer.write_array_len(2)?;
65                writer.write_u8(9)?;
66                writer.write_string(s)
67            }
68            Value::DateTime(dt) => {
69                writer.write_array_len(2)?;
70                writer.write_u8(10)?;
71                dt.write(writer)
72            }
73            Value::Duration(d) => {
74                writer.write_array_len(2)?;
75                writer.write_u8(11)?;
76                d.write(writer)
77            }
78            Value::Decimal(d) => {
79                writer.write_array_len(2)?;
80                writer.write_u8(12)?;
81                writer.write_binary(&d.serialize())
82            }
83            Value::Geometry(g) => {
84                writer.write_array_len(2)?;
85                writer.write_u8(13)?;
86                g.write(writer)
87            }
88            Value::Set(s) => {
89                writer.write_array_len(2)?;
90                writer.write_u8(14)?;
91                s.write(writer)
92            }
93            Value::Regex(r) => {
94                writer.write_array_len(2)?;
95                writer.write_u8(15)?;
96                writer.write_string(r)
97            }
98            Value::Range {
99                start,
100                end,
101                inclusive,
102            } => {
103                writer.write_array_len(4)?;
104                writer.write_u8(16)?;
105                start.write(writer)?;
106                end.write(writer)?;
107                writer.write_boolean(*inclusive)
108            }
109            Value::Record { table, id } => {
110                writer.write_array_len(3)?;
111                writer.write_u8(17)?;
112                writer.write_string(table)?;
113                writer.write_string(id)
114            }
115            Value::ArrayCell(cell) => {
116                writer.write_array_len(2)?;
117                writer.write_u8(18)?;
118                cell.write(writer)
119            }
120            Value::NaiveDateTime(dt) => {
121                writer.write_array_len(2)?;
122                writer.write_u8(19)?;
123                dt.write(writer)
124            }
125            Value::Vector(v) => {
126                writer.write_array_len(2)?;
127                writer.write_u8(20)?;
128                writer.write_binary(bytemuck::cast_slice(v.as_ref()))
129            }
130        }
131    }
132}
133
134impl<'a> zerompk::FromMessagePack<'a> for Value {
135    fn read<R: zerompk::Read<'a>>(reader: &mut R) -> zerompk::Result<Self> {
136        let len = reader.read_array_len()?;
137        if len == 0 {
138            return Err(zerompk::Error::ArrayLengthMismatch {
139                expected: 1,
140                actual: 0,
141            });
142        }
143        let tag = reader.read_u8()?;
144        match tag {
145            0 => Ok(Value::Null),
146            1 => Ok(Value::Bool(reader.read_boolean()?)),
147            2 => Ok(Value::Integer(reader.read_i64()?)),
148            3 => Ok(Value::Float(reader.read_f64()?)),
149            4 => Ok(Value::String(reader.read_string()?.into_owned())),
150            5 => Ok(Value::Bytes(reader.read_binary()?.into_owned())),
151            6 => Ok(Value::Array(Vec::<Value>::read(reader)?)),
152            7 => Ok(Value::Object(HashMap::<String, Value>::read(reader)?)),
153            8 => Ok(Value::Uuid(reader.read_string()?.into_owned())),
154            9 => Ok(Value::Ulid(reader.read_string()?.into_owned())),
155            10 => Ok(Value::DateTime(NdbDateTime::read(reader)?)),
156            11 => Ok(Value::Duration(NdbDuration::read(reader)?)),
157            12 => {
158                let cow = reader.read_binary()?;
159                if cow.len() != 16 {
160                    return Err(zerompk::Error::BufferTooSmall);
161                }
162                let mut buf = [0u8; 16];
163                buf.copy_from_slice(&cow);
164                Ok(Value::Decimal(rust_decimal::Decimal::deserialize(buf)))
165            }
166            13 => Ok(Value::Geometry(Geometry::read(reader)?)),
167            14 => Ok(Value::Set(Vec::<Value>::read(reader)?)),
168            15 => Ok(Value::Regex(reader.read_string()?.into_owned())),
169            16 => {
170                let start = Option::<Box<Value>>::read(reader)?;
171                let end = Option::<Box<Value>>::read(reader)?;
172                let inclusive = reader.read_boolean()?;
173                Ok(Value::Range {
174                    start,
175                    end,
176                    inclusive,
177                })
178            }
179            17 => {
180                let table = reader.read_string()?.into_owned();
181                let id = reader.read_string()?.into_owned();
182                Ok(Value::Record { table, id })
183            }
184            18 => Ok(Value::ArrayCell(ArrayCell::read(reader)?)),
185            19 => Ok(Value::NaiveDateTime(NdbDateTime::read(reader)?)),
186            20 => {
187                let cow = reader.read_binary()?;
188                if cow.len() % 4 != 0 {
189                    return Err(zerompk::Error::BufferTooSmall);
190                }
191                // Deserialize each f32 from its 4-byte little-endian
192                // representation. This is safe for any alignment and matches
193                // the byte order produced by bytemuck::cast_slice on the
194                // encode side (native endian = little-endian on x86/ARM).
195                let floats: Arc<[f32]> = cow
196                    .chunks_exact(4)
197                    .map(|chunk| {
198                        let arr = [chunk[0], chunk[1], chunk[2], chunk[3]];
199                        f32::from_ne_bytes(arr)
200                    })
201                    .collect();
202                Ok(Value::Vector(floats))
203            }
204            _ => Err(zerompk::Error::InvalidMarker(tag)),
205        }
206    }
207}