junobuild_satellite/db/
impls.rs

1use crate::db::types::config::DbConfig;
2use crate::db::types::interface::SetDbConfig;
3use crate::db::types::state::{DbHeapState, Doc, StableKey};
4use crate::SetDoc;
5use candid::Principal;
6use ic_cdk::api::time;
7use ic_stable_structures::storable::Bound;
8use ic_stable_structures::Storable;
9use junobuild_collections::constants::db::DEFAULT_DB_COLLECTIONS;
10use junobuild_collections::types::rules::{Memory, Rule};
11use junobuild_shared::data::version::next_version;
12use junobuild_shared::memory::serializers::{
13    deserialize_from_bytes, serialize_into_bytes, serialize_to_bytes,
14};
15use junobuild_shared::types::state::{Timestamp, UserId, Version};
16use junobuild_shared::types::state::{Timestamped, Versioned};
17use std::borrow::Cow;
18use std::cmp::Ordering;
19use std::collections::{BTreeMap, HashMap};
20
21impl Default for DbHeapState {
22    fn default() -> Self {
23        let now = time();
24
25        DbHeapState {
26            db: HashMap::from(
27                DEFAULT_DB_COLLECTIONS
28                    .map(|(collection, _rules)| (collection.to_owned(), BTreeMap::new())),
29            ),
30            rules: HashMap::from(DEFAULT_DB_COLLECTIONS.map(|(collection, rule)| {
31                (
32                    collection.to_owned(),
33                    Rule {
34                        read: rule.read,
35                        write: rule.write,
36                        memory: Some(rule.memory.unwrap_or(Memory::Stable)),
37                        mutable_permissions: Some(rule.mutable_permissions.unwrap_or(false)),
38                        max_size: rule.max_size,
39                        max_capacity: rule.max_capacity,
40                        max_changes_per_user: rule.max_changes_per_user,
41                        created_at: now,
42                        updated_at: now,
43                        version: rule.version,
44                        rate_config: rule.rate_config,
45                    },
46                )
47            })),
48            config: None,
49        }
50    }
51}
52
53impl Timestamped for Doc {
54    fn created_at(&self) -> Timestamp {
55        self.created_at
56    }
57
58    fn updated_at(&self) -> Timestamp {
59        self.updated_at
60    }
61
62    fn cmp_updated_at(&self, other: &Self) -> Ordering {
63        self.updated_at.cmp(&other.updated_at)
64    }
65
66    fn cmp_created_at(&self, other: &Self) -> Ordering {
67        self.created_at.cmp(&other.created_at)
68    }
69}
70
71impl Storable for Doc {
72    fn to_bytes(&self) -> Cow<'_, [u8]> {
73        serialize_to_bytes(self)
74    }
75
76    fn into_bytes(self) -> Vec<u8> {
77        serialize_into_bytes(&self)
78    }
79
80    fn from_bytes(bytes: Cow<[u8]>) -> Self {
81        deserialize_from_bytes(bytes)
82    }
83
84    const BOUND: Bound = Bound::Unbounded;
85}
86
87impl Storable for StableKey {
88    fn to_bytes(&self) -> Cow<'_, [u8]> {
89        serialize_to_bytes(self)
90    }
91
92    fn into_bytes(self) -> Vec<u8> {
93        serialize_into_bytes(&self)
94    }
95
96    fn from_bytes(bytes: Cow<[u8]>) -> Self {
97        deserialize_from_bytes(bytes)
98    }
99
100    const BOUND: Bound = Bound::Unbounded;
101}
102
103impl Doc {
104    pub fn prepare(caller: Principal, current_doc: &Option<Doc>, user_doc: SetDoc) -> Self {
105        let now = time();
106
107        let created_at: Timestamp = match current_doc {
108            None => now,
109            Some(current_doc) => current_doc.created_at,
110        };
111
112        let version = next_version(current_doc);
113
114        let owner: UserId = match current_doc {
115            None => caller,
116            Some(current_doc) => current_doc.owner,
117        };
118
119        let updated_at: Timestamp = now;
120
121        Doc {
122            owner,
123            data: user_doc.data,
124            description: user_doc.description,
125            created_at,
126            updated_at,
127            version: Some(version),
128        }
129    }
130}
131
132impl Versioned for Doc {
133    fn version(&self) -> Option<Version> {
134        self.version
135    }
136}
137
138impl DbConfig {
139    pub fn prepare(current_config: &Option<DbConfig>, user_config: &SetDbConfig) -> Self {
140        let now = time();
141
142        let created_at: Timestamp = match current_config {
143            None => now,
144            Some(current_doc) => current_doc.created_at.unwrap_or(now),
145        };
146
147        let version = next_version(current_config);
148
149        let updated_at: Timestamp = now;
150
151        DbConfig {
152            max_memory_size: user_config.max_memory_size.clone(),
153            created_at: Some(created_at),
154            updated_at: Some(updated_at),
155            version: Some(version),
156        }
157    }
158}
159
160impl Versioned for DbConfig {
161    fn version(&self) -> Option<Version> {
162        self.version
163    }
164}