Skip to main content

icydb_model/base/
mod.rs

1//! Module: base
2//!
3//! Responsibility: facade module surface.
4//! Does not own: database runtime authority.
5//! Boundary: keeps public facade shape stable for downstream code.
6
7pub(crate) mod helper;
8pub mod normalizer;
9pub mod types;
10pub mod validator;
11
12#[cfg(test)]
13mod tests {
14    use crate::{
15        Path as _,
16        base::types::{
17            color::{RgbHex, RgbaHex},
18            finance::{E8s, E18s, Usd},
19            geo::{AddressLine, CityName, PostalCode, RegionName},
20            hash::Sha256,
21            ident::{Constant, Field, Function, Variable, Variant},
22            intl::{CountryCode, LanguageCode, PhoneNumber},
23            lang::Code,
24            num::{Degrees, Percent, PercentModifier},
25            web::{MimeType, Url},
26        },
27        build::schema_read,
28        node::Newtype,
29    };
30
31    #[test]
32    fn built_in_durable_rules_and_application_validators_have_disjoint_owners() {
33        let schema = schema_read();
34        for path in [
35            Degrees::PATH,
36            Percent::PATH,
37            PercentModifier::PATH,
38            Usd::PATH,
39            E8s::PATH,
40            E18s::PATH,
41            AddressLine::PATH,
42            CityName::PATH,
43            PostalCode::PATH,
44            RegionName::PATH,
45        ] {
46            let newtype = schema
47                .cast_node::<Newtype>(path)
48                .expect("durable built-in newtype should be registered");
49            assert_eq!(newtype.ty().rules().len(), 1, "{path}");
50            assert!(newtype.ty().validators().is_empty(), "{path}");
51        }
52
53        for path in [
54            Constant::PATH,
55            Field::PATH,
56            Function::PATH,
57            Variable::PATH,
58            Variant::PATH,
59        ] {
60            let newtype = schema
61                .cast_node::<Newtype>(path)
62                .expect("identifier built-in newtype should be registered");
63            assert_eq!(newtype.ty().rules().len(), 1, "{path}");
64            assert_eq!(newtype.ty().validators().len(), 1, "{path}");
65        }
66
67        for path in [Url::PATH, MimeType::PATH, PhoneNumber::PATH] {
68            let newtype = schema
69                .cast_node::<Newtype>(path)
70                .expect("application-only built-in newtype should be registered");
71            assert!(newtype.ty().rules().is_empty(), "{path}");
72            assert!(!newtype.ty().validators().is_empty(), "{path}");
73        }
74
75        for path in [
76            RgbHex::PATH,
77            RgbaHex::PATH,
78            Sha256::PATH,
79            CountryCode::PATH,
80            LanguageCode::PATH,
81            Code::PATH,
82        ] {
83            let newtype = schema
84                .cast_node::<Newtype>(path)
85                .expect("application-only built-in newtype should be registered");
86            assert!(newtype.ty().rules().is_empty(), "{path}");
87            assert!(!newtype.ty().validators().is_empty(), "{path}");
88        }
89
90        let mut classified = [
91            Degrees::PATH,
92            Percent::PATH,
93            PercentModifier::PATH,
94            Usd::PATH,
95            E8s::PATH,
96            E18s::PATH,
97            AddressLine::PATH,
98            CityName::PATH,
99            PostalCode::PATH,
100            RegionName::PATH,
101            Constant::PATH,
102            Field::PATH,
103            Function::PATH,
104            Variable::PATH,
105            Variant::PATH,
106            Url::PATH,
107            MimeType::PATH,
108            PhoneNumber::PATH,
109            RgbHex::PATH,
110            RgbaHex::PATH,
111            Sha256::PATH,
112            CountryCode::PATH,
113            LanguageCode::PATH,
114            Code::PATH,
115        ];
116        classified.sort_unstable();
117        let attached = schema
118            .get_nodes::<Newtype>()
119            .filter(|(_, newtype)| {
120                !newtype.ty().rules().is_empty() || !newtype.ty().validators().is_empty()
121            })
122            .map(|(path, _)| path)
123            .collect::<Vec<_>>();
124        assert_eq!(attached, classified);
125
126        for (path, expected_scale) in [(Usd::PATH, 2), (E8s::PATH, 8), (E18s::PATH, 18)] {
127            let newtype = schema
128                .cast_node::<Newtype>(path)
129                .expect("decimal built-in newtype should be registered");
130            assert_eq!(newtype.item().scale(), Some(expected_scale), "{path}");
131        }
132        drop(schema);
133    }
134}