1use std::borrow::Cow;
18use std::collections::BTreeMap;
19use time::OffsetDateTime;
21use super::Value;
23use crate::message::{PostcardReader as Reader, PostcardValue, decoding_add, decoding_multiply};
24use crate::schema::declaration::{Definition, Field, Kind};
25use crate::schema::{Cardinality, Described};
26use crate::{MessageError, btree_map_memory};
27
28pub const VALUE_DEPTH: usize = 4;
31
32const NULL: u32 = 0;
34const BOOL: u32 = 1;
35const INTEGER: u32 = 2;
36const UNSIGNED: u32 = 3;
37const NUMBER: u32 = 4;
38const TEXT: u32 = 5;
39const DATETIME: u32 = 6;
40const ARRAY: u32 = 7;
41const OBJECT: u32 = 8;
42
43pub(crate) const TIMESTAMP_DEFINITION: Definition = Timestamp::DEFINITION;
44pub(crate) const VALUE_FIELDS: &[Field] = Value4::FIELDS;
45pub(crate) const ENTRY_DEFINITION: Definition = Entry4::DEFINITION;
46
47macro_rules! shape {
50 ($name:ident, $fields:expr) => {
51 pub(crate) struct $name;
52 impl Described for $name {
53 const NAME: &'static str = concat!(module_path!(), "::", stringify!($name));
54 const FIELDS: &'static [Field] = $fields;
55 const MARKER: &'static [u8] = &crate::schema::declaration::encode::<
56 { crate::schema::declaration::encoded_len(Self::NAME, Self::FIELDS) },
57 >(Self::NAME, Self::FIELDS);
58 }
59 };
60}
61
62macro_rules! level {
63 ($level:ident, $entry:ident, $array:ident, $object:ident, $inner:ident) => {
64 shape!($array, &[field("items", 1, message($inner::DEFINITION), Cardinality::Repeated)]);
65 shape!(
66 $entry,
67 &[field("key", 1, Kind::String, Cardinality::Required), field("value", 2, message($inner::DEFINITION), Cardinality::Required),]
68 );
69 shape!($object, &[field("entries", 1, message($entry::DEFINITION), Cardinality::Repeated)]);
70 shape!(
71 $level,
72 &[
73 field("null", 1, message(<()>::DEFINITION), Cardinality::Variant),
74 field("bool", 2, message(<bool>::DEFINITION), Cardinality::Variant),
75 field("integer", 3, message(<i64>::DEFINITION), Cardinality::Variant),
76 field("unsigned", 4, message(<u64>::DEFINITION), Cardinality::Variant),
77 field("number", 5, message(<f64>::DEFINITION), Cardinality::Variant),
78 field("text", 6, message(String::DEFINITION), Cardinality::Variant),
79 field("datetime", 7, message(Timestamp::DEFINITION), Cardinality::Variant),
80 field("array", 8, message($array::DEFINITION), Cardinality::Variant),
81 field("object", 9, message($object::DEFINITION), Cardinality::Variant),
82 ]
83 );
84 };
85}
86
87shape!(Timestamp, &[field("seconds", 1, Kind::I64, Cardinality::Required), field("nanos", 2, Kind::U32, Cardinality::Required),]);
88shape!(
89 Value0,
90 &[
91 field("null", 1, message(<()>::DEFINITION), Cardinality::Variant),
92 field("bool", 2, message(<bool as Described>::DEFINITION), Cardinality::Variant,),
93 field("integer", 3, message(<i64 as Described>::DEFINITION), Cardinality::Variant,),
94 field("unsigned", 4, message(<u64 as Described>::DEFINITION), Cardinality::Variant,),
95 field("number", 5, message(<f64 as Described>::DEFINITION), Cardinality::Variant,),
96 field("text", 6, message(<String as Described>::DEFINITION), Cardinality::Variant,),
97 field("datetime", 7, message(Timestamp::DEFINITION), Cardinality::Variant,),
98 ]
99);
100level!(Value1, Entry1, Array1, Object1, Value0);
101level!(Value2, Entry2, Array2, Object2, Value1);
102level!(Value3, Entry3, Array3, Object3, Value2);
103level!(Value4, Entry4, Array4, Object4, Value3);
104
105impl Described for Value {
116 const NAME: &'static str = "harmos::Value";
117 const FIELDS: &'static [Field] = VALUE_FIELDS;
118 const MARKER: &'static [u8] = &crate::schema::declaration::encode::<
119 { crate::schema::declaration::encoded_len(Self::NAME, Self::FIELDS) },
120 >(Self::NAME, Self::FIELDS);
121}
122
123impl PostcardValue for Value {
124 fn write(&self, bytes: &mut Vec<u8>) {
125 match self {
126 Self::Null => NULL.write(bytes),
127 Self::Bool(value) => {
128 BOOL.write(bytes);
129 value.write(bytes);
130 }
131 Self::Integer(value) => {
132 INTEGER.write(bytes);
133 value.write(bytes);
134 }
135 Self::Unsigned(value) => {
136 UNSIGNED.write(bytes);
137 value.write(bytes);
138 }
139 Self::Number(value) => {
140 NUMBER.write(bytes);
141 value.write(bytes);
142 }
143 Self::Text(value) => {
144 TEXT.write(bytes);
145 value.write(bytes);
146 }
147 Self::Datetime(value) => {
148 DATETIME.write(bytes);
149 write_timestamp(*value, bytes);
150 }
151 Self::Array(values) => {
152 ARRAY.write(bytes);
153 values.len().write(bytes);
154 for value in values {
155 value.write(bytes);
156 }
157 }
158 Self::Object(entries) => {
159 OBJECT.write(bytes);
160 write_entries(entries, bytes);
161 }
162 }
163 }
164
165 fn size(&self) -> usize {
166 let payload = match self {
167 Self::Null => 0,
168 Self::Bool(value) => value.size(),
169 Self::Integer(value) => value.size(),
170 Self::Unsigned(value) => value.size(),
171 Self::Number(value) => value.size(),
172 Self::Text(value) => value.size(),
173 Self::Datetime(value) => timestamp_size(*value),
174 Self::Array(values) => values.iter().fold(values.len().size(), |size, value| size.saturating_add(value.size())),
175 Self::Object(entries) => entries_size(entries),
176 };
177 variant(self).size().saturating_add(payload)
178 }
179
180 fn memory(input: &mut Reader<'_>) -> Result<usize, MessageError> {
181 memory_at(input, VALUE_DEPTH)
182 }
183
184 fn read(input: &mut Reader<'_>) -> Result<Self, MessageError> {
185 read_at(input, VALUE_DEPTH)
186 }
187}
188
189const fn field(name: &'static str, tag: u32, kind: Kind, cardinality: Cardinality) -> Field {
194 Field {
195 name: Cow::Borrowed(name),
196 tag,
197 kind,
198 cardinality,
199 }
200}
201
202const fn message(definition: Definition) -> Kind {
203 Kind::Message { definition }
204}
205
206fn variant(value: &Value) -> u32 {
207 match value {
208 Value::Null => NULL,
209 Value::Bool(_) => BOOL,
210 Value::Integer(_) => INTEGER,
211 Value::Unsigned(_) => UNSIGNED,
212 Value::Number(_) => NUMBER,
213 Value::Text(_) => TEXT,
214 Value::Datetime(_) => DATETIME,
215 Value::Array(_) => ARRAY,
216 Value::Object(_) => OBJECT,
217 }
218}
219
220fn depth_error() -> MessageError {
221 MessageError::borrowed("value nests deeper than its portable depth")
222}
223
224pub(crate) fn timestamp_parts(value: OffsetDateTime) -> (i64, u32) {
225 (value.unix_timestamp(), value.nanosecond())
226}
227
228pub(crate) fn from_parts(seconds: i64, nanos: u64) -> Result<OffsetDateTime, MessageError> {
229 let nanos = u32::try_from(nanos)
230 .ok()
231 .filter(|nanos| *nanos < 1_000_000_000)
232 .ok_or_else(|| MessageError::borrowed("timestamp nanoseconds out of range"))?;
233 OffsetDateTime::from_unix_timestamp(seconds)
234 .ok()
235 .and_then(|value| value.replace_nanosecond(nanos).ok())
236 .ok_or_else(|| MessageError::borrowed("timestamp out of range"))
237}
238
239pub(crate) fn write_timestamp(value: OffsetDateTime, bytes: &mut Vec<u8>) {
240 let (seconds, nanos) = timestamp_parts(value);
241 seconds.write(bytes);
242 nanos.write(bytes);
243}
244
245pub(crate) fn timestamp_size(value: OffsetDateTime) -> usize {
246 let (seconds, nanos) = timestamp_parts(value);
247 seconds.size().saturating_add(nanos.size())
248}
249
250pub(crate) fn read_timestamp(input: &mut Reader<'_>) -> Result<OffsetDateTime, MessageError> {
251 let seconds = i64::read(input)?;
252 let nanos = u32::read(input)?;
253 from_parts(seconds, u64::from(nanos))
254}
255
256pub(crate) fn write_entries(entries: &BTreeMap<String, Value>, bytes: &mut Vec<u8>) {
257 entries.len().write(bytes);
258 for (key, value) in entries {
259 key.write(bytes);
260 value.write(bytes);
261 }
262}
263
264pub(crate) fn entries_size(entries: &BTreeMap<String, Value>) -> usize {
265 entries.iter().fold(entries.len().size(), |size, (key, value)| size.saturating_add(key.size()).saturating_add(value.size()))
266}
267
268pub(crate) fn entries_memory(input: &mut Reader<'_>, depth: usize) -> Result<usize, MessageError> {
269 input.nested(|input| {
270 let count: usize = input.value()?;
271 input.claim(count)?;
272 let mut owned = btree_map_memory::<String, Value>(count);
273 for _ in 0..count {
274 let key = String::memory(input)?.saturating_sub(std::mem::size_of::<String>());
275 let value = memory_at(input, depth)?.saturating_sub(std::mem::size_of::<Value>());
276 owned = decoding_add(owned, decoding_add(key, value)?)?;
277 }
278 Ok(owned)
279 })
280}
281
282pub(crate) fn read_entries(input: &mut Reader<'_>, depth: usize) -> Result<BTreeMap<String, Value>, MessageError> {
283 input.nested(|input| {
284 let count: usize = input.value()?;
285 input.claim(count)?;
286 let mut entries = BTreeMap::new();
287 for _ in 0..count {
288 let key = String::read(input)?;
289 let value = read_at(input, depth)?;
290 if entries.insert(key, value).is_some() {
291 return Err(MessageError::borrowed("duplicate value object key"));
292 }
293 }
294 Ok(entries)
295 })
296}
297
298fn memory_at(input: &mut Reader<'_>, depth: usize) -> Result<usize, MessageError> {
299 input.nested(|input| {
300 let owned = std::mem::size_of::<Value>();
301 let allocation = match u32::read(input)? {
302 NULL => 0,
303 BOOL => {
304 bool::read(input)?;
305 0
306 }
307 INTEGER => {
308 i64::read(input)?;
309 0
310 }
311 UNSIGNED => {
312 u64::read(input)?;
313 0
314 }
315 NUMBER => {
316 f64::read(input)?;
317 0
318 }
319 TEXT => String::memory(input)?.saturating_sub(std::mem::size_of::<String>()),
320 DATETIME => {
321 read_timestamp(input)?;
322 0
323 }
324 ARRAY => {
325 let depth = depth.checked_sub(1).ok_or_else(depth_error)?;
326 let count: usize = input.value()?;
327 input.claim(count)?;
328 let mut items = decoding_multiply(count, std::mem::size_of::<Value>())?;
329 for _ in 0..count {
330 let item = memory_at(input, depth)?;
331 items = decoding_add(items, item.saturating_sub(std::mem::size_of::<Value>()))?;
332 }
333 items
334 }
335 OBJECT => {
336 let depth = depth.checked_sub(1).ok_or_else(depth_error)?;
337 entries_memory(input, depth)?
338 }
339 _ => return Err(MessageError::borrowed("unknown value variant")),
340 };
341 decoding_add(owned, allocation)
342 })
343}
344
345fn read_at(input: &mut Reader<'_>, depth: usize) -> Result<Value, MessageError> {
346 input.nested(|input| {
347 Ok(match u32::read(input)? {
348 NULL => Value::Null,
349 BOOL => Value::Bool(bool::read(input)?),
350 INTEGER => Value::Integer(i64::read(input)?),
351 UNSIGNED => Value::Unsigned(u64::read(input)?),
352 NUMBER => Value::Number(f64::read(input)?),
353 TEXT => Value::Text(String::read(input)?),
354 DATETIME => Value::Datetime(read_timestamp(input)?),
355 ARRAY => {
356 let depth = depth.checked_sub(1).ok_or_else(depth_error)?;
357 let count: usize = input.value()?;
358 input.claim(count)?;
359 let mut items = crate::message::decoding_vector(count)?;
360 for _ in 0..count {
361 items.push(read_at(input, depth)?);
362 }
363 Value::Array(items)
364 }
365 OBJECT => {
366 let depth = depth.checked_sub(1).ok_or_else(depth_error)?;
367 Value::Object(read_entries(input, depth)?)
368 }
369 _ => return Err(MessageError::borrowed("unknown value variant")),
370 })
371 })
372}
373
374