Skip to main content

harmos_domain/
schema.rs

1/* ***
2 *
3 * Harmos
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * ***
8 */
9
10// TODO: Describe this module's responsibility.
11
12/* === Modules === */
13
14pub mod declaration;
15pub mod graph;
16pub mod identity;
17mod payload;
18
19/* === Re-Exports === */
20
21pub use declaration::{Field, Kind};
22pub use payload::{Event, PathElement, PayloadError, Scalar, Validator, VisitError};
23
24/* === Imports === */
25
26// Standard Library Imports
27use std::borrow::Cow;
28// Third Party Imports
29use serde::{Deserialize, Serialize};
30// Local Imports
31
32/* === Constants === */
33
34pub const MAX_DEPTH: usize = 32;
35pub const MAX_NAME_BYTES: usize = 256;
36
37/* === Macros === */
38
39// Scalar Wrapper Payloads, With Their Fixed Field-One Identity
40macro_rules! wrapper {
41    ($($ty:ty => $kind:ident),* $(,)?) => {$(
42        impl Described for $ty {
43            const NAME: &'static str = concat!("harmos::", stringify!($ty));
44            const FIELDS: &'static [graph::Field<declaration::Definition>] = &[graph::Field {
45                name: Cow::Borrowed("value"),
46                tag: 1,
47                kind: graph::Kind::$kind,
48                cardinality: Cardinality::Required,
49            }];
50            const MARKER: &'static [u8] = &declaration::encode::<{
51                declaration::encoded_len(Self::NAME, Self::FIELDS)
52            }>(Self::NAME, Self::FIELDS);
53        }
54    )*};
55}
56
57wrapper!(bool => Bool, u32 => U32, u64 => U64, i32 => I32, i64 => I64, f32 => F32, f64 => F64, String => String, Vec<u8> => Bytes);
58
59/* === Type Aliases === */
60
61/* === Structs === */
62
63/* === Enums === */
64
65#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
66#[serde(rename_all = "snake_case")]
67pub enum Cardinality {
68    Required,
69    Optional,
70    Repeated,
71    Variant,
72}
73
74#[derive(Debug, thiserror::Error)]
75pub enum Error {
76    #[error(transparent)]
77    Graph(#[from] graph::Error),
78}
79
80/* === Traits === */
81
82// A Static Message Shape, Independent Of Payload Encoding Or Construction.
83pub trait Described: 'static {
84    const NAME: &'static str;
85    const FIELDS: &'static [graph::Field<declaration::Definition>];
86    const MARKER: &'static [u8];
87
88    const DEFAULT_VARIANT: Option<usize> = Some(0);
89
90    const DEFINITION: declaration::Definition = declaration::Definition::of::<Self>();
91}
92
93/* === Implementations === */
94
95impl Described for () {
96    const NAME: &'static str = "harmos::unit";
97    const FIELDS: &'static [graph::Field<declaration::Definition>] = &[];
98    const MARKER: &'static [u8] = &declaration::encode::<{ declaration::encoded_len(Self::NAME, Self::FIELDS) }>(Self::NAME, Self::FIELDS);
99}
100
101/* === Public Functions === */
102
103/* === Private Functions === */
104
105fn diagnostic_name(name: &str) -> String {
106    if name.len() <= MAX_NAME_BYTES {
107        return name.to_owned();
108    }
109    let mut end = MAX_NAME_BYTES - 3;
110    while !name.is_char_boundary(end) {
111        end -= 1;
112    }
113    let mut result = String::with_capacity(MAX_NAME_BYTES);
114    result.push_str(&name[..end]);
115    result.push_str("...");
116    result
117}
118
119/* === Tests === */