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(crate) fn get(ty: &CanisterRole) -> Option<WasmModule> {
39        WASM_REGISTRY.with_borrow(|reg| reg.get(ty).cloned())
40    }
41
42    pub(crate) fn try_get(ty: &CanisterRole) -> Result<WasmModule, Error> {
43        Self::get(ty).ok_or_else(|| WasmRegistryError::WasmNotFound(ty.clone()).into())
44    }
45
46    #[allow(clippy::cast_precision_loss)]
47    pub(crate) fn insert(canister_type: &CanisterRole, wasm: WasmModule) {
48        let wasm_size = wasm.len();
49
50        WASM_REGISTRY.with_borrow_mut(|reg| {
51            reg.insert(canister_type.clone(), wasm);
52        });
53
54        log!(
55            Topic::Wasm,
56            Info,
57            "📄 registry.insert: {} ({:.2} KB)",
58            canister_type,
59            wasm_size as f64 / 1000.0
60        );
61    }
62
63    pub(crate) fn import(wasms: &'static [(CanisterRole, &[u8])]) {
64        for (ty, bytes) in wasms {
65            Self::insert(ty, WasmModule::new(bytes));
66        }
67    }
68}