Skip to main content

icydb_model/
types.rs

1use crate::prelude::*;
2use icydb_schema::ScalarKind;
3use std::str::FromStr;
4
5//
6// Cardinality
7//
8// Schema-level multiplicity marker used by codegen and validation passes.
9// `One` means a required single value.
10// `Opt` means an optional slot (nullable / absent is valid).
11// `Many` means repeated values (for list/set-like shapes).
12//
13
14#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
15pub enum Cardinality {
16    #[default]
17    One,
18    Opt,
19    Many,
20}
21
22impl FromStr for Cardinality {
23    type Err = &'static str;
24
25    fn from_str(s: &str) -> Result<Self, Self::Err> {
26        match s {
27            "One" => Ok(Self::One),
28            "Opt" => Ok(Self::Opt),
29            "Many" => Ok(Self::Many),
30            _ => Err("unknown Cardinality"),
31        }
32    }
33}
34
35//
36// Primitive
37//
38// Width-preserving scalar vocabulary used by the application authoring graph.
39// `icydb-schema` owns the catalog and its canonical `ScalarKind` mapping;
40// accepted runtime capability policy belongs to `ScalarKind` metadata.
41//
42
43macro_rules! define_primitive {
44    ( @entries $( ($primitive:ident, $scalar:ident) ),* $(,)? ) => {
45        #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
46        #[remain::sorted]
47        pub enum Primitive {
48            $( $primitive, )*
49        }
50
51        impl FromStr for Primitive {
52            type Err = &'static str;
53
54            fn from_str(value: &str) -> Result<Self, Self::Err> {
55                match value {
56                    $( stringify!($primitive) => Ok(Self::$primitive), )*
57                    _ => Err("unknown Primitive"),
58                }
59            }
60        }
61
62        const fn primitive_scalar_kind(primitive: Primitive) -> ScalarKind {
63            match primitive {
64                $( Primitive::$primitive => ScalarKind::$scalar, )*
65            }
66        }
67    };
68}
69
70icydb_schema::authoring_primitive_registry!(define_primitive);
71
72impl Primitive {
73    #[must_use]
74    pub const fn is_primary_key_component_encodable(self) -> bool {
75        primitive_scalar_kind(self).is_primary_key_component_encodable()
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::{Primitive, primitive_scalar_kind};
82    use icydb_schema::ScalarKind;
83
84    macro_rules! define_primitive_cases {
85        ( @entries $( ($primitive:ident, $scalar:ident) ),* $(,)? ) => {
86            const PRIMITIVE_CASES: &[(&str, Primitive, ScalarKind)] = &[
87                $(
88                    (
89                        stringify!($primitive),
90                        Primitive::$primitive,
91                        ScalarKind::$scalar,
92                    ),
93                )*
94            ];
95        };
96    }
97
98    icydb_schema::authoring_primitive_registry!(define_primitive_cases);
99
100    #[test]
101    fn primitive_catalog_parses_and_maps_to_scalar_kinds() {
102        for &(name, primitive, scalar_kind) in PRIMITIVE_CASES {
103            assert_eq!(name.parse(), Ok(primitive));
104            assert_eq!(primitive_scalar_kind(primitive), scalar_kind);
105        }
106
107        assert_eq!("Unknown".parse::<Primitive>(), Err("unknown Primitive"));
108    }
109}