Skip to main content

harmos_domain/model/storage/
codec.rs

1/* ***
2 *
3 * Harmos
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * ***
8 */
9
10/* === Modules === */
11
12mod timestamp;
13
14/* === Re-Exports === */
15
16pub use timestamp::Time;
17
18/* === Imports === */
19
20// Standard Library Imports
21use std::borrow::Cow;
22use std::marker::PhantomData;
23use std::num::NonZeroU32;
24use std::sync::Arc;
25
26// Third Party Imports
27
28// Local Imports
29use crate::__private::{PostcardReader, PostcardValue};
30use crate::schema::declaration::{self, Field, Kind};
31use crate::schema::{Cardinality, Described};
32use crate::{Identifier, MemorySize, MessageError};
33
34/* === Constants === */
35
36/* === Macros === */
37
38#[doc(hidden)]
39#[macro_export]
40macro_rules! storage_product {
41    ($ty:ty { $($field:ident: $codec:ty => $tag:literal),* $(,)? }) => {
42        $crate::model::storage::codec::product!($ty { $($field: $codec => $tag),* }, check = |_: &$ty| Ok(()));
43    };
44    ($ty:ty { $($field:ident: $codec:ty => $tag:literal),* $(,)? }, check = $check:expr) => {
45        impl $crate::schema::Described for $ty {
46            const NAME: &'static str = concat!(module_path!(), "::", stringify!($ty));
47            const FIELDS: &'static [$crate::schema::declaration::Field] = &[$($crate::schema::declaration::Field {
48                name: std::borrow::Cow::Borrowed(stringify!($field)),
49                tag: $tag,
50                kind: <$codec as $crate::model::storage::codec::Value>::KIND,
51                cardinality: <$codec as $crate::model::storage::codec::Value>::CARDINALITY,
52            }),*];
53
54            const MARKER: &'static [u8] = &$crate::schema::declaration::encode::<{
55                $crate::schema::declaration::encoded_len(Self::NAME, Self::FIELDS)
56            }>(Self::NAME, Self::FIELDS);
57}
58        #[allow(unused_variables)]
59        impl $crate::__private::PostcardValue for $ty {
60            fn write(&self, bytes: &mut Vec<u8>) {
61                $(<$codec as $crate::model::storage::codec::Value>::postcard_write(&self.$field, bytes);)*
62            }
63            fn size(&self) -> usize {
64                0usize$(.saturating_add(<$codec as $crate::model::storage::codec::Value>::postcard_size(&self.$field)))*
65            }
66            fn memory(input: &mut $crate::__private::PostcardReader<'_>) -> std::result::Result<usize, $crate::MessageError> {
67                input.nested(|input| {
68                    let memory = std::mem::size_of::<Self>();
69                    $(let memory = $crate::__private::decoding_add(memory, <$codec as $crate::model::storage::codec::Value>::postcard_memory(input)?)?;)*
70                    Ok(memory)
71                })
72            }
73            fn read(input: &mut $crate::__private::PostcardReader<'_>) -> std::result::Result<Self, $crate::MessageError> {
74                let value = input.nested(|input| Ok(Self { $($field: <$codec as $crate::model::storage::codec::Value>::postcard_read(input)?),* }))?;
75                let check: fn(&Self) -> std::result::Result<(), $crate::MessageError> = $check;
76                check(&value)?;
77                Ok(value)
78            }
79        }
80    };
81}
82
83pub use storage_product as product;
84
85macro_rules! postcard_field {
86    () => {
87        fn postcard_write(value: &Self::Native, bytes: &mut Vec<u8>) {
88            crate::__private::PostcardValue::write(value, bytes);
89        }
90        fn postcard_size(value: &Self::Native) -> usize {
91            crate::__private::PostcardValue::size(value)
92        }
93        fn postcard_memory(input: &mut crate::__private::PostcardReader<'_>) -> std::result::Result<usize, crate::MessageError> {
94            Ok(<Self::Native as crate::__private::PostcardValue>::memory(input)?.saturating_sub(std::mem::size_of::<Self::Native>()))
95        }
96        fn postcard_read(input: &mut crate::__private::PostcardReader<'_>) -> std::result::Result<Self::Native, crate::MessageError> {
97            <Self::Native as crate::__private::PostcardValue>::read(input)
98        }
99    };
100}
101pub(crate) use postcard_field;
102
103#[doc(hidden)]
104#[macro_export]
105macro_rules! storage_variants {
106    ($ty:ty { $($index:literal, $tag:literal, $name:literal: $pat:pat => { $($field:ident: $codec:ty => $ftag:literal),* $(,)? } => $build:expr;)+ }) => {
107        const _: () = {
108        struct Variant<const TAG: u32>;
109        $(impl $crate::schema::Described for Variant<$tag> {
110            const NAME: &'static str = concat!(module_path!(), "::", stringify!($ty), "::", $name);
111            const FIELDS: &'static [$crate::schema::declaration::Field] = &[$($crate::schema::declaration::Field {
112                name: std::borrow::Cow::Borrowed(stringify!($field)), tag: $ftag,
113                kind: <$codec as $crate::model::storage::codec::Value>::KIND,
114                cardinality: <$codec as $crate::model::storage::codec::Value>::CARDINALITY,
115            }),*];
116            const MARKER: &'static [u8] = &$crate::schema::declaration::encode::<{
117                $crate::schema::declaration::encoded_len(Self::NAME, Self::FIELDS)
118            }>(Self::NAME, Self::FIELDS);
119        })+
120        impl $crate::schema::Described for $ty {
121            const NAME: &'static str = concat!(module_path!(), "::", stringify!($ty));
122            const FIELDS: &'static [$crate::schema::declaration::Field] = &[$($crate::schema::declaration::Field {
123                name: std::borrow::Cow::Borrowed($name),
124                tag: $tag,
125                cardinality: $crate::schema::Cardinality::Variant,
126                kind: $crate::schema::declaration::Kind::Message {
127                    definition: <Variant<$tag> as $crate::schema::Described>::DEFINITION,
128                },
129            }),+];
130
131            // Every Storage Oneof Requires Its Variant; An Absent One Is Refused.
132            const DEFAULT_VARIANT: Option<usize> = None;
133            const MARKER: &'static [u8] = &$crate::schema::declaration::encode::<{
134                $crate::schema::declaration::encoded_len(Self::NAME, Self::FIELDS)
135            }>(Self::NAME, Self::FIELDS);
136}
137        impl $crate::__private::PostcardValue for $ty {
138            #[allow(unused_variables)]
139            fn write(&self, bytes: &mut Vec<u8>) {
140                match self {
141                    $($pat => {
142                        $crate::__private::PostcardValue::write(&($index as u32), bytes);
143                        $(<$codec as $crate::model::storage::codec::Value>::postcard_write($field, bytes);)*
144                    })+
145                }
146            }
147            #[allow(unused_variables)]
148            fn size(&self) -> usize {
149                match self {
150                    $($pat => $crate::__private::PostcardValue::size(&($index as u32))
151                        $(.saturating_add(<$codec as $crate::model::storage::codec::Value>::postcard_size($field)))*,)+
152                }
153            }
154            fn memory(input: &mut $crate::__private::PostcardReader<'_>) -> std::result::Result<usize, $crate::MessageError> {
155                input.nested(|input| {
156                    let memory = std::mem::size_of::<Self>();
157                    match input.value::<u32>()? {
158                        $($index => {
159                            $(let memory = $crate::__private::decoding_add(memory, <$codec as $crate::model::storage::codec::Value>::postcard_memory(input)?)?;)*
160                            Ok(memory)
161                        })+
162                        _ => Err($crate::MessageError::borrowed(concat!("unknown ", stringify!($ty), " variant"))),
163                    }
164                })
165            }
166            fn read(input: &mut $crate::__private::PostcardReader<'_>) -> std::result::Result<Self, $crate::MessageError> {
167                input.nested(|input| match input.value::<u32>()? {
168                    $($index => {
169                        $(let $field = <$codec as $crate::model::storage::codec::Value>::postcard_read(input)?;)*
170                        Ok($build)
171                    })+
172                    _ => Err($crate::MessageError::borrowed(concat!("unknown ", stringify!($ty), " variant"))),
173                })
174            }
175        }
176        };
177    };
178}
179pub use storage_variants as variants;
180
181#[doc(hidden)]
182#[macro_export]
183macro_rules! storage_coded {
184    ($ty:ident { $($variant:ident),+ $(,)? }) => {
185        impl $crate::model::storage::codec::Coded for $ty {
186            const NAME: &'static str = concat!(module_path!(), "::", stringify!($ty));
187            const VARIANTS: &'static [Self] = &[$(Self::$variant),+];
188        }
189    };
190}
191pub use storage_coded as coded;
192
193/* === Type Aliases === */
194
195type Result<T, E = MessageError> = std::result::Result<T, E>;
196
197/* === Structs === */
198
199pub struct Repeated<T>(PhantomData<fn() -> T>);
200pub struct Nested<T>(PhantomData<fn() -> T>);
201pub struct Shared<T>(PhantomData<fn() -> T>);
202pub struct Optional<T>(PhantomData<fn() -> T>);
203pub struct Id;
204pub struct Bytes;
205pub struct Unsigned;
206pub struct Percent;
207pub struct Version;
208pub struct Flag;
209pub struct Signed;
210pub struct Float;
211pub struct Text;
212pub struct Code<E>(PhantomData<fn() -> E>);
213pub struct Index;
214pub struct Wide;
215pub struct WideNonZero;
216pub struct WideSigned;
217pub struct Wrap<A>(PhantomData<fn() -> A>);
218pub struct Many<A>(PhantomData<fn() -> A>);
219
220/* === Enums === */
221
222/* === Traits === */
223
224pub trait Native: PostcardValue + MemorySize + Described {}
225impl<T: PostcardValue + MemorySize + Described> Native for T {}
226
227pub trait Coded: Copy + PartialEq + Send + Sync + 'static {
228    const NAME: &'static str;
229    const VARIANTS: &'static [Self];
230    fn code(&self) -> u32 {
231        Self::VARIANTS
232            .iter()
233            .position(|variant| variant == self)
234            .and_then(|index| u32::try_from(index).ok())
235            .expect("a coded variant is listed")
236    }
237
238    fn from_code(code: u64) -> Result<Self> {
239        usize::try_from(code)
240            .ok()
241            .and_then(|index| Self::VARIANTS.get(index).copied())
242            .ok_or_else(|| MessageError::borrowed("unknown storage enum code"))
243    }
244}
245
246pub trait Value: 'static {
247    const NAME: &'static str;
248    type Native;
249    const KIND: Kind;
250    const CARDINALITY: Cardinality = Cardinality::Required;
251    fn postcard_write(value: &Self::Native, bytes: &mut Vec<u8>);
252    fn postcard_size(value: &Self::Native) -> usize;
253    fn postcard_memory(input: &mut PostcardReader<'_>) -> Result<usize>;
254    fn postcard_read(input: &mut PostcardReader<'_>) -> Result<Self::Native>;
255}
256
257/* === Implementations === */
258
259impl<T: Native> Value for Repeated<T> {
260    const NAME: &'static str = declaration::Name::new(concat!(module_path!(), "::", stringify!(Repeated)), &[T::NAME]).as_str();
261    postcard_field!();
262    type Native = Vec<T>;
263    const KIND: Kind = Nested::<T>::KIND;
264    const CARDINALITY: Cardinality = Cardinality::Repeated;
265}
266
267impl<T: Native> Value for Nested<T> {
268    const NAME: &'static str = declaration::Name::new(concat!(module_path!(), "::", stringify!(Nested)), &[T::NAME]).as_str();
269    postcard_field!();
270    type Native = T;
271    const KIND: Kind = Kind::Message { definition: T::DEFINITION };
272}
273
274impl<T: Native> Value for Shared<T> {
275    const NAME: &'static str = Nested::<T>::NAME;
276    type Native = Arc<T>;
277    const KIND: Kind = Nested::<T>::KIND;
278
279    fn postcard_write(value: &Self::Native, bytes: &mut Vec<u8>) {
280        T::write(value, bytes);
281    }
282
283    fn postcard_size(value: &Self::Native) -> usize {
284        T::size(value)
285    }
286
287    fn postcard_memory(input: &mut PostcardReader<'_>) -> Result<usize> {
288        crate::__private::decoding_add(T::memory(input)?, 2 * std::mem::size_of::<usize>())
289    }
290
291    fn postcard_read(input: &mut PostcardReader<'_>) -> Result<Self::Native> {
292        T::read(input).map(Arc::new)
293    }
294}
295
296impl<T: Value> Value for Optional<T> {
297    const NAME: &'static str = declaration::Name::new(concat!(module_path!(), "::", stringify!(Optional)), &[T::NAME]).as_str();
298    fn postcard_write(value: &Self::Native, bytes: &mut Vec<u8>) {
299        PostcardValue::write(&value.is_some(), bytes);
300        if let Some(value) = value {
301            T::postcard_write(value, bytes);
302        }
303    }
304
305    fn postcard_size(value: &Self::Native) -> usize {
306        1usize.saturating_add(value.as_ref().map_or(0, T::postcard_size))
307    }
308
309    fn postcard_memory(input: &mut PostcardReader<'_>) -> Result<usize> {
310        input.nested(|input| if input.value::<bool>()? { T::postcard_memory(input) } else { Ok(0) })
311    }
312
313    fn postcard_read(input: &mut PostcardReader<'_>) -> Result<Self::Native> {
314        input.nested(|input| if input.value::<bool>()? { T::postcard_read(input).map(Some) } else { Ok(None) })
315    }
316
317    type Native = Option<T::Native>;
318    const KIND: Kind = T::KIND;
319    const CARDINALITY: Cardinality = Cardinality::Optional;
320}
321
322impl Value for Id {
323    const NAME: &'static str = concat!(module_path!(), "::", stringify!(Id));
324    postcard_field!();
325    type Native = Identifier;
326    const KIND: Kind = Kind::String;
327}
328
329impl Value for Bytes {
330    const NAME: &'static str = concat!(module_path!(), "::", stringify!(Bytes));
331    postcard_field!();
332    type Native = Vec<u8>;
333    const KIND: Kind = Kind::Bytes;
334}
335
336impl Value for Unsigned {
337    const NAME: &'static str = concat!(module_path!(), "::", stringify!(Unsigned));
338    postcard_field!();
339    type Native = u64;
340    const KIND: Kind = Kind::U64;
341}
342
343// A whole percentage rank, carried as a protobuf `uint32`; the rank's range is
344// a plan rule, so any byte decodes and the plan check refuses above 100.
345impl Value for Percent {
346    const NAME: &'static str = concat!(module_path!(), "::", stringify!(Percent));
347    postcard_field!();
348    type Native = u8;
349    const KIND: Kind = Kind::U32;
350}
351
352impl Value for Version {
353    const NAME: &'static str = concat!(module_path!(), "::", stringify!(Version));
354    postcard_field!();
355    type Native = NonZeroU32;
356    const KIND: Kind = Kind::U32;
357}
358
359macro_rules! varint {
360    ($adapter:ty, $native:ty, $kind:ident, $encoding:ident, $from:expr) => {
361        impl Value for $adapter {
362            const NAME: &'static str = concat!(module_path!(), "::", stringify!($adapter));
363            postcard_field!();
364            type Native = $native;
365            const KIND: Kind = Kind::$kind;
366        }
367    };
368}
369
370varint!(Flag, bool, Bool, bool, |value: u64| match value {
371    0 => Ok(false),
372    1 => Ok(true),
373    _ => Err(MessageError::borrowed("invalid storage boolean")),
374});
375varint!(Signed, i64, I64, int64, |value: u64| Ok(value as i64));
376
377impl Value for Float {
378    const NAME: &'static str = concat!(module_path!(), "::", stringify!(Float));
379    postcard_field!();
380    type Native = f64;
381    const KIND: Kind = Kind::F64;
382}
383
384impl Value for Text {
385    const NAME: &'static str = concat!(module_path!(), "::", stringify!(Text));
386    postcard_field!();
387    type Native = String;
388    const KIND: Kind = Kind::String;
389}
390
391impl<E: Coded> Value for Code<E> {
392    const NAME: &'static str = declaration::Name::new(concat!(module_path!(), "::", stringify!(Code)), &[E::NAME]).as_str();
393    type Native = E;
394    const KIND: Kind = Kind::U32;
395    fn postcard_write(value: &E, bytes: &mut Vec<u8>) {
396        PostcardValue::write(&value.code(), bytes);
397    }
398
399    fn postcard_size(value: &E) -> usize {
400        PostcardValue::size(&value.code())
401    }
402
403    fn postcard_memory(input: &mut PostcardReader<'_>) -> Result<usize> {
404        E::from_code(u64::from(input.value::<u32>()?))?;
405        Ok(0)
406    }
407
408    fn postcard_read(input: &mut PostcardReader<'_>) -> Result<E> {
409        E::from_code(u64::from(input.value::<u32>()?))
410    }
411}
412
413// Host Indices And Counts Travel As uint64; Decoding Never Truncates.
414fn host_width(value: u64) -> Result<usize> {
415    usize::try_from(value).map_err(|_| MessageError::borrowed("index exceeds host width"))
416}
417
418impl Value for Index {
419    const NAME: &'static str = concat!(module_path!(), "::", stringify!(Index));
420    type Native = usize;
421    const KIND: Kind = Kind::U64;
422    fn postcard_write(value: &usize, bytes: &mut Vec<u8>) {
423        PostcardValue::write(&(*value as u64), bytes);
424    }
425
426    fn postcard_size(value: &usize) -> usize {
427        PostcardValue::size(&(*value as u64))
428    }
429
430    fn postcard_memory(input: &mut PostcardReader<'_>) -> Result<usize> {
431        Self::postcard_read(input)?;
432        Ok(0)
433    }
434
435    fn postcard_read(input: &mut PostcardReader<'_>) -> Result<usize> {
436        host_width(input.value::<u64>()?)
437    }
438}
439
440// 128-Bit Values Travel As A Message Of Lossless High And Low Halves.
441macro_rules! wide {
442    ($adapter:ty, $native:ty, $high:ty, $high_codec:ty, $split:expr, $join:expr) => {
443        impl Described for $adapter {
444            const NAME: &'static str = <Self as Value>::NAME;
445            const FIELDS: &'static [Field] = &[
446                crate::schema::declaration::Field {
447                    name: Cow::Borrowed("high"),
448                    tag: 1,
449                    kind: <$high_codec as Value>::KIND,
450                    cardinality: Cardinality::Required,
451                },
452                crate::schema::declaration::Field {
453                    name: Cow::Borrowed("low"),
454                    tag: 2,
455                    kind: Kind::U64,
456                    cardinality: Cardinality::Required,
457                },
458            ];
459            const MARKER: &'static [u8] = &declaration::encode::<{ declaration::encoded_len(<Self as Described>::NAME, Self::FIELDS) }>(
460                <Self as Described>::NAME,
461                Self::FIELDS,
462            );
463        }
464        impl Value for $adapter {
465            const NAME: &'static str = concat!(module_path!(), "::", stringify!($adapter));
466            type Native = $native;
467            const KIND: Kind = Kind::Message {
468                definition: <Self as Described>::DEFINITION,
469            };
470            fn postcard_write(value: &$native, bytes: &mut Vec<u8>) {
471                let (high, low): ($high, u64) = ($split)(*value);
472                PostcardValue::write(&high, bytes);
473                PostcardValue::write(&low, bytes);
474            }
475            fn postcard_size(value: &$native) -> usize {
476                let (high, low): ($high, u64) = ($split)(*value);
477                PostcardValue::size(&high).saturating_add(PostcardValue::size(&low))
478            }
479            fn postcard_memory(input: &mut PostcardReader<'_>) -> Result<usize> {
480                Self::postcard_read(input)?;
481                Ok(0)
482            }
483            fn postcard_read(input: &mut PostcardReader<'_>) -> Result<$native> {
484                let high = input.value::<$high>()?;
485                let low = input.value::<u64>()?;
486                ($join)(high, low)
487            }
488        }
489    };
490}
491
492wide!(Wide, u128, u64, Unsigned, |value: u128| ((value >> 64) as u64, value as u64), |high: u64, low: u64| Ok::<_, MessageError>(
493    (u128::from(high) << 64) | u128::from(low)
494));
495wide!(
496    WideNonZero,
497    std::num::NonZeroU128,
498    u64,
499    Unsigned,
500    |value: std::num::NonZeroU128| ((value.get() >> 64) as u64, value.get() as u64),
501    |high: u64, low: u64| std::num::NonZeroU128::new((u128::from(high) << 64) | u128::from(low))
502        .ok_or_else(|| MessageError::borrowed("wide value must be nonzero"))
503);
504wide!(WideSigned, i128, i64, Signed, |value: i128| ((value >> 64) as i64, value as u64), |high: i64, low: u64| Ok::<_, MessageError>(
505    (i128::from(high) << 64) | i128::from(low)
506));
507
508// One Message Holding A Single Field At Tag 1; Absence Reads As Empty.
509impl<A: Value> Described for Wrap<A> {
510    const NAME: &'static str = <Self as Value>::NAME;
511    const FIELDS: &'static [Field] = &[crate::schema::declaration::Field {
512        name: Cow::Borrowed("value"),
513        tag: 1,
514        kind: A::KIND,
515        cardinality: A::CARDINALITY,
516    }];
517    const MARKER: &'static [u8] = declaration::encode_buffer::<2048>(<Self as Described>::NAME, Self::FIELDS)
518        .split_at(declaration::encoded_len(<Self as Described>::NAME, Self::FIELDS))
519        .0;
520}
521impl<A: Value> Value for Wrap<A> {
522    const NAME: &'static str = declaration::Name::new(concat!(module_path!(), "::", stringify!(Wrap)), &[A::NAME]).as_str();
523    type Native = A::Native;
524    const KIND: Kind = Kind::Message {
525        definition: <Self as Described>::DEFINITION,
526    };
527    fn postcard_write(value: &A::Native, bytes: &mut Vec<u8>) {
528        A::postcard_write(value, bytes);
529    }
530
531    fn postcard_size(value: &A::Native) -> usize {
532        A::postcard_size(value)
533    }
534
535    fn postcard_memory(input: &mut PostcardReader<'_>) -> Result<usize> {
536        A::postcard_memory(input)
537    }
538
539    fn postcard_read(input: &mut PostcardReader<'_>) -> Result<A::Native> {
540        A::postcard_read(input)
541    }
542}
543
544// Repeated Messages, Each Holding One Element At Tag 1.
545impl<A: Value> Value for Many<A> {
546    const NAME: &'static str = declaration::Name::new(concat!(module_path!(), "::", stringify!(Many)), &[A::NAME]).as_str();
547    type Native = Vec<A::Native>;
548    const KIND: Kind = Wrap::<A>::KIND;
549    const CARDINALITY: Cardinality = Cardinality::Repeated;
550    fn postcard_write(values: &Vec<A::Native>, bytes: &mut Vec<u8>) {
551        PostcardValue::write(&(values.len() as u64), bytes);
552        for value in values {
553            A::postcard_write(value, bytes);
554        }
555    }
556
557    fn postcard_size(values: &Vec<A::Native>) -> usize {
558        values.iter().fold(PostcardValue::size(&(values.len() as u64)), |size, value| size.saturating_add(A::postcard_size(value)))
559    }
560
561    fn postcard_memory(input: &mut PostcardReader<'_>) -> Result<usize> {
562        let count = host_width(input.value::<u64>()?)?;
563        input.claim(count)?;
564        let mut memory = crate::__private::decoding_multiply(count, std::mem::size_of::<A::Native>())?;
565        for _ in 0..count {
566            memory = crate::__private::decoding_add(memory, A::postcard_memory(input)?)?;
567        }
568        Ok(memory)
569    }
570
571    fn postcard_read(input: &mut PostcardReader<'_>) -> Result<Vec<A::Native>> {
572        let count = host_width(input.value::<u64>()?)?;
573        input.claim(count)?;
574        let mut values = crate::__private::decoding_vector(count)?;
575        for _ in 0..count {
576            values.push(A::postcard_read(input)?);
577        }
578        Ok(values)
579    }
580}
581
582// One Message Holding A Pair At Tags 1 And 2.
583/* === Public Functions === */
584
585/* === Private Functions === */
586
587/* === Tests === */