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