Skip to main content

icydb_schema/node/
store.rs

1use crate::node::{validate_memory_id_in_range, validate_memory_id_not_reserved};
2use crate::prelude::*;
3
4///
5/// Store
6///
7/// Schema node describing stable IC BTreeMap memories that store:
8/// - primary entity data
9/// - all index data for that entity
10/// - persisted schema metadata for that store
11///
12
13#[derive(Clone, Debug, Serialize)]
14pub struct Store {
15    def: Def,
16    ident: &'static str,
17    canister: &'static str,
18    data_memory_id: u8,
19    index_memory_id: u8,
20    schema_memory_id: u8,
21}
22
23impl Store {
24    #[must_use]
25    pub const fn new(
26        def: Def,
27        ident: &'static str,
28        canister: &'static str,
29        data_memory_id: u8,
30        index_memory_id: u8,
31        schema_memory_id: u8,
32    ) -> Self {
33        Self {
34            def,
35            ident,
36            canister,
37            data_memory_id,
38            index_memory_id,
39            schema_memory_id,
40        }
41    }
42
43    #[must_use]
44    pub const fn def(&self) -> &Def {
45        &self.def
46    }
47
48    #[must_use]
49    pub const fn ident(&self) -> &'static str {
50        self.ident
51    }
52
53    #[must_use]
54    pub const fn canister(&self) -> &'static str {
55        self.canister
56    }
57
58    #[must_use]
59    pub const fn data_memory_id(&self) -> u8 {
60        self.data_memory_id
61    }
62
63    #[must_use]
64    pub const fn index_memory_id(&self) -> u8 {
65        self.index_memory_id
66    }
67
68    #[must_use]
69    pub const fn schema_memory_id(&self) -> u8 {
70        self.schema_memory_id
71    }
72}
73
74impl MacroNode for Store {
75    fn as_any(&self) -> &dyn std::any::Any {
76        self
77    }
78}
79
80impl ValidateNode for Store {
81    fn validate(&self) -> Result<(), ErrorTree> {
82        let mut errs = ErrorTree::new();
83        let schema = schema_read();
84
85        match schema.cast_node::<Canister>(self.canister()) {
86            Ok(canister) => {
87                // Validate data memory ID
88                validate_memory_id_in_range(
89                    &mut errs,
90                    "data_memory_id",
91                    self.data_memory_id(),
92                    canister.memory_min(),
93                    canister.memory_max(),
94                );
95                validate_memory_id_not_reserved(&mut errs, "data_memory_id", self.data_memory_id());
96
97                // Validate index memory ID
98                validate_memory_id_in_range(
99                    &mut errs,
100                    "index_memory_id",
101                    self.index_memory_id(),
102                    canister.memory_min(),
103                    canister.memory_max(),
104                );
105                validate_memory_id_not_reserved(
106                    &mut errs,
107                    "index_memory_id",
108                    self.index_memory_id(),
109                );
110
111                // Validate schema memory ID
112                validate_memory_id_in_range(
113                    &mut errs,
114                    "schema_memory_id",
115                    self.schema_memory_id(),
116                    canister.memory_min(),
117                    canister.memory_max(),
118                );
119                validate_memory_id_not_reserved(
120                    &mut errs,
121                    "schema_memory_id",
122                    self.schema_memory_id(),
123                );
124
125                // Ensure the per-store memories are distinct.
126                if self.data_memory_id() == self.index_memory_id() {
127                    err!(
128                        errs,
129                        "data_memory_id and index_memory_id must differ (both are {})",
130                        self.data_memory_id(),
131                    );
132                }
133                if self.data_memory_id() == self.schema_memory_id() {
134                    err!(
135                        errs,
136                        "data_memory_id and schema_memory_id must differ (both are {})",
137                        self.data_memory_id(),
138                    );
139                }
140                if self.index_memory_id() == self.schema_memory_id() {
141                    err!(
142                        errs,
143                        "index_memory_id and schema_memory_id must differ (both are {})",
144                        self.index_memory_id(),
145                    );
146                }
147            }
148            Err(e) => errs.add(e),
149        }
150
151        errs.result()
152    }
153}
154
155impl VisitableNode for Store {
156    fn route_key(&self) -> String {
157        self.def().path()
158    }
159
160    fn drive<V: Visitor>(&self, v: &mut V) {
161        self.def().accept(v);
162    }
163}