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 a stable IC BTreeMap pair that stores:
8/// - primary entity data
9/// - all index data for that entity
10///
11
12#[derive(Clone, Debug, Serialize)]
13pub struct Store {
14    def: Def,
15    ident: &'static str,
16    canister: &'static str,
17    data_memory_id: u8,
18    index_memory_id: u8,
19}
20
21impl Store {
22    #[must_use]
23    pub const fn new(
24        def: Def,
25        ident: &'static str,
26        canister: &'static str,
27        data_memory_id: u8,
28        index_memory_id: u8,
29    ) -> Self {
30        Self {
31            def,
32            ident,
33            canister,
34            data_memory_id,
35            index_memory_id,
36        }
37    }
38
39    #[must_use]
40    pub const fn def(&self) -> &Def {
41        &self.def
42    }
43
44    #[must_use]
45    pub const fn ident(&self) -> &'static str {
46        self.ident
47    }
48
49    #[must_use]
50    pub const fn canister(&self) -> &'static str {
51        self.canister
52    }
53
54    #[must_use]
55    pub const fn data_memory_id(&self) -> u8 {
56        self.data_memory_id
57    }
58
59    #[must_use]
60    pub const fn index_memory_id(&self) -> u8 {
61        self.index_memory_id
62    }
63}
64
65impl MacroNode for Store {
66    fn as_any(&self) -> &dyn std::any::Any {
67        self
68    }
69}
70
71impl ValidateNode for Store {
72    fn validate(&self) -> Result<(), ErrorTree> {
73        let mut errs = ErrorTree::new();
74        let schema = schema_read();
75
76        match schema.cast_node::<Canister>(self.canister()) {
77            Ok(canister) => {
78                // Validate data memory ID
79                validate_memory_id_in_range(
80                    &mut errs,
81                    "data_memory_id",
82                    self.data_memory_id(),
83                    canister.memory_min(),
84                    canister.memory_max(),
85                );
86                validate_memory_id_not_reserved(&mut errs, "data_memory_id", self.data_memory_id());
87
88                // Validate index memory ID
89                validate_memory_id_in_range(
90                    &mut errs,
91                    "index_memory_id",
92                    self.index_memory_id(),
93                    canister.memory_min(),
94                    canister.memory_max(),
95                );
96                validate_memory_id_not_reserved(
97                    &mut errs,
98                    "index_memory_id",
99                    self.index_memory_id(),
100                );
101
102                // Ensure they are not the same
103                if self.data_memory_id() == self.index_memory_id() {
104                    err!(
105                        errs,
106                        "data_memory_id and index_memory_id must differ (both are {})",
107                        self.data_memory_id(),
108                    );
109                }
110            }
111            Err(e) => errs.add(e),
112        }
113
114        errs.result()
115    }
116}
117
118impl VisitableNode for Store {
119    fn route_key(&self) -> String {
120        self.def().path()
121    }
122
123    fn drive<V: Visitor>(&self, v: &mut V) {
124        self.def().accept(v);
125    }
126}