icydb_schema/node/
schema.rs1use crate::{Error, prelude::*};
2use std::time::{SystemTime, UNIX_EPOCH};
3use std::{any::Any, collections::BTreeMap};
4
5#[remain::sorted]
10#[derive(Clone, Debug, Serialize)]
11pub enum SchemaNode {
12 Canister(Canister),
13 Entity(Entity),
14 Enum(Enum),
15 List(List),
16 Map(Map),
17 Newtype(Newtype),
18 Record(Record),
19 Sanitizer(Sanitizer),
20 Set(Set),
21 Store(Store),
22 Tuple(Tuple),
23 Validator(Validator),
24}
25
26impl SchemaNode {
27 const fn def(&self) -> &Def {
28 match self {
29 Self::Canister(n) => n.def(),
30 Self::Entity(n) => n.def(),
31 Self::Enum(n) => n.def(),
32 Self::List(n) => n.def(),
33 Self::Map(n) => n.def(),
34 Self::Newtype(n) => n.def(),
35 Self::Record(n) => n.def(),
36 Self::Sanitizer(n) => n.def(),
37 Self::Set(n) => n.def(),
38 Self::Store(n) => n.def(),
39 Self::Tuple(n) => n.def(),
40 Self::Validator(n) => n.def(),
41 }
42 }
43}
44
45impl MacroNode for SchemaNode {
46 fn as_any(&self) -> &dyn Any {
47 match self {
48 Self::Canister(n) => n.as_any(),
49 Self::Entity(n) => n.as_any(),
50 Self::Enum(n) => n.as_any(),
51 Self::List(n) => n.as_any(),
52 Self::Map(n) => n.as_any(),
53 Self::Newtype(n) => n.as_any(),
54 Self::Record(n) => n.as_any(),
55 Self::Sanitizer(n) => n.as_any(),
56 Self::Set(n) => n.as_any(),
57 Self::Store(n) => n.as_any(),
58 Self::Tuple(n) => n.as_any(),
59 Self::Validator(n) => n.as_any(),
60 }
61 }
62}
63
64impl ValidateNode for SchemaNode {}
65
66impl VisitableNode for SchemaNode {
67 fn drive<V: Visitor>(&self, v: &mut V) {
68 match self {
69 Self::Canister(n) => n.accept(v),
70 Self::Entity(n) => n.accept(v),
71 Self::Enum(n) => n.accept(v),
72 Self::List(n) => n.accept(v),
73 Self::Map(n) => n.accept(v),
74 Self::Newtype(n) => n.accept(v),
75 Self::Record(n) => n.accept(v),
76 Self::Sanitizer(n) => n.accept(v),
77 Self::Set(n) => n.accept(v),
78 Self::Store(n) => n.accept(v),
79 Self::Tuple(n) => n.accept(v),
80 Self::Validator(n) => n.accept(v),
81 }
82 }
83}
84
85#[derive(Clone, Debug, Serialize)]
90pub struct Schema {
91 nodes: BTreeMap<String, SchemaNode>,
92 hash: &'static str,
93 timestamp: u64,
94}
95
96impl Schema {
97 #[must_use]
98 pub fn new() -> Self {
99 Self {
100 nodes: BTreeMap::new(),
101 hash: "",
102 timestamp: now_secs(),
103 }
104 }
105
106 pub fn insert_node(&mut self, node: SchemaNode) {
108 self.nodes.insert(node.def().path(), node);
109 }
110
111 #[must_use]
113 pub fn get_node<'a>(&'a self, path: &str) -> Option<&'a SchemaNode> {
114 self.nodes.get(path)
115 }
116
117 pub fn try_get_node<'a>(&'a self, path: &str) -> Result<&'a SchemaNode, Error> {
119 let node = self
120 .get_node(path)
121 .ok_or_else(|| NodeError::PathNotFound(path.to_string()))?;
122
123 Ok(node)
124 }
125
126 pub fn cast_node<'a, T: 'static>(&'a self, path: &str) -> Result<&'a T, Error> {
128 let node = self.try_get_node(path)?;
129
130 node.as_any()
131 .downcast_ref::<T>()
132 .ok_or_else(|| NodeError::IncorrectNodeType(path.to_string()).into())
133 }
134
135 pub(crate) fn check_node_as<T: 'static>(&self, path: &str) -> Result<(), Error> {
137 self.cast_node::<T>(path).map(|_| ())
138 }
139
140 pub fn get_nodes<T: 'static>(&self) -> impl Iterator<Item = (&str, &T)> {
142 self.nodes
143 .iter()
144 .filter_map(|(key, node)| node.as_any().downcast_ref::<T>().map(|n| (key.as_str(), n)))
145 }
146
147 pub fn filter_nodes<'a, T: 'static>(
150 &'a self,
151 predicate: impl Fn(&T) -> bool + 'a,
152 ) -> impl Iterator<Item = (&'a str, &'a T)> + 'a {
153 self.nodes.iter().filter_map(move |(key, node)| {
154 node.as_any()
155 .downcast_ref::<T>()
156 .filter(|target| predicate(target))
157 .map(|target| (key.as_str(), target))
158 })
159 }
160
161 #[must_use]
163 pub const fn nodes(&self) -> &BTreeMap<String, SchemaNode> {
164 &self.nodes
165 }
166
167 #[must_use]
169 pub const fn hash(&self) -> &'static str {
170 self.hash
171 }
172
173 #[must_use]
175 pub const fn timestamp(&self) -> u64 {
176 self.timestamp
177 }
178}
179
180impl Default for Schema {
181 fn default() -> Self {
182 Self::new()
183 }
184}
185
186fn now_secs() -> u64 {
187 SystemTime::now()
188 .duration_since(UNIX_EPOCH)
189 .map_or(0, |duration| duration.as_secs())
190}
191
192impl ValidateNode for Schema {}
193
194impl VisitableNode for Schema {
195 fn drive<V: Visitor>(&self, v: &mut V) {
196 for node in self.nodes.values() {
197 node.accept(v);
198 }
199 }
200}