junobuild_collections/
impls.rs

1use crate::assert::collection::is_system_collection;
2use crate::errors::JUNO_COLLECTIONS_ERROR_RESERVED_COLLECTION;
3use crate::types::core::CollectionKey;
4use crate::types::interface::SetRule;
5use crate::types::rules::{Memory, Rule};
6use ic_cdk::api::time;
7use junobuild_shared::data::version::next_version;
8use junobuild_shared::types::state::{Timestamp, Version, Versioned};
9
10impl Rule {
11    pub fn mem(&self) -> Memory {
12        self.memory.clone().unwrap_or_default()
13    }
14
15    pub fn prepare(
16        collection: &CollectionKey,
17        current_rule: &Option<&Rule>,
18        user_rule: &SetRule,
19    ) -> Result<Self, String> {
20        if is_system_collection(collection) {
21            return Self::prepare_sys_rule(collection, current_rule, user_rule);
22        }
23
24        Ok(Self::prepare_user_rule(current_rule, user_rule))
25    }
26
27    fn initialize_common_fields(current_rule: &Option<&Rule>) -> (Timestamp, Version, Timestamp) {
28        let now = time();
29
30        let created_at: Timestamp = match current_rule {
31            None => now,
32            Some(current_rule) => current_rule.created_at,
33        };
34
35        let version = next_version(current_rule);
36
37        let updated_at: Timestamp = now;
38
39        (created_at, version, updated_at)
40    }
41
42    fn prepare_user_rule(current_rule: &Option<&Rule>, user_rule: &SetRule) -> Self {
43        let (created_at, version, updated_at) = Self::initialize_common_fields(current_rule);
44
45        Rule {
46            read: user_rule.read.clone(),
47            write: user_rule.write.clone(),
48            memory: Some(user_rule.clone().memory.unwrap_or(Memory::Stable)),
49            mutable_permissions: Some(user_rule.mutable_permissions.unwrap_or(true)),
50            max_size: user_rule.max_size,
51            max_capacity: user_rule.max_capacity,
52            max_changes_per_user: user_rule.max_changes_per_user,
53            created_at,
54            updated_at,
55            version: Some(version),
56            rate_config: user_rule.rate_config.clone(),
57        }
58    }
59
60    fn prepare_sys_rule(
61        collection: &CollectionKey,
62        current_rule: &Option<&Rule>,
63        user_rule: &SetRule,
64    ) -> Result<Rule, String> {
65        match current_rule {
66            None => Err(format!(
67                "{JUNO_COLLECTIONS_ERROR_RESERVED_COLLECTION} ({collection})"
68            )),
69            Some(current_rule) => {
70                let (created_at, version, updated_at) =
71                    Self::initialize_common_fields(&Some(current_rule));
72
73                let rule = Rule {
74                    read: current_rule.read.clone(),
75                    write: current_rule.write.clone(),
76                    memory: current_rule.memory.clone(),
77                    mutable_permissions: current_rule.mutable_permissions,
78                    max_size: current_rule.max_size,
79                    max_capacity: current_rule.max_capacity,
80                    max_changes_per_user: current_rule.max_changes_per_user,
81                    created_at,
82                    updated_at,
83                    version: Some(version),
84                    rate_config: user_rule.rate_config.clone(),
85                };
86
87                Ok(rule)
88            }
89        }
90    }
91
92    pub fn switch_rule_memory(current_rule: &Rule) -> Rule {
93        let (created_at, version, updated_at) = Self::initialize_common_fields(&Some(current_rule));
94
95        Rule {
96            memory: Some(match current_rule.mem() {
97                Memory::Heap => Memory::Stable,
98                Memory::Stable => Memory::Heap,
99            }),
100            created_at,
101            updated_at,
102            version: Some(version),
103            ..current_rule.clone()
104        }
105    }
106}
107
108impl Versioned for &Rule {
109    fn version(&self) -> Option<Version> {
110        self.version
111    }
112}