junobuild_satellite/db/
impls.rs

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