Skip to main content

harmos_domain/plugin/
mod.rs

1/* ***
2 *
3 * Harmos
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * ***
8 */
9
10/* === Modules === */
11
12mod requirement;
13
14/* === Re-Exports === */
15
16pub use requirement::{Grant, Requirement, Requirements};
17
18/* === Imports === */
19
20// Standard Library Imports
21// Third Party Imports
22// Local Imports
23
24/* === Constants === */
25
26/* === Macros === */
27
28/* === Type Aliases === */
29
30/* === Structs === */
31
32/* === Enums === */
33
34/* === Traits === */
35
36pub trait Contribution: 'static {
37    const NAMESPACE: &'static str;
38    const SECTION: crate::inventory::Section;
39
40    fn register(registrar: &mut crate::Registrar) -> Result<(), crate::RegistrationError>;
41}
42
43pub trait Declared: Send + Sync + 'static {
44    const ID: &'static str;
45    const VERSION: &'static str;
46    const DESCRIPTION: &'static str;
47    const PROVIDES: &'static [crate::catalog::Node<crate::operations::WireDeclaration>];
48    const REQUIRES: &'static [crate::catalog::Node<Requirement>];
49    const CONTRIBUTIONS: &'static [crate::inventory::Section] = &[];
50    const LISTENERS: &'static [crate::catalog::Node<crate::listeners::Entry>] = &[];
51    const OBSERVERS: &'static [crate::catalog::Node<crate::inventory::observers::Entry>] = &[];
52    const STREAMS: &'static [crate::inventory::publications::Entry];
53
54    fn markers() -> Result<Vec<&'static [u8]>, crate::schema::graph::Error>;
55}
56
57/* === Implementations === */
58
59/* === Public Functions === */
60
61// Retain Each Shared Type Once Alongside The Artifact's Carrier Sections.
62pub fn schema_markers<P: Declared>(
63    mut carrier: Vec<&'static [u8]>, settings: &crate::config::SchemaSettings,
64) -> Result<Vec<&'static [u8]>, crate::schema::graph::Error> {
65    use crate::schema::Described;
66    use crate::schema::declaration::Definition;
67    use crate::schema::graph::Error;
68    let carrier_bytes = carrier.capacity().checked_mul(std::mem::size_of::<&[u8]>()).ok_or(Error::Budget)?;
69    if carrier_bytes > settings.preparation_bytes.get() {
70        return Err(Error::Budget);
71    }
72    let mut roots = Vec::new();
73    {
74        let mut append = |definition: &crate::operations::WireDeclaration| {
75            push_schema_root(&mut roots, definition.request, carrier_bytes, settings)?;
76            push_schema_root(&mut roots, definition.response, carrier_bytes, settings)?;
77            for item in [definition.input, definition.output].into_iter().flatten() {
78                push_schema_root(&mut roots, item, carrier_bytes, settings)?;
79            }
80            Ok(())
81        };
82        crate::catalog::try_for_each(P::PROVIDES, &mut append)?;
83        crate::catalog::try_for_each(P::REQUIRES, |requirement| append(&requirement.declaration))?;
84        if crate::catalog::count(P::OBSERVERS) != 0 {
85            append(&crate::operations::WireDeclaration::of::<crate::observers::Control>())?;
86        }
87        crate::catalog::try_for_each(P::LISTENERS, |listener| append(&listener.callback))?;
88    }
89    for stream in P::STREAMS {
90        push_schema_root(&mut roots, stream.row, carrier_bytes, settings)?;
91    }
92    crate::catalog::try_for_each(P::LISTENERS, |listener| push_schema_root(&mut roots, listener.source.row(), carrier_bytes, settings))?;
93    push_schema_root(
94        &mut roots,
95        <crate::operations::lifecycle::Initialize as crate::schema::Described>::DEFINITION,
96        carrier_bytes,
97        settings,
98    )?;
99    push_schema_root(&mut roots, <()>::DEFINITION, carrier_bytes, settings)?;
100    let retained = roots
101        .capacity()
102        .checked_mul(std::mem::size_of::<Definition>())
103        .and_then(|bytes| bytes.checked_add(carrier.capacity() * std::mem::size_of::<&[u8]>()))
104        .ok_or(Error::Budget)?;
105    let remaining = settings.preparation_bytes.get().checked_sub(retained).and_then(std::num::NonZeroUsize::new).ok_or(Error::Budget)?;
106    let allowance = crate::config::SchemaSettings { preparation_bytes: remaining, ..*settings };
107    let declarations = crate::schema::declaration::markers_many(roots, &allowance)?;
108    let output = carrier
109        .len()
110        .checked_add(declarations.len())
111        .and_then(|count| count.checked_mul(4 * std::mem::size_of::<&[u8]>()))
112        .and_then(|bytes| bytes.checked_add(declarations.capacity() * std::mem::size_of::<&[u8]>()))
113        .ok_or(Error::Budget)?;
114    if output > settings.preparation_bytes.get() {
115        return Err(Error::Budget);
116    }
117    carrier.extend(declarations);
118    Ok(carrier)
119}
120
121/* === Private Functions === */
122
123fn push_schema_root(
124    roots: &mut Vec<crate::schema::declaration::Definition>, definition: crate::schema::declaration::Definition, carrier_bytes: usize,
125    settings: &crate::config::SchemaSettings,
126) -> Result<(), crate::schema::graph::Error> {
127    use crate::schema::graph::Error;
128    let count = roots.len().checked_add(1).ok_or(Error::Budget)?;
129    let bytes = count
130        .checked_mul(4 * std::mem::size_of::<crate::schema::declaration::Definition>())
131        .and_then(|bytes| bytes.checked_add(carrier_bytes))
132        .ok_or(Error::Budget)?;
133    if bytes > settings.preparation_bytes.get() || count > settings.preparation_work.get() {
134        return Err(Error::Budget);
135    }
136    roots.push(definition);
137    Ok(())
138}
139
140/* === Tests === */