canic_core/model/wasm/
wasm_registry.rs

1use crate::{Error, ids::CanisterRole, log, log::Topic, model::ModelError, types::WasmModule};
2use std::{cell::RefCell, collections::HashMap};
3use thiserror::Error as ThisError;
4
5//
6// WASM_REGISTRY
7//
8
9thread_local! {
10    pub static WASM_REGISTRY: RefCell<HashMap<CanisterRole, WasmModule>> = RefCell::new(HashMap::new());
11}
12
13///
14/// WasmRegistryError
15///
16
17#[derive(Debug, ThisError)]
18pub enum WasmRegistryError {
19    #[error("wasm '{0}' not found")]
20    WasmNotFound(CanisterRole),
21}
22
23impl From<WasmRegistryError> for Error {
24    fn from(err: WasmRegistryError) -> Self {
25        ModelError::from(err).into()
26    }
27}
28
29///
30/// WasmRegistry
31///
32
33#[derive(Debug, Default)]
34pub struct WasmRegistry {}
35
36impl WasmRegistry {
37    #[must_use]
38    pub fn new() -> Self {
39        Self::default()
40    }
41
42    #[must_use]
43    pub fn get(ty: &CanisterRole) -> Option<WasmModule> {
44        WASM_REGISTRY.with_borrow(|reg| reg.get(ty).cloned())
45    }
46
47    pub fn try_get(ty: &CanisterRole) -> Result<WasmModule, Error> {
48        Self::get(ty).ok_or_else(|| WasmRegistryError::WasmNotFound(ty.clone()).into())
49    }
50
51    #[allow(clippy::cast_precision_loss)]
52    pub fn insert(canister_type: &CanisterRole, wasm: WasmModule) {
53        let wasm_size = wasm.len();
54
55        WASM_REGISTRY.with_borrow_mut(|reg| {
56            reg.insert(canister_type.clone(), wasm);
57        });
58
59        log!(
60            Topic::Wasm,
61            Info,
62            "📄 registry.insert: {} ({:.2} KB)",
63            canister_type,
64            wasm_size as f64 / 1000.0
65        );
66    }
67
68    pub fn import(wasms: &'static [(CanisterRole, &[u8])]) {
69        for (ty, bytes) in wasms {
70            Self::insert(ty, WasmModule::new(bytes));
71        }
72    }
73}