Skip to main content

canic_core/ids/template/
mod.rs

1use crate::memory::impl_storable_bounded;
2use candid::{
3    CandidType,
4    types::{Serializer, Type},
5};
6use serde::{Deserialize, Serialize};
7use std::{borrow::Borrow, borrow::Cow, fmt};
8
9///
10/// TemplateId
11///
12
13#[derive(
14    CandidType, Clone, Debug, Eq, Ord, PartialOrd, Deserialize, Serialize, PartialEq, Hash,
15)]
16#[serde(transparent)]
17pub struct TemplateId(pub Cow<'static, str>);
18
19impl TemplateId {
20    #[must_use]
21    pub const fn new(s: &'static str) -> Self {
22        Self(Cow::Borrowed(s))
23    }
24
25    #[must_use]
26    pub const fn owned(s: String) -> Self {
27        Self(Cow::Owned(s))
28    }
29
30    #[must_use]
31    pub fn as_str(&self) -> &str {
32        &self.0
33    }
34}
35
36impl From<&'static str> for TemplateId {
37    fn from(value: &'static str) -> Self {
38        Self::new(value)
39    }
40}
41
42impl From<String> for TemplateId {
43    fn from(value: String) -> Self {
44        Self::owned(value)
45    }
46}
47
48impl From<&String> for TemplateId {
49    fn from(value: &String) -> Self {
50        Self::owned(value.clone())
51    }
52}
53
54impl Borrow<str> for TemplateId {
55    fn borrow(&self) -> &str {
56        self.as_str()
57    }
58}
59
60impl fmt::Display for TemplateId {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        f.write_str(self.as_str())
63    }
64}
65
66impl_storable_bounded!(TemplateId, 160, false);
67
68///
69/// TemplateVersion
70///
71
72#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
73#[serde(transparent)]
74pub struct TemplateVersion(pub Cow<'static, str>);
75
76impl TemplateVersion {
77    #[must_use]
78    pub const fn new(s: &'static str) -> Self {
79        Self(Cow::Borrowed(s))
80    }
81
82    #[must_use]
83    pub const fn owned(s: String) -> Self {
84        Self(Cow::Owned(s))
85    }
86
87    #[must_use]
88    pub fn as_str(&self) -> &str {
89        &self.0
90    }
91}
92
93impl From<&'static str> for TemplateVersion {
94    fn from(value: &'static str) -> Self {
95        Self::new(value)
96    }
97}
98
99impl From<String> for TemplateVersion {
100    fn from(value: String) -> Self {
101        Self::owned(value)
102    }
103}
104
105impl From<&String> for TemplateVersion {
106    fn from(value: &String) -> Self {
107        Self::owned(value.clone())
108    }
109}
110
111impl Borrow<str> for TemplateVersion {
112    fn borrow(&self) -> &str {
113        self.as_str()
114    }
115}
116
117impl fmt::Display for TemplateVersion {
118    // Render the semantic version exactly as the stored string value.
119    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120        f.write_str(self.as_str())
121    }
122}
123
124impl CandidType for TemplateVersion {
125    // Expose `TemplateVersion` as plain Candid `text` on public canister boundaries.
126    fn _ty() -> Type {
127        String::ty()
128    }
129
130    // Serialize the wrapped semantic version using the same Candid encoding as `String`.
131    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
132    where
133        S: Serializer,
134    {
135        self.as_str().idl_serialize(serializer)
136    }
137}
138
139impl_storable_bounded!(TemplateVersion, 64, false);
140
141///
142/// WasmStoreBinding
143///
144
145#[derive(
146    CandidType, Clone, Debug, Eq, Ord, PartialOrd, Deserialize, Serialize, PartialEq, Hash,
147)]
148#[serde(transparent)]
149pub struct WasmStoreBinding(pub Cow<'static, str>);
150
151impl WasmStoreBinding {
152    #[must_use]
153    pub const fn new(s: &'static str) -> Self {
154        Self(Cow::Borrowed(s))
155    }
156
157    #[must_use]
158    pub const fn owned(s: String) -> Self {
159        Self(Cow::Owned(s))
160    }
161
162    #[must_use]
163    pub fn as_str(&self) -> &str {
164        &self.0
165    }
166}
167
168impl From<&'static str> for WasmStoreBinding {
169    fn from(value: &'static str) -> Self {
170        Self::new(value)
171    }
172}
173
174impl From<String> for WasmStoreBinding {
175    fn from(value: String) -> Self {
176        Self::owned(value)
177    }
178}
179
180impl From<&String> for WasmStoreBinding {
181    fn from(value: &String) -> Self {
182        Self::owned(value.clone())
183    }
184}
185
186impl Borrow<str> for WasmStoreBinding {
187    fn borrow(&self) -> &str {
188        self.as_str()
189    }
190}
191
192impl fmt::Display for WasmStoreBinding {
193    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194        f.write_str(self.as_str())
195    }
196}
197
198impl_storable_bounded!(WasmStoreBinding, 64, false);
199
200///
201/// TemplateReleaseKey
202///
203
204#[derive(
205    CandidType, Clone, Debug, Eq, Ord, PartialOrd, Deserialize, Serialize, PartialEq, Hash,
206)]
207pub struct TemplateReleaseKey {
208    pub template_id: TemplateId,
209    pub version: TemplateVersion,
210}
211
212impl TemplateReleaseKey {
213    #[must_use]
214    pub const fn new(template_id: TemplateId, version: TemplateVersion) -> Self {
215        Self {
216            template_id,
217            version,
218        }
219    }
220}
221
222impl fmt::Display for TemplateReleaseKey {
223    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224        write!(f, "{}@{}", self.template_id, self.version)
225    }
226}
227
228impl_storable_bounded!(TemplateReleaseKey, 256, false);
229
230///
231/// TemplateChunkKey
232///
233
234#[derive(
235    CandidType, Clone, Debug, Eq, Ord, PartialOrd, Deserialize, Serialize, PartialEq, Hash,
236)]
237pub struct TemplateChunkKey {
238    pub release: TemplateReleaseKey,
239    pub chunk_index: u32,
240}
241
242impl TemplateChunkKey {
243    #[must_use]
244    pub const fn new(release: TemplateReleaseKey, chunk_index: u32) -> Self {
245        Self {
246            release,
247            chunk_index,
248        }
249    }
250}
251
252impl fmt::Display for TemplateChunkKey {
253    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254        write!(f, "{}#{}", self.release, self.chunk_index)
255    }
256}
257
258impl_storable_bounded!(TemplateChunkKey, 320, false);
259
260#[cfg(test)]
261mod tests {
262    use super::TemplateVersion;
263    use candid::{CandidType, Encode};
264
265    // Keep the public wire format aligned with plain Candid `text`.
266    #[test]
267    fn template_version_uses_string_candid_encoding() {
268        let version = TemplateVersion::new("0.18.5");
269
270        assert_eq!(TemplateVersion::ty(), String::ty());
271        assert_eq!(Encode!(&version).unwrap(), Encode!(&"0.18.5").unwrap());
272    }
273}
274
275///
276/// TemplateChunkingMode
277///
278
279#[derive(
280    CandidType, Clone, Copy, Debug, Eq, Ord, PartialOrd, Deserialize, Serialize, PartialEq,
281)]
282pub enum TemplateChunkingMode {
283    Inline,
284    Chunked,
285}
286
287///
288/// WasmStoreGcMode
289///
290
291#[derive(
292    CandidType, Clone, Copy, Debug, Default, Eq, Ord, PartialOrd, Deserialize, Serialize, PartialEq,
293)]
294pub enum WasmStoreGcMode {
295    #[default]
296    Normal,
297    Prepared,
298    InProgress,
299    Complete,
300}
301
302///
303/// WasmStoreGcStatus
304///
305
306#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
307pub struct WasmStoreGcStatus {
308    pub mode: WasmStoreGcMode,
309    pub changed_at: u64,
310    pub prepared_at: Option<u64>,
311    pub started_at: Option<u64>,
312    pub completed_at: Option<u64>,
313    pub runs_completed: u32,
314}
315
316///
317/// TemplateManifestState
318///
319
320#[derive(
321    CandidType, Clone, Copy, Debug, Eq, Ord, PartialOrd, Deserialize, Serialize, PartialEq,
322)]
323pub enum TemplateManifestState {
324    Staged,
325    Approved,
326    Blocked,
327    Deprecated,
328}