Skip to main content

harmos_domain/operations/common/
catalog.rs

1/* ***
2 *
3 * Harmos
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * ***
8 */
9
10/* === Modules === */
11
12/* === Re-Exports === */
13
14/* === Imports === */
15
16// Standard Library Imports
17use std::collections::BTreeSet;
18// Third Party Imports
19
20// Local Imports
21use super::{Declares, Definition, OperationDeclaration, OperationPolicy, ReplaySafety, Visibility};
22use crate::catalog::{self, Catalog, Member, Node, Projection, Visitor};
23use crate::{Error, Identifier, Result};
24
25/* === Constants === */
26
27/* === Macros === */
28
29/* === Type Aliases === */
30
31/* === Structs === */
32
33#[derive(Clone, Copy, Debug, PartialEq, Eq)]
34pub struct Entry {
35    pub id: &'static str,
36    pub description: &'static str,
37    pub policy: OperationPolicy,
38    pub visibility: Visibility,
39    pub replay: ReplaySafety,
40}
41
42pub struct Declarations;
43
44/* === Enums === */
45
46/* === Traits === */
47
48/* === Implementations === */
49
50impl Entry {
51    pub const fn of<O: OperationDeclaration>() -> Self {
52        Self { id: O::ID, description: O::DESCRIPTION, policy: O::POLICY, visibility: O::VISIBILITY, replay: O::REPLAY }
53    }
54
55    pub fn definition(&self) -> Result<Definition> {
56        let id = Identifier::new(self.id)?;
57        let definition = Definition {
58            id,
59            description: self.description.to_owned(),
60            policy: self.policy,
61            visibility: self.visibility,
62            replay: self.replay,
63        };
64        definition.validate()?;
65        Ok(definition)
66    }
67}
68
69impl Visitor for Declarations {
70    type Entry = Entry;
71}
72
73impl<M: Declares> Member<M> for Declarations {
74    const ENTRY: Entry = Entry::of::<M::Declaration>();
75}
76
77impl Declarations {
78    pub fn of<C: Catalog<Self>>() -> Result<Vec<Definition>> {
79        Self::from_projection(&C::ENTRIES)
80    }
81
82    pub fn from_entries(entries: &[Entry]) -> Result<Vec<Definition>> {
83        let mut names = BTreeSet::new();
84        let mut definitions = Vec::with_capacity(entries.len());
85        for declaration in entries {
86            append(declaration, &mut names, &mut definitions)?;
87        }
88        Ok(definitions)
89    }
90
91    pub fn from_tree(entries: &[Node<Entry>]) -> Result<Vec<Definition>> {
92        let mut names = BTreeSet::new();
93        let mut definitions = Vec::with_capacity(catalog::count(entries));
94        catalog::try_for_each(entries, |declaration| append(declaration, &mut names, &mut definitions))?;
95        Ok(definitions)
96    }
97
98    pub fn from_projection<P: Projection<Entry>>(entries: &P) -> Result<Vec<Definition>> {
99        let mut names = BTreeSet::new();
100        let mut definitions = Vec::with_capacity(P::LEN);
101        entries.try_for_each(|declaration| append(declaration, &mut names, &mut definitions))?;
102        Ok(definitions)
103    }
104}
105
106/* === Public Functions === */
107
108/* === Private Functions === */
109
110fn append(declaration: &Entry, names: &mut BTreeSet<Identifier>, definitions: &mut Vec<Definition>) -> Result<()> {
111    let definition = declaration.definition()?;
112    if !names.insert(definition.id.clone()) {
113        return Err(Error::DuplicateOperation { id: declaration.id.to_owned() });
114    }
115    definitions.push(definition);
116    Ok(())
117}
118
119/* === Tests === */