Skip to main content

harmos_domain/
registration.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
17
18// Third Party Imports
19use serde::Serialize;
20// Local Imports
21use crate::identity::artifact_subset;
22
23/* === Constants === */
24
25/* === Macros === */
26
27/* === Type Aliases === */
28
29/* === Structs === */
30
31#[derive(Clone, Debug, PartialEq, Eq, Serialize, serde::Deserialize)]
32pub struct Registration {
33    pub namespace: String,
34    pub schema: u32,
35    pub payload: Vec<u8>,
36}
37
38#[derive(Debug, Default)]
39pub struct Registrar {
40    registrations: Vec<Registration>,
41}
42
43/* === Enums === */
44
45#[derive(Debug, thiserror::Error)]
46pub enum RegistrationError {
47    #[error("`{namespace}` is not a portable registration namespace")]
48    InvalidNamespace { namespace: String },
49
50    #[error("registration `{namespace}` has a zero schema ordinal")]
51    ZeroSchema { namespace: String },
52
53    #[error("registration namespace `{namespace}` was declared more than once")]
54    DuplicateNamespace { namespace: String },
55
56    #[error("registration `{namespace}` could not be encoded: {source}")]
57    Encode {
58        namespace: String,
59
60        #[source]
61        source: serde_json::Error,
62    },
63}
64
65/* === Traits === */
66
67/* === Implementations === */
68
69impl Registrar {
70    pub fn new() -> Self {
71        Self::default()
72    }
73
74    pub fn register<T: Serialize>(&mut self, namespace: impl Into<String>, schema: u32, value: &T) -> Result<(), RegistrationError> {
75        let namespace = namespace.into();
76        if !artifact_subset(&namespace) {
77            return Err(RegistrationError::InvalidNamespace { namespace });
78        }
79        if schema == 0 {
80            return Err(RegistrationError::ZeroSchema { namespace });
81        }
82        if self.registrations.iter().any(|entry| entry.namespace == namespace) {
83            return Err(RegistrationError::DuplicateNamespace { namespace });
84        }
85        let payload = serde_json::to_vec(value).map_err(|source| RegistrationError::Encode { namespace: namespace.clone(), source })?;
86        self.registrations.push(Registration { namespace, schema, payload });
87        Ok(())
88    }
89
90    pub fn finish(mut self) -> Vec<Registration> {
91        self.registrations.sort_by(|left, right| left.namespace.cmp(&right.namespace));
92        self.registrations
93    }
94}
95
96/* === Public Functions === */
97
98/* === Private Functions === */
99
100/* === Tests === */