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